xref: /petsc/src/dm/impls/plex/plexcreate.c (revision d5b43468fb8780a8feea140ccd6fa3e6a50411cc)
1552f7358SJed Brown #define PETSCDM_DLL
2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I   "petscdmplex.h"   I*/
3e8f14785SLisandro Dalcin #include <petsc/private/hashseti.h>   /*I   "petscdmplex.h"   I*/
40c312b8eSJed Brown #include <petscsf.h>
54663dae6SJed Brown #include <petscdmplextransform.h>
6b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h>
7b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h>
8552f7358SJed Brown 
9b09969d6SVaclav Hapla PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList;
1058cd63d5SVaclav Hapla 
119318fe57SMatthew G. Knepley /* External function declarations here */
129318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm);
139318fe57SMatthew G. Knepley 
14e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */
15d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout)
16d71ae5a4SJacob Faibussowitsch {
174fb89dddSMatthew G. Knepley   const PetscReal         *maxCell, *Lstart, *L;
186858538eSMatthew G. Knepley   PetscBool                dist;
196bc1bd01Sksagiyam   DMPlexReorderDefaultFlag reorder;
20e600fa54SMatthew G. Knepley 
21e600fa54SMatthew G. Knepley   PetscFunctionBegin;
22e600fa54SMatthew G. Knepley   if (copyPeriodicity) {
234fb89dddSMatthew G. Knepley     PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L));
244fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L));
25e600fa54SMatthew G. Knepley   }
269566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dmin, &dist));
279566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeSetDefault(dmout, dist));
286bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dmin, &reorder));
296bc1bd01Sksagiyam   PetscCall(DMPlexReorderSetDefault(dmout, reorder));
30e600fa54SMatthew G. Knepley   ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation;
311baa6e33SBarry Smith   if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0));
32e600fa54SMatthew G. Knepley   PetscFunctionReturn(0);
33e600fa54SMatthew G. Knepley }
34e600fa54SMatthew G. Knepley 
359318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm
369318fe57SMatthew G. Knepley    - Share the DM_Plex structure
379318fe57SMatthew G. Knepley    - Share the coordinates
389318fe57SMatthew G. Knepley    - Share the SF
399318fe57SMatthew G. Knepley */
40d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm)
41d71ae5a4SJacob Faibussowitsch {
429318fe57SMatthew G. Knepley   PetscSF          sf;
439318fe57SMatthew G. Knepley   DM               dmNew = *ndm, coordDM, coarseDM;
449318fe57SMatthew G. Knepley   Vec              coords;
454fb89dddSMatthew G. Knepley   const PetscReal *maxCell, *Lstart, *L;
469318fe57SMatthew G. Knepley   PetscInt         dim, cdim;
479318fe57SMatthew G. Knepley 
489318fe57SMatthew G. Knepley   PetscFunctionBegin;
499318fe57SMatthew G. Knepley   if (dm == dmNew) {
509566063dSJacob Faibussowitsch     PetscCall(DMDestroy(ndm));
519318fe57SMatthew G. Knepley     PetscFunctionReturn(0);
529318fe57SMatthew G. Knepley   }
539318fe57SMatthew G. Knepley   dm->setupcalled = dmNew->setupcalled;
549566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dmNew, &dim));
559566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
569566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmNew, &cdim));
579566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
589566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmNew, &sf));
599566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sf));
609566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmNew, &coordDM));
619566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmNew, &coords));
629566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dm, coordDM));
639566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coords));
646858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM));
656858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords));
666858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dm, coordDM));
676858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dm, coords));
689318fe57SMatthew G. Knepley   /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */
696858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&dm->coordinates[0].field));
706858538eSMatthew G. Knepley   dm->coordinates[0].field            = dmNew->coordinates[0].field;
7161a622f3SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc;
724fb89dddSMatthew G. Knepley   PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L));
734fb89dddSMatthew G. Knepley   PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
749566063dSJacob Faibussowitsch   PetscCall(DMDestroy_Plex(dm));
759566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
769318fe57SMatthew G. Knepley   dm->data = dmNew->data;
779318fe57SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->refct++;
789566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(dm));
799566063dSJacob Faibussowitsch   PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL));
809566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmNew, &coarseDM));
819566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dm, coarseDM));
829566063dSJacob Faibussowitsch   PetscCall(DMDestroy(ndm));
839318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
849318fe57SMatthew G. Knepley }
859318fe57SMatthew G. Knepley 
869318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew
879318fe57SMatthew G. Knepley    - Swap the DM_Plex structure
889318fe57SMatthew G. Knepley    - Swap the coordinates
899318fe57SMatthew G. Knepley    - Swap the point PetscSF
909318fe57SMatthew G. Knepley */
91d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB)
92d71ae5a4SJacob Faibussowitsch {
939318fe57SMatthew G. Knepley   DM          coordDMA, coordDMB;
949318fe57SMatthew G. Knepley   Vec         coordsA, coordsB;
959318fe57SMatthew G. Knepley   PetscSF     sfA, sfB;
969318fe57SMatthew G. Knepley   DMField     fieldTmp;
979318fe57SMatthew G. Knepley   void       *tmp;
989318fe57SMatthew G. Knepley   DMLabelLink listTmp;
999318fe57SMatthew G. Knepley   DMLabel     depthTmp;
1009318fe57SMatthew G. Knepley   PetscInt    tmpI;
1019318fe57SMatthew G. Knepley 
1029318fe57SMatthew G. Knepley   PetscFunctionBegin;
1039318fe57SMatthew G. Knepley   if (dmA == dmB) PetscFunctionReturn(0);
1049566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmA, &sfA));
1059566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmB, &sfB));
1069566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sfA));
1079566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmA, sfB));
1089566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmB, sfA));
1099566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)sfA));
1109318fe57SMatthew G. Knepley 
1119566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmA, &coordDMA));
1129566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmB, &coordDMB));
1139566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordDMA));
1149566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmA, coordDMB));
1159566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmB, coordDMA));
1169566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
1179318fe57SMatthew G. Knepley 
1189566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordsA));
1199566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmB, &coordsB));
1209566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordsA));
1219566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmA, coordsB));
1229566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordsA));
1239566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordsA));
1249318fe57SMatthew G. Knepley 
1256858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA));
1266858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB));
1276858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordDMA));
1286858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmA, coordDMB));
1296858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmB, coordDMA));
1306858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
1316858538eSMatthew G. Knepley 
1326858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA));
1336858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB));
1346858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordsA));
1356858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB));
1366858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA));
1376858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordsA));
1386858538eSMatthew G. Knepley 
1396858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[0].field;
1406858538eSMatthew G. Knepley   dmA->coordinates[0].field = dmB->coordinates[0].field;
1416858538eSMatthew G. Knepley   dmB->coordinates[0].field = fieldTmp;
1426858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[1].field;
1436858538eSMatthew G. Knepley   dmA->coordinates[1].field = dmB->coordinates[1].field;
1446858538eSMatthew G. Knepley   dmB->coordinates[1].field = fieldTmp;
1459318fe57SMatthew G. Knepley   tmp                       = dmA->data;
1469318fe57SMatthew G. Knepley   dmA->data                 = dmB->data;
1479318fe57SMatthew G. Knepley   dmB->data                 = tmp;
1489318fe57SMatthew G. Knepley   listTmp                   = dmA->labels;
1499318fe57SMatthew G. Knepley   dmA->labels               = dmB->labels;
1509318fe57SMatthew G. Knepley   dmB->labels               = listTmp;
1519318fe57SMatthew G. Knepley   depthTmp                  = dmA->depthLabel;
1529318fe57SMatthew G. Knepley   dmA->depthLabel           = dmB->depthLabel;
1539318fe57SMatthew G. Knepley   dmB->depthLabel           = depthTmp;
1549318fe57SMatthew G. Knepley   depthTmp                  = dmA->celltypeLabel;
1559318fe57SMatthew G. Knepley   dmA->celltypeLabel        = dmB->celltypeLabel;
1569318fe57SMatthew G. Knepley   dmB->celltypeLabel        = depthTmp;
1579318fe57SMatthew G. Knepley   tmpI                      = dmA->levelup;
1589318fe57SMatthew G. Knepley   dmA->levelup              = dmB->levelup;
1599318fe57SMatthew G. Knepley   dmB->levelup              = tmpI;
1609318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
1619318fe57SMatthew G. Knepley }
1629318fe57SMatthew G. Knepley 
163d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm)
164d71ae5a4SJacob Faibussowitsch {
1659318fe57SMatthew G. Knepley   DM idm;
1669318fe57SMatthew G. Knepley 
1679318fe57SMatthew G. Knepley   PetscFunctionBegin;
1689566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolate(dm, &idm));
1699566063dSJacob Faibussowitsch   PetscCall(DMPlexCopyCoordinates(dm, idm));
17069d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &idm));
1719318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
1729318fe57SMatthew G. Knepley }
1739318fe57SMatthew G. Knepley 
1749318fe57SMatthew G. Knepley /*@C
1759318fe57SMatthew G. Knepley   DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates
1769318fe57SMatthew G. Knepley 
1779318fe57SMatthew G. Knepley   Collective
1789318fe57SMatthew G. Knepley 
1799318fe57SMatthew G. Knepley   Input Parameters:
1809318fe57SMatthew G. Knepley + DM        - The DM
1814f9ab2b4SJed Brown . degree    - The degree of the finite element or PETSC_DECIDE
1829318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface
1839318fe57SMatthew G. Knepley 
1849318fe57SMatthew G. Knepley   Level: advanced
1859318fe57SMatthew G. Knepley 
186db781477SPatrick Sanan .seealso: `PetscFECreateLagrange()`, `DMGetCoordinateDM()`
1879318fe57SMatthew G. Knepley @*/
188d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscPointFunc coordFunc)
189d71ae5a4SJacob Faibussowitsch {
1909318fe57SMatthew G. Knepley   DM_Plex     *mesh = (DM_Plex *)dm->data;
1919318fe57SMatthew G. Knepley   DM           cdm;
1929318fe57SMatthew G. Knepley   PetscDS      cds;
1939318fe57SMatthew G. Knepley   PetscFE      fe;
1949318fe57SMatthew G. Knepley   PetscClassId id;
1959318fe57SMatthew G. Knepley 
1969318fe57SMatthew G. Knepley   PetscFunctionBegin;
1979566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
1989566063dSJacob Faibussowitsch   PetscCall(DMGetDS(cdm, &cds));
1999566063dSJacob Faibussowitsch   PetscCall(PetscDSGetDiscretization(cds, 0, (PetscObject *)&fe));
2009566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetClassId((PetscObject)fe, &id));
2019318fe57SMatthew G. Knepley   if (id != PETSCFE_CLASSID) {
2029318fe57SMatthew G. Knepley     PetscBool simplex;
2039318fe57SMatthew G. Knepley     PetscInt  dim, dE, qorder;
2049318fe57SMatthew G. Knepley 
2059566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
2069566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDim(dm, &dE));
2079318fe57SMatthew G. Knepley     qorder = degree;
208d0609cedSBarry Smith     PetscObjectOptionsBegin((PetscObject)cdm);
2099566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBoundedInt("-coord_dm_default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0));
210d0609cedSBarry Smith     PetscOptionsEnd();
2114f9ab2b4SJed Brown     if (degree == PETSC_DECIDE) fe = NULL;
2124f9ab2b4SJed Brown     else {
2138c4475acSStefano Zampini       PetscCall(DMPlexIsSimplex(dm, &simplex));
2149566063dSJacob Faibussowitsch       PetscCall(PetscFECreateLagrange(PETSC_COMM_SELF, dim, dE, simplex, degree, qorder, &fe));
2154f9ab2b4SJed Brown     }
2169566063dSJacob Faibussowitsch     PetscCall(DMProjectCoordinates(dm, fe));
2179566063dSJacob Faibussowitsch     PetscCall(PetscFEDestroy(&fe));
2189318fe57SMatthew G. Knepley   }
2199318fe57SMatthew G. Knepley   mesh->coordFunc = coordFunc;
2209318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
2219318fe57SMatthew G. Knepley }
2229318fe57SMatthew G. Knepley 
2231df5d5c5SMatthew G. Knepley /*@
2241df5d5c5SMatthew G. Knepley   DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement.
2251df5d5c5SMatthew G. Knepley 
226d083f849SBarry Smith   Collective
2271df5d5c5SMatthew G. Knepley 
2281df5d5c5SMatthew G. Knepley   Input Parameters:
2291df5d5c5SMatthew G. Knepley + comm - The communicator for the DM object
2301df5d5c5SMatthew G. Knepley . dim - The spatial dimension
2311df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells
2321df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces)
2331df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell
2341df5d5c5SMatthew G. Knepley 
2351df5d5c5SMatthew G. Knepley   Output Parameter:
2361df5d5c5SMatthew G. Knepley . dm - The DM object
2371df5d5c5SMatthew G. Knepley 
2381df5d5c5SMatthew G. Knepley   Level: beginner
2391df5d5c5SMatthew G. Knepley 
240db781477SPatrick Sanan .seealso: `DMSetType()`, `DMCreate()`
2411df5d5c5SMatthew G. Knepley @*/
242d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm)
243d71ae5a4SJacob Faibussowitsch {
2441df5d5c5SMatthew G. Knepley   DM          dm;
2451df5d5c5SMatthew G. Knepley   PetscMPIInt rank;
2461df5d5c5SMatthew G. Knepley 
2471df5d5c5SMatthew G. Knepley   PetscFunctionBegin;
2489566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, &dm));
2499566063dSJacob Faibussowitsch   PetscCall(DMSetType(dm, DMPLEX));
2509566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
2519566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
252ce78fa2fSMatthew G. Knepley   switch (dim) {
253ce78fa2fSMatthew G. Knepley   case 2:
2549566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular"));
2559566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral"));
256ce78fa2fSMatthew G. Knepley     break;
257ce78fa2fSMatthew G. Knepley   case 3:
2589566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral"));
2599566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral"));
260ce78fa2fSMatthew G. Knepley     break;
261d71ae5a4SJacob Faibussowitsch   default:
262d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
263ce78fa2fSMatthew G. Knepley   }
2641df5d5c5SMatthew G. Knepley   if (rank) {
2651df5d5c5SMatthew G. Knepley     PetscInt numPoints[2] = {0, 0};
2669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL));
2671df5d5c5SMatthew G. Knepley   } else {
2681df5d5c5SMatthew G. Knepley     switch (dim) {
2691df5d5c5SMatthew G. Knepley     case 2:
2701df5d5c5SMatthew G. Knepley       if (simplex) {
2711df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {4, 2};
2721df5d5c5SMatthew G. Knepley         PetscInt    coneSize[6]         = {3, 3, 0, 0, 0, 0};
2731df5d5c5SMatthew G. Knepley         PetscInt    cones[6]            = {2, 3, 4, 5, 4, 3};
2741df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
2751df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[8]     = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5};
2761df5d5c5SMatthew G. Knepley 
2779566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2781df5d5c5SMatthew G. Knepley       } else {
2791df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {6, 2};
2801df5d5c5SMatthew G. Knepley         PetscInt    coneSize[8]         = {4, 4, 0, 0, 0, 0, 0, 0};
2811df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {2, 3, 4, 5, 3, 6, 7, 4};
2821df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2831df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[12]    = {-1.0, -0.5, 0.0, -0.5, 0.0, 0.5, -1.0, 0.5, 1.0, -0.5, 1.0, 0.5};
2841df5d5c5SMatthew G. Knepley 
2859566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2861df5d5c5SMatthew G. Knepley       }
2871df5d5c5SMatthew G. Knepley       break;
2881df5d5c5SMatthew G. Knepley     case 3:
2891df5d5c5SMatthew G. Knepley       if (simplex) {
2901df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {5, 2};
2911df5d5c5SMatthew G. Knepley         PetscInt    coneSize[7]         = {4, 4, 0, 0, 0, 0, 0};
2921df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {4, 3, 5, 2, 5, 3, 4, 6};
2931df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2941df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[15]    = {-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0};
2951df5d5c5SMatthew G. Knepley 
2969566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
2971df5d5c5SMatthew G. Knepley       } else {
2981df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]         = {12, 2};
2991df5d5c5SMatthew G. Knepley         PetscInt    coneSize[14]         = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3001df5d5c5SMatthew G. Knepley         PetscInt    cones[16]            = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8};
3011df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3029371c9d4SSatish Balay         PetscScalar vertexCoords[36]     = {-1.0, -0.5, -0.5, -1.0, 0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, -0.5, -1.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, -1.0, 0.5, 0.5, 1.0, 0.5, -0.5, 1.0, -0.5, -0.5, 1.0, -0.5, 0.5, 1.0, 0.5, 0.5};
3031df5d5c5SMatthew G. Knepley 
3049566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
3051df5d5c5SMatthew G. Knepley       }
3061df5d5c5SMatthew G. Knepley       break;
307d71ae5a4SJacob Faibussowitsch     default:
308d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
3091df5d5c5SMatthew G. Knepley     }
3101df5d5c5SMatthew G. Knepley   }
3111df5d5c5SMatthew G. Knepley   *newdm = dm;
3121df5d5c5SMatthew G. Knepley   if (refinementLimit > 0.0) {
3131df5d5c5SMatthew G. Knepley     DM          rdm;
3141df5d5c5SMatthew G. Knepley     const char *name;
3151df5d5c5SMatthew G. Knepley 
3169566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE));
3179566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit));
3189566063dSJacob Faibussowitsch     PetscCall(DMRefine(*newdm, comm, &rdm));
3199566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)*newdm, &name));
3209566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)rdm, name));
3219566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
3221df5d5c5SMatthew G. Knepley     *newdm = rdm;
3231df5d5c5SMatthew G. Knepley   }
3241df5d5c5SMatthew G. Knepley   if (interpolate) {
3255fd9971aSMatthew G. Knepley     DM idm;
3261df5d5c5SMatthew G. Knepley 
3279566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*newdm, &idm));
3289566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
3291df5d5c5SMatthew G. Knepley     *newdm = idm;
3301df5d5c5SMatthew G. Knepley   }
3311df5d5c5SMatthew G. Knepley   PetscFunctionReturn(0);
3321df5d5c5SMatthew G. Knepley }
3331df5d5c5SMatthew G. Knepley 
334d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
335d71ae5a4SJacob Faibussowitsch {
3369318fe57SMatthew G. Knepley   const PetscInt numVertices    = 2;
3379318fe57SMatthew G. Knepley   PetscInt       markerRight    = 1;
3389318fe57SMatthew G. Knepley   PetscInt       markerLeft     = 1;
3399318fe57SMatthew G. Knepley   PetscBool      markerSeparate = PETSC_FALSE;
3409318fe57SMatthew G. Knepley   Vec            coordinates;
3419318fe57SMatthew G. Knepley   PetscSection   coordSection;
3429318fe57SMatthew G. Knepley   PetscScalar   *coords;
3439318fe57SMatthew G. Knepley   PetscInt       coordSize;
3449318fe57SMatthew G. Knepley   PetscMPIInt    rank;
3459318fe57SMatthew G. Knepley   PetscInt       cdim = 1, v;
346552f7358SJed Brown 
3479318fe57SMatthew G. Knepley   PetscFunctionBegin;
3489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
3499318fe57SMatthew G. Knepley   if (markerSeparate) {
3509318fe57SMatthew G. Knepley     markerRight = 2;
3519318fe57SMatthew G. Knepley     markerLeft  = 1;
3529318fe57SMatthew G. Knepley   }
3539566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
354c5853193SPierre Jolivet   if (rank == 0) {
3559566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numVertices));
3569566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3579566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft));
3589566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight));
3599318fe57SMatthew G. Knepley   }
3609566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
3619566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
3629318fe57SMatthew G. Knepley   /* Build coordinates */
3639566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
3649566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
3659566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
3669566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, 0, numVertices));
3679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
3689318fe57SMatthew G. Knepley   for (v = 0; v < numVertices; ++v) {
3699566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
3709566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
3719318fe57SMatthew G. Knepley   }
3729566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
3739566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
3749566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
3759566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
3769566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
3779566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
3789566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
3799566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
3809318fe57SMatthew G. Knepley   coords[0] = lower[0];
3819318fe57SMatthew G. Knepley   coords[1] = upper[0];
3829566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
3839566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
3849566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
3859318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
3869318fe57SMatthew G. Knepley }
38726492d91SMatthew G. Knepley 
388d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
389d71ae5a4SJacob Faibussowitsch {
3901df21d24SMatthew G. Knepley   const PetscInt numVertices    = (edges[0] + 1) * (edges[1] + 1);
3911df21d24SMatthew G. Knepley   const PetscInt numEdges       = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1];
392552f7358SJed Brown   PetscInt       markerTop      = 1;
393552f7358SJed Brown   PetscInt       markerBottom   = 1;
394552f7358SJed Brown   PetscInt       markerRight    = 1;
395552f7358SJed Brown   PetscInt       markerLeft     = 1;
396552f7358SJed Brown   PetscBool      markerSeparate = PETSC_FALSE;
397552f7358SJed Brown   Vec            coordinates;
398552f7358SJed Brown   PetscSection   coordSection;
399552f7358SJed Brown   PetscScalar   *coords;
400552f7358SJed Brown   PetscInt       coordSize;
401552f7358SJed Brown   PetscMPIInt    rank;
402552f7358SJed Brown   PetscInt       v, vx, vy;
403552f7358SJed Brown 
404552f7358SJed Brown   PetscFunctionBegin;
4059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
406552f7358SJed Brown   if (markerSeparate) {
4071df21d24SMatthew G. Knepley     markerTop    = 3;
4081df21d24SMatthew G. Knepley     markerBottom = 1;
4091df21d24SMatthew G. Knepley     markerRight  = 2;
4101df21d24SMatthew G. Knepley     markerLeft   = 4;
411552f7358SJed Brown   }
4129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
413dd400576SPatrick Sanan   if (rank == 0) {
414552f7358SJed Brown     PetscInt e, ex, ey;
415552f7358SJed Brown 
4169566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices));
41748a46eb9SPierre Jolivet     for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
4189566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
419552f7358SJed Brown     for (vx = 0; vx <= edges[0]; vx++) {
420552f7358SJed Brown       for (ey = 0; ey < edges[1]; ey++) {
421552f7358SJed Brown         PetscInt edge   = vx * edges[1] + ey + edges[0] * (edges[1] + 1);
422552f7358SJed Brown         PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges;
423da80777bSKarl Rupp         PetscInt cone[2];
424552f7358SJed Brown 
4259371c9d4SSatish Balay         cone[0] = vertex;
4269371c9d4SSatish Balay         cone[1] = vertex + edges[0] + 1;
4279566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
428552f7358SJed Brown         if (vx == edges[0]) {
4299566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
4309566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
431552f7358SJed Brown           if (ey == edges[1] - 1) {
4329566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
4339566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight));
434552f7358SJed Brown           }
435552f7358SJed Brown         } else if (vx == 0) {
4369566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
4379566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
438552f7358SJed Brown           if (ey == edges[1] - 1) {
4399566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
4409566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft));
441552f7358SJed Brown           }
442552f7358SJed Brown         }
443552f7358SJed Brown       }
444552f7358SJed Brown     }
445552f7358SJed Brown     for (vy = 0; vy <= edges[1]; vy++) {
446552f7358SJed Brown       for (ex = 0; ex < edges[0]; ex++) {
447552f7358SJed Brown         PetscInt edge   = vy * edges[0] + ex;
448552f7358SJed Brown         PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges;
449da80777bSKarl Rupp         PetscInt cone[2];
450552f7358SJed Brown 
4519371c9d4SSatish Balay         cone[0] = vertex;
4529371c9d4SSatish Balay         cone[1] = vertex + 1;
4539566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
454552f7358SJed Brown         if (vy == edges[1]) {
4559566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
4569566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
457552f7358SJed Brown           if (ex == edges[0] - 1) {
4589566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
4599566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop));
460552f7358SJed Brown           }
461552f7358SJed Brown         } else if (vy == 0) {
4629566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
4639566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
464552f7358SJed Brown           if (ex == edges[0] - 1) {
4659566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
4669566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom));
467552f7358SJed Brown           }
468552f7358SJed Brown         }
469552f7358SJed Brown       }
470552f7358SJed Brown     }
471552f7358SJed Brown   }
4729566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
4739566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
474552f7358SJed Brown   /* Build coordinates */
4759566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 2));
4769566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
4779566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
4789566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices));
4799566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2));
480552f7358SJed Brown   for (v = numEdges; v < numEdges + numVertices; ++v) {
4819566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 2));
4829566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2));
483552f7358SJed Brown   }
4849566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
4859566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
4869566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
4879566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
4889566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
4899566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 2));
4909566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
4919566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
492552f7358SJed Brown   for (vy = 0; vy <= edges[1]; ++vy) {
493552f7358SJed Brown     for (vx = 0; vx <= edges[0]; ++vx) {
494552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx;
495552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy;
496552f7358SJed Brown     }
497552f7358SJed Brown   }
4989566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
4999566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
5009566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
501552f7358SJed Brown   PetscFunctionReturn(0);
502552f7358SJed Brown }
503552f7358SJed Brown 
504d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[])
505d71ae5a4SJacob Faibussowitsch {
5069e8abbc3SMichael Lange   PetscInt     vertices[3], numVertices;
5077b59f5a9SMichael Lange   PetscInt     numFaces       = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2];
508c2df9bbfSMatthew G. Knepley   PetscInt     markerTop      = 1;
509c2df9bbfSMatthew G. Knepley   PetscInt     markerBottom   = 1;
510c2df9bbfSMatthew G. Knepley   PetscInt     markerFront    = 1;
511c2df9bbfSMatthew G. Knepley   PetscInt     markerBack     = 1;
512c2df9bbfSMatthew G. Knepley   PetscInt     markerRight    = 1;
513c2df9bbfSMatthew G. Knepley   PetscInt     markerLeft     = 1;
514c2df9bbfSMatthew G. Knepley   PetscBool    markerSeparate = PETSC_FALSE;
515552f7358SJed Brown   Vec          coordinates;
516552f7358SJed Brown   PetscSection coordSection;
517552f7358SJed Brown   PetscScalar *coords;
518552f7358SJed Brown   PetscInt     coordSize;
519552f7358SJed Brown   PetscMPIInt  rank;
520552f7358SJed Brown   PetscInt     v, vx, vy, vz;
5217b59f5a9SMichael Lange   PetscInt     voffset, iface = 0, cone[4];
522552f7358SJed Brown 
523552f7358SJed Brown   PetscFunctionBegin;
5241dca8a05SBarry Smith   PetscCheck(faces[0] >= 1 && faces[1] >= 1 && faces[2] >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Must have at least 1 face per side");
5259566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
526c2df9bbfSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
527c2df9bbfSMatthew G. Knepley   if (markerSeparate) {
528c2df9bbfSMatthew G. Knepley     markerBottom = 1;
529c2df9bbfSMatthew G. Knepley     markerTop    = 2;
530c2df9bbfSMatthew G. Knepley     markerFront  = 3;
531c2df9bbfSMatthew G. Knepley     markerBack   = 4;
532c2df9bbfSMatthew G. Knepley     markerRight  = 5;
533c2df9bbfSMatthew G. Knepley     markerLeft   = 6;
534c2df9bbfSMatthew G. Knepley   }
5359371c9d4SSatish Balay   vertices[0] = faces[0] + 1;
5369371c9d4SSatish Balay   vertices[1] = faces[1] + 1;
5379371c9d4SSatish Balay   vertices[2] = faces[2] + 1;
5389e8abbc3SMichael Lange   numVertices = vertices[0] * vertices[1] * vertices[2];
539dd400576SPatrick Sanan   if (rank == 0) {
540552f7358SJed Brown     PetscInt f;
541552f7358SJed Brown 
5429566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices));
54348a46eb9SPierre Jolivet     for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
5449566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
5457b59f5a9SMichael Lange 
5467b59f5a9SMichael Lange     /* Side 0 (Top) */
5477b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
5487b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5497b59f5a9SMichael Lange         voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx;
5509371c9d4SSatish Balay         cone[0] = voffset;
5519371c9d4SSatish Balay         cone[1] = voffset + 1;
5529371c9d4SSatish Balay         cone[2] = voffset + vertices[0] + 1;
5539371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
5549566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
555c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop));
556c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop));
557c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop));
558c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop));
559c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop));
5607b59f5a9SMichael Lange         iface++;
561552f7358SJed Brown       }
562552f7358SJed Brown     }
5637b59f5a9SMichael Lange 
5647b59f5a9SMichael Lange     /* Side 1 (Bottom) */
5657b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
5667b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5677b59f5a9SMichael Lange         voffset = numFaces + vy * (faces[0] + 1) + vx;
5689371c9d4SSatish Balay         cone[0] = voffset + 1;
5699371c9d4SSatish Balay         cone[1] = voffset;
5709371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
5719371c9d4SSatish Balay         cone[3] = voffset + vertices[0] + 1;
5729566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
573c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom));
574c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom));
575c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom));
576c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom));
577c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom));
5787b59f5a9SMichael Lange         iface++;
579552f7358SJed Brown       }
580552f7358SJed Brown     }
5817b59f5a9SMichael Lange 
5827b59f5a9SMichael Lange     /* Side 2 (Front) */
5837b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
5847b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5857b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vx;
5869371c9d4SSatish Balay         cone[0] = voffset;
5879371c9d4SSatish Balay         cone[1] = voffset + 1;
5889371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + 1;
5899371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1];
5909566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
591c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront));
592c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront));
593c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront));
594c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront));
595c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront));
5967b59f5a9SMichael Lange         iface++;
597552f7358SJed Brown       }
5987b59f5a9SMichael Lange     }
5997b59f5a9SMichael Lange 
6007b59f5a9SMichael Lange     /* Side 3 (Back) */
6017b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6027b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
6037b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx;
6049371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
6059371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1] + 1;
6069371c9d4SSatish Balay         cone[2] = voffset + 1;
6079371c9d4SSatish Balay         cone[3] = voffset;
6089566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
609c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack));
610c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack));
611c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack));
612c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack));
613c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack));
6147b59f5a9SMichael Lange         iface++;
6157b59f5a9SMichael Lange       }
6167b59f5a9SMichael Lange     }
6177b59f5a9SMichael Lange 
6187b59f5a9SMichael Lange     /* Side 4 (Left) */
6197b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6207b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
6217b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0];
6229371c9d4SSatish Balay         cone[0] = voffset;
6239371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1];
6249371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + vertices[0];
6259371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
6269566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
627c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft));
628c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft));
629c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft));
630c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft));
631c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft));
6327b59f5a9SMichael Lange         iface++;
6337b59f5a9SMichael Lange       }
6347b59f5a9SMichael Lange     }
6357b59f5a9SMichael Lange 
6367b59f5a9SMichael Lange     /* Side 5 (Right) */
6377b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6387b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
639aab5bcd8SJed Brown         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0];
6409371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
6419371c9d4SSatish Balay         cone[1] = voffset;
6429371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
6439371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1] + vertices[0];
6449566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
645c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight));
646c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight));
647c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight));
648c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight));
649c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight));
6507b59f5a9SMichael Lange         iface++;
6517b59f5a9SMichael Lange       }
652552f7358SJed Brown     }
653552f7358SJed Brown   }
6549566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
6559566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
656552f7358SJed Brown   /* Build coordinates */
6579566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 3));
6589566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
6599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
6609566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices));
6619566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3));
662552f7358SJed Brown   for (v = numFaces; v < numFaces + numVertices; ++v) {
6639566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 3));
6649566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3));
665552f7358SJed Brown   }
6669566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
6679566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
6689566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
6699566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
6709566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
6719566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 3));
6729566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
6739566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
674552f7358SJed Brown   for (vz = 0; vz <= faces[2]; ++vz) {
675552f7358SJed Brown     for (vy = 0; vy <= faces[1]; ++vy) {
676552f7358SJed Brown       for (vx = 0; vx <= faces[0]; ++vx) {
677552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx;
678552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy;
679552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz;
680552f7358SJed Brown       }
681552f7358SJed Brown     }
682552f7358SJed Brown   }
6839566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
6849566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
6859566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
686552f7358SJed Brown   PetscFunctionReturn(0);
687552f7358SJed Brown }
688552f7358SJed Brown 
689d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate)
690d71ae5a4SJacob Faibussowitsch {
6919318fe57SMatthew G. Knepley   PetscFunctionBegin;
6929318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
6939566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim - 1));
6949566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim));
6959318fe57SMatthew G. Knepley   switch (dim) {
696d71ae5a4SJacob Faibussowitsch   case 1:
697d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces));
698d71ae5a4SJacob Faibussowitsch     break;
699d71ae5a4SJacob Faibussowitsch   case 2:
700d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces));
701d71ae5a4SJacob Faibussowitsch     break;
702d71ae5a4SJacob Faibussowitsch   case 3:
703d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces));
704d71ae5a4SJacob Faibussowitsch     break;
705d71ae5a4SJacob Faibussowitsch   default:
706d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim);
7079318fe57SMatthew G. Knepley   }
7089566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
7099318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
7109318fe57SMatthew G. Knepley }
7119318fe57SMatthew G. Knepley 
7129318fe57SMatthew G. Knepley /*@C
7139318fe57SMatthew G. Knepley   DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra).
7149318fe57SMatthew G. Knepley 
7159318fe57SMatthew G. Knepley   Collective
7169318fe57SMatthew G. Knepley 
7179318fe57SMatthew G. Knepley   Input Parameters:
7189318fe57SMatthew G. Knepley + comm        - The communicator for the DM object
7199318fe57SMatthew G. Knepley . dim         - The spatial dimension of the box, so the resulting mesh is has dimension dim-1
7209318fe57SMatthew G. Knepley . faces       - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
7219318fe57SMatthew G. Knepley . lower       - The lower left corner, or NULL for (0, 0, 0)
7229318fe57SMatthew G. Knepley . upper       - The upper right corner, or NULL for (1, 1, 1)
7239318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
7249318fe57SMatthew G. Knepley 
7259318fe57SMatthew G. Knepley   Output Parameter:
7269318fe57SMatthew G. Knepley . dm  - The DM object
7279318fe57SMatthew G. Knepley 
7289318fe57SMatthew G. Knepley   Level: beginner
7299318fe57SMatthew G. Knepley 
730db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()`
7319318fe57SMatthew G. Knepley @*/
732d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm)
733d71ae5a4SJacob Faibussowitsch {
7349318fe57SMatthew G. Knepley   PetscInt  fac[3] = {1, 1, 1};
7359318fe57SMatthew G. Knepley   PetscReal low[3] = {0, 0, 0};
7369318fe57SMatthew G. Knepley   PetscReal upp[3] = {1, 1, 1};
7379318fe57SMatthew G. Knepley 
7389318fe57SMatthew G. Knepley   PetscFunctionBegin;
7399566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
7409566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
7419566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate));
7429318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
7439318fe57SMatthew G. Knepley }
7449318fe57SMatthew G. Knepley 
745d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd)
746d71ae5a4SJacob Faibussowitsch {
747fdbf62faSLisandro Dalcin   PetscInt     i, fStart, fEnd, numCells = 0, numVerts = 0;
748fdbf62faSLisandro Dalcin   PetscInt     numPoints[2], *coneSize, *cones, *coneOrientations;
749fdbf62faSLisandro Dalcin   PetscScalar *vertexCoords;
750fdbf62faSLisandro Dalcin   PetscReal    L, maxCell;
751fdbf62faSLisandro Dalcin   PetscBool    markerSeparate = PETSC_FALSE;
752fdbf62faSLisandro Dalcin   PetscInt     markerLeft = 1, faceMarkerLeft = 1;
753fdbf62faSLisandro Dalcin   PetscInt     markerRight = 1, faceMarkerRight = 2;
754fdbf62faSLisandro Dalcin   PetscBool    wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE;
755fdbf62faSLisandro Dalcin   PetscMPIInt  rank;
756fdbf62faSLisandro Dalcin 
757fdbf62faSLisandro Dalcin   PetscFunctionBegin;
7589318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
759fdbf62faSLisandro Dalcin 
7609566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, 1));
7619566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
7629566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
763fdbf62faSLisandro Dalcin 
7649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
765dd400576SPatrick Sanan   if (rank == 0) numCells = segments;
766dd400576SPatrick Sanan   if (rank == 0) numVerts = segments + (wrap ? 0 : 1);
767fdbf62faSLisandro Dalcin 
7689371c9d4SSatish Balay   numPoints[0] = numVerts;
7699371c9d4SSatish Balay   numPoints[1] = numCells;
7709566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords));
7719566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts));
772ad540459SPierre Jolivet   for (i = 0; i < numCells; ++i) coneSize[i] = 2;
773ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0;
7749371c9d4SSatish Balay   for (i = 0; i < numCells; ++i) {
7759371c9d4SSatish Balay     cones[2 * i]     = numCells + i % numVerts;
7769371c9d4SSatish Balay     cones[2 * i + 1] = numCells + (i + 1) % numVerts;
7779371c9d4SSatish Balay   }
778ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells);
7799566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
7809566063dSJacob Faibussowitsch   PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords));
781fdbf62faSLisandro Dalcin 
7829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
7839371c9d4SSatish Balay   if (markerSeparate) {
7849371c9d4SSatish Balay     markerLeft  = faceMarkerLeft;
7859371c9d4SSatish Balay     markerRight = faceMarkerRight;
7869371c9d4SSatish Balay   }
787dd400576SPatrick Sanan   if (!wrap && rank == 0) {
7889566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
7899566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft));
7909566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight));
7919566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft));
7929566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight));
793fdbf62faSLisandro Dalcin   }
794fdbf62faSLisandro Dalcin   if (wrap) {
795fdbf62faSLisandro Dalcin     L       = upper - lower;
796fdbf62faSLisandro Dalcin     maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments));
7974fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L));
798fdbf62faSLisandro Dalcin   }
7999566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
800fdbf62faSLisandro Dalcin   PetscFunctionReturn(0);
801fdbf62faSLisandro Dalcin }
802fdbf62faSLisandro Dalcin 
803d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
804d71ae5a4SJacob Faibussowitsch {
8059318fe57SMatthew G. Knepley   DM      boundary, vol;
806c22d3578SMatthew G. Knepley   DMLabel bdlabel;
807d6218766SMatthew G. Knepley 
808d6218766SMatthew G. Knepley   PetscFunctionBegin;
8099318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
810c22d3578SMatthew G. Knepley   for (PetscInt i = 0; i < dim; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity is not supported for simplex meshes");
8119566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary));
8129566063dSJacob Faibussowitsch   PetscCall(DMSetType(boundary, DMPLEX));
8139566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE));
8149566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol));
815c22d3578SMatthew G. Knepley   PetscCall(DMGetLabel(vol, "marker", &bdlabel));
816c22d3578SMatthew G. Knepley   if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel));
8175de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol));
81869d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
8199566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&boundary));
820d6218766SMatthew G. Knepley   PetscFunctionReturn(0);
821d6218766SMatthew G. Knepley }
822d6218766SMatthew G. Knepley 
823d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ)
824d71ae5a4SJacob Faibussowitsch {
825ed0e4b50SMatthew G. Knepley   DMLabel     cutLabel  = NULL;
826f4eb4c5dSMatthew G. Knepley   PetscInt    markerTop = 1, faceMarkerTop = 1;
827f4eb4c5dSMatthew G. Knepley   PetscInt    markerBottom = 1, faceMarkerBottom = 1;
828f4eb4c5dSMatthew G. Knepley   PetscInt    markerFront = 1, faceMarkerFront = 1;
829f4eb4c5dSMatthew G. Knepley   PetscInt    markerBack = 1, faceMarkerBack = 1;
830f4eb4c5dSMatthew G. Knepley   PetscInt    markerRight = 1, faceMarkerRight = 1;
831f4eb4c5dSMatthew G. Knepley   PetscInt    markerLeft = 1, faceMarkerLeft = 1;
8323dfda0b1SToby Isaac   PetscInt    dim;
833d8211ee3SMatthew G. Knepley   PetscBool   markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE;
8343dfda0b1SToby Isaac   PetscMPIInt rank;
8353dfda0b1SToby Isaac 
8363dfda0b1SToby Isaac   PetscFunctionBegin;
8379566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
8389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
8399566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
8409566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
8419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
8429371c9d4SSatish Balay   if (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST || bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST || bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST) {
8439371c9d4SSatish Balay     if (cutMarker) {
8449371c9d4SSatish Balay       PetscCall(DMCreateLabel(dm, "periodic_cut"));
8459371c9d4SSatish Balay       PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
8469371c9d4SSatish Balay     }
847d8211ee3SMatthew G. Knepley   }
8483dfda0b1SToby Isaac   switch (dim) {
8493dfda0b1SToby Isaac   case 2:
850f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 3;
851f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
852f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 2;
853f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 4;
8543dfda0b1SToby Isaac     break;
8553dfda0b1SToby Isaac   case 3:
856f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
857f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 2;
858f4eb4c5dSMatthew G. Knepley     faceMarkerFront  = 3;
859f4eb4c5dSMatthew G. Knepley     faceMarkerBack   = 4;
860f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 5;
861f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 6;
8623dfda0b1SToby Isaac     break;
863d71ae5a4SJacob Faibussowitsch   default:
864d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
8653dfda0b1SToby Isaac   }
8669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
867f4eb4c5dSMatthew G. Knepley   if (markerSeparate) {
868f4eb4c5dSMatthew G. Knepley     markerBottom = faceMarkerBottom;
869f4eb4c5dSMatthew G. Knepley     markerTop    = faceMarkerTop;
870f4eb4c5dSMatthew G. Knepley     markerFront  = faceMarkerFront;
871f4eb4c5dSMatthew G. Knepley     markerBack   = faceMarkerBack;
872f4eb4c5dSMatthew G. Knepley     markerRight  = faceMarkerRight;
873f4eb4c5dSMatthew G. Knepley     markerLeft   = faceMarkerLeft;
8743dfda0b1SToby Isaac   }
8753dfda0b1SToby Isaac   {
876dd400576SPatrick Sanan     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
877dd400576SPatrick Sanan     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
878dd400576SPatrick Sanan     const PetscInt numZEdges    = rank == 0 ? edges[2] : 0;
879dd400576SPatrick Sanan     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0;
880dd400576SPatrick Sanan     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0;
881dd400576SPatrick Sanan     const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0;
8823dfda0b1SToby Isaac     const PetscInt numCells     = numXEdges * numYEdges * numZEdges;
8833dfda0b1SToby Isaac     const PetscInt numXFaces    = numYEdges * numZEdges;
8843dfda0b1SToby Isaac     const PetscInt numYFaces    = numXEdges * numZEdges;
8853dfda0b1SToby Isaac     const PetscInt numZFaces    = numXEdges * numYEdges;
8863dfda0b1SToby Isaac     const PetscInt numTotXFaces = numXVertices * numXFaces;
8873dfda0b1SToby Isaac     const PetscInt numTotYFaces = numYVertices * numYFaces;
8883dfda0b1SToby Isaac     const PetscInt numTotZFaces = numZVertices * numZFaces;
8893dfda0b1SToby Isaac     const PetscInt numFaces     = numTotXFaces + numTotYFaces + numTotZFaces;
8903dfda0b1SToby Isaac     const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices;
8913dfda0b1SToby Isaac     const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices;
8923dfda0b1SToby Isaac     const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices;
8933dfda0b1SToby Isaac     const PetscInt numVertices  = numXVertices * numYVertices * numZVertices;
8943dfda0b1SToby Isaac     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numTotZEdges;
8953dfda0b1SToby Isaac     const PetscInt firstVertex  = (dim == 2) ? numFaces : numCells;
8963dfda0b1SToby Isaac     const PetscInt firstXFace   = (dim == 2) ? 0 : numCells + numVertices;
8973dfda0b1SToby Isaac     const PetscInt firstYFace   = firstXFace + numTotXFaces;
8983dfda0b1SToby Isaac     const PetscInt firstZFace   = firstYFace + numTotYFaces;
8993dfda0b1SToby Isaac     const PetscInt firstXEdge   = numCells + numFaces + numVertices;
9003dfda0b1SToby Isaac     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
9013dfda0b1SToby Isaac     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
9023dfda0b1SToby Isaac     Vec            coordinates;
9033dfda0b1SToby Isaac     PetscSection   coordSection;
9043dfda0b1SToby Isaac     PetscScalar   *coords;
9053dfda0b1SToby Isaac     PetscInt       coordSize;
9063dfda0b1SToby Isaac     PetscInt       v, vx, vy, vz;
9073dfda0b1SToby Isaac     PetscInt       c, f, fx, fy, fz, e, ex, ey, ez;
9083dfda0b1SToby Isaac 
9099566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices));
91048a46eb9SPierre Jolivet     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
91148a46eb9SPierre Jolivet     for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
91248a46eb9SPierre Jolivet     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
9139566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
9143dfda0b1SToby Isaac     /* Build cells */
9153dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
9163dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
9173dfda0b1SToby Isaac         for (fx = 0; fx < numXEdges; ++fx) {
9183dfda0b1SToby Isaac           PetscInt cell  = (fz * numYEdges + fy) * numXEdges + fx;
9193dfda0b1SToby Isaac           PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
9203dfda0b1SToby Isaac           PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices);
9213dfda0b1SToby Isaac           PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
9223dfda0b1SToby Isaac           PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices);
9233dfda0b1SToby Isaac           PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
9243dfda0b1SToby Isaac           PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices);
9253dfda0b1SToby Isaac           /* B,  T,  F,  K,  R,  L */
926b5a892a1SMatthew G. Knepley           PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */
92742206facSLisandro Dalcin           PetscInt cone[6];
9283dfda0b1SToby Isaac 
9293dfda0b1SToby Isaac           /* no boundary twisting in 3D */
9309371c9d4SSatish Balay           cone[0] = faceB;
9319371c9d4SSatish Balay           cone[1] = faceT;
9329371c9d4SSatish Balay           cone[2] = faceF;
9339371c9d4SSatish Balay           cone[3] = faceK;
9349371c9d4SSatish Balay           cone[4] = faceR;
9359371c9d4SSatish Balay           cone[5] = faceL;
9369566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, cell, cone));
9379566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, cell, ornt));
9389566063dSJacob Faibussowitsch           if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9399566063dSJacob Faibussowitsch           if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9409566063dSJacob Faibussowitsch           if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
9413dfda0b1SToby Isaac         }
9423dfda0b1SToby Isaac       }
9433dfda0b1SToby Isaac     }
9443dfda0b1SToby Isaac     /* Build x faces */
9453dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
9463dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
9473dfda0b1SToby Isaac         for (fx = 0; fx < numXVertices; ++fx) {
9483dfda0b1SToby Isaac           PetscInt face    = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
9493dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
9503dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz;
9513dfda0b1SToby Isaac           PetscInt edgeB   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
9523dfda0b1SToby Isaac           PetscInt edgeT   = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy;
953b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
9543dfda0b1SToby Isaac           PetscInt cone[4];
9553dfda0b1SToby Isaac 
9563dfda0b1SToby Isaac           if (dim == 3) {
9573dfda0b1SToby Isaac             /* markers */
9583dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
9593dfda0b1SToby Isaac               if (fx == numXVertices - 1) {
9609566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight));
9619566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerRight));
9629371c9d4SSatish Balay               } else if (fx == 0) {
9639566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft));
9649566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft));
9653dfda0b1SToby Isaac               }
9663dfda0b1SToby Isaac             }
9673dfda0b1SToby Isaac           }
9689371c9d4SSatish Balay           cone[0] = edgeB;
9699371c9d4SSatish Balay           cone[1] = edgeR;
9709371c9d4SSatish Balay           cone[2] = edgeT;
9719371c9d4SSatish Balay           cone[3] = edgeL;
9729566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
9739566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
9743dfda0b1SToby Isaac         }
9753dfda0b1SToby Isaac       }
9763dfda0b1SToby Isaac     }
9773dfda0b1SToby Isaac     /* Build y faces */
9783dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
97942206facSLisandro Dalcin       for (fx = 0; fx < numXEdges; ++fx) {
9803dfda0b1SToby Isaac         for (fy = 0; fy < numYVertices; ++fy) {
9813dfda0b1SToby Isaac           PetscInt face    = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
9823dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
9833dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz;
9843dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
9853dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx;
986b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
9873dfda0b1SToby Isaac           PetscInt cone[4];
9883dfda0b1SToby Isaac 
9893dfda0b1SToby Isaac           if (dim == 3) {
9903dfda0b1SToby Isaac             /* markers */
9913dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
9923dfda0b1SToby Isaac               if (fy == numYVertices - 1) {
9939566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack));
9949566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBack));
9959371c9d4SSatish Balay               } else if (fy == 0) {
9969566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront));
9979566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerFront));
9983dfda0b1SToby Isaac               }
9993dfda0b1SToby Isaac             }
10003dfda0b1SToby Isaac           }
10019371c9d4SSatish Balay           cone[0] = edgeB;
10029371c9d4SSatish Balay           cone[1] = edgeR;
10039371c9d4SSatish Balay           cone[2] = edgeT;
10049371c9d4SSatish Balay           cone[3] = edgeL;
10059566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
10069566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
10073dfda0b1SToby Isaac         }
10083dfda0b1SToby Isaac       }
10093dfda0b1SToby Isaac     }
10103dfda0b1SToby Isaac     /* Build z faces */
10113dfda0b1SToby Isaac     for (fy = 0; fy < numYEdges; ++fy) {
10123dfda0b1SToby Isaac       for (fx = 0; fx < numXEdges; ++fx) {
10133dfda0b1SToby Isaac         for (fz = 0; fz < numZVertices; fz++) {
10143dfda0b1SToby Isaac           PetscInt face    = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
10153dfda0b1SToby Isaac           PetscInt edgeL   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
10163dfda0b1SToby Isaac           PetscInt edgeR   = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy;
10173dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
10183dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx;
1019b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
10203dfda0b1SToby Isaac           PetscInt cone[4];
10213dfda0b1SToby Isaac 
10223dfda0b1SToby Isaac           if (dim == 2) {
10239371c9d4SSatish Balay             if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) {
10249371c9d4SSatish Balay               edgeR += numYEdges - 1 - 2 * fy;
10259371c9d4SSatish Balay               ornt[1] = -1;
10269371c9d4SSatish Balay             }
10279371c9d4SSatish Balay             if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) {
10289371c9d4SSatish Balay               edgeT += numXEdges - 1 - 2 * fx;
10299371c9d4SSatish Balay               ornt[2] = 0;
10309371c9d4SSatish Balay             }
10319566063dSJacob Faibussowitsch             if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
10329566063dSJacob Faibussowitsch             if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
1033d1c88043SMatthew G. Knepley           } else {
10343dfda0b1SToby Isaac             /* markers */
10353dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
10363dfda0b1SToby Isaac               if (fz == numZVertices - 1) {
10379566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop));
10389566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerTop));
10399371c9d4SSatish Balay               } else if (fz == 0) {
10409566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom));
10419566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom));
10423dfda0b1SToby Isaac               }
10433dfda0b1SToby Isaac             }
10443dfda0b1SToby Isaac           }
10459371c9d4SSatish Balay           cone[0] = edgeB;
10469371c9d4SSatish Balay           cone[1] = edgeR;
10479371c9d4SSatish Balay           cone[2] = edgeT;
10489371c9d4SSatish Balay           cone[3] = edgeL;
10499566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
10509566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
10513dfda0b1SToby Isaac         }
10523dfda0b1SToby Isaac       }
10533dfda0b1SToby Isaac     }
10543dfda0b1SToby Isaac     /* Build Z edges*/
10553dfda0b1SToby Isaac     for (vy = 0; vy < numYVertices; vy++) {
10563dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
10573dfda0b1SToby Isaac         for (ez = 0; ez < numZEdges; ez++) {
10583dfda0b1SToby Isaac           const PetscInt edge    = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez;
10593dfda0b1SToby Isaac           const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx;
10603dfda0b1SToby Isaac           const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx;
10613dfda0b1SToby Isaac           PetscInt       cone[2];
10623dfda0b1SToby Isaac 
10639371c9d4SSatish Balay           cone[0] = vertexB;
10649371c9d4SSatish Balay           cone[1] = vertexT;
1065c2df9bbfSMatthew G. Knepley           PetscCall(DMPlexSetCone(dm, edge, cone));
10663dfda0b1SToby Isaac           if (dim == 3) {
10673dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
10683dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
10699566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1070c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1071c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1072c2df9bbfSMatthew G. Knepley               } else if (vx == 0) {
10739566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1074c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1075c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
10763dfda0b1SToby Isaac               }
10773dfda0b1SToby Isaac             }
10783dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
10793dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
10809566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1081c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1082c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1083c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
10849566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1085c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1086c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
10873dfda0b1SToby Isaac               }
10883dfda0b1SToby Isaac             }
10893dfda0b1SToby Isaac           }
10903dfda0b1SToby Isaac         }
10913dfda0b1SToby Isaac       }
10923dfda0b1SToby Isaac     }
10933dfda0b1SToby Isaac     /* Build Y edges*/
10943dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
10953dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
10963dfda0b1SToby Isaac         for (ey = 0; ey < numYEdges; ey++) {
10973dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx;
10983dfda0b1SToby Isaac           const PetscInt edge    = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey;
10993dfda0b1SToby Isaac           const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx;
11003dfda0b1SToby Isaac           const PetscInt vertexK = firstVertex + nextv;
11013dfda0b1SToby Isaac           PetscInt       cone[2];
11023dfda0b1SToby Isaac 
11039371c9d4SSatish Balay           cone[0] = vertexF;
11049371c9d4SSatish Balay           cone[1] = vertexK;
11059566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
11063dfda0b1SToby Isaac           if (dim == 2) {
11073dfda0b1SToby Isaac             if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
11083dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
11099566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
11109566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
11119566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1112c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1113d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
11149566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
11159566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
11169566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1117c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
11183dfda0b1SToby Isaac               }
1119d8211ee3SMatthew G. Knepley             } else {
11204c67ea77SStefano Zampini               if (vx == 0 && cutLabel) {
11219566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
11229566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1123c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
11243dfda0b1SToby Isaac               }
1125d8211ee3SMatthew G. Knepley             }
1126d8211ee3SMatthew G. Knepley           } else {
11273dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
11283dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
11299566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1130c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1131c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1132d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
11339566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1134c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1135c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
11363dfda0b1SToby Isaac               }
11373dfda0b1SToby Isaac             }
11383dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
11393dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
11409566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1141c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1142c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1143d8211ee3SMatthew G. Knepley               } else if (vz == 0) {
11449566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1145c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1146c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
11473dfda0b1SToby Isaac               }
11483dfda0b1SToby Isaac             }
11493dfda0b1SToby Isaac           }
11503dfda0b1SToby Isaac         }
11513dfda0b1SToby Isaac       }
11523dfda0b1SToby Isaac     }
11533dfda0b1SToby Isaac     /* Build X edges*/
11543dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
11553dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; vy++) {
11563dfda0b1SToby Isaac         for (ex = 0; ex < numXEdges; ex++) {
11573dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices;
11583dfda0b1SToby Isaac           const PetscInt edge    = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex;
11593dfda0b1SToby Isaac           const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex;
11603dfda0b1SToby Isaac           const PetscInt vertexR = firstVertex + nextv;
11613dfda0b1SToby Isaac           PetscInt       cone[2];
11623dfda0b1SToby Isaac 
11639371c9d4SSatish Balay           cone[0] = vertexL;
11649371c9d4SSatish Balay           cone[1] = vertexR;
11659566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
11663dfda0b1SToby Isaac           if (dim == 2) {
11673dfda0b1SToby Isaac             if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
11683dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
11699566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
11709566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
11719566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1172c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1173d8211ee3SMatthew G. Knepley               } else if (vy == 0) {
11749566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
11759566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
11769566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1177c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
11783dfda0b1SToby Isaac               }
1179d8211ee3SMatthew G. Knepley             } else {
11804c67ea77SStefano Zampini               if (vy == 0 && cutLabel) {
11819566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
11829566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1183c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
11843dfda0b1SToby Isaac               }
1185d8211ee3SMatthew G. Knepley             }
1186d8211ee3SMatthew G. Knepley           } else {
11873dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
11883dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
11899566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1190c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1191c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1192c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
11939566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1194c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1195c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
11963dfda0b1SToby Isaac               }
11973dfda0b1SToby Isaac             }
11983dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
11993dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
12009566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1201c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1202c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1203c2df9bbfSMatthew G. Knepley               } else if (vz == 0) {
12049566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1205c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1206c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
12073dfda0b1SToby Isaac               }
12083dfda0b1SToby Isaac             }
12093dfda0b1SToby Isaac           }
12103dfda0b1SToby Isaac         }
12113dfda0b1SToby Isaac       }
12123dfda0b1SToby Isaac     }
12139566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
12149566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
12153dfda0b1SToby Isaac     /* Build coordinates */
12169566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
12179566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
12189566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
12199566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
12203dfda0b1SToby Isaac     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
12219566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
12229566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
12233dfda0b1SToby Isaac     }
12249566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
12259566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
12269566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
12279566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
12289566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
12299566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
12309566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
12319566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
12323dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; ++vz) {
12333dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; ++vy) {
12343dfda0b1SToby Isaac         for (vx = 0; vx < numXVertices; ++vx) {
12353dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
12363dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
1237ad540459SPierre Jolivet           if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz;
12383dfda0b1SToby Isaac         }
12393dfda0b1SToby Isaac       }
12403dfda0b1SToby Isaac     }
12419566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
12429566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
12439566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
12443dfda0b1SToby Isaac   }
12453dfda0b1SToby Isaac   PetscFunctionReturn(0);
12463dfda0b1SToby Isaac }
12473dfda0b1SToby Isaac 
1248d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1249d71ae5a4SJacob Faibussowitsch {
12509318fe57SMatthew G. Knepley   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
12519318fe57SMatthew G. Knepley   PetscInt       fac[3] = {0, 0, 0}, d;
1252552f7358SJed Brown 
1253552f7358SJed Brown   PetscFunctionBegin;
12549318fe57SMatthew G. Knepley   PetscValidPointer(dm, 1);
12559318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
12569566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
12579371c9d4SSatish Balay   for (d = 0; d < dim; ++d) {
12589371c9d4SSatish Balay     fac[d] = faces[d];
12599371c9d4SSatish Balay     bdt[d] = periodicity[d];
12609371c9d4SSatish Balay   }
12619566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2]));
12629371c9d4SSatish Balay   if (periodicity[0] == DM_BOUNDARY_PERIODIC || periodicity[0] == DM_BOUNDARY_TWIST || periodicity[1] == DM_BOUNDARY_PERIODIC || periodicity[1] == DM_BOUNDARY_TWIST || (dim > 2 && (periodicity[2] == DM_BOUNDARY_PERIODIC || periodicity[2] == DM_BOUNDARY_TWIST))) {
12636858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
12646858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1265552f7358SJed Brown 
12669318fe57SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
12676858538eSMatthew G. Knepley       if (periodicity[d] != DM_BOUNDARY_NONE) {
12689318fe57SMatthew G. Knepley         L[d]       = upper[d] - lower[d];
12699318fe57SMatthew G. Knepley         maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d]));
1270768d5fceSMatthew G. Knepley       }
12716858538eSMatthew G. Knepley     }
12724fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1273768d5fceSMatthew G. Knepley   }
12749566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
12759318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
12769318fe57SMatthew G. Knepley }
12779318fe57SMatthew G. Knepley 
1278d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
1279d71ae5a4SJacob Faibussowitsch {
12809318fe57SMatthew G. Knepley   PetscFunctionBegin;
12819566063dSJacob Faibussowitsch   if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0]));
12829566063dSJacob Faibussowitsch   else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
12839566063dSJacob Faibussowitsch   else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity));
12849318fe57SMatthew G. Knepley   if (!interpolate && dim > 1 && !simplex) {
1285768d5fceSMatthew G. Knepley     DM udm;
1286768d5fceSMatthew G. Knepley 
12879566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(dm, &udm));
12889566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, udm));
128969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &udm));
1290768d5fceSMatthew G. Knepley   }
1291768d5fceSMatthew G. Knepley   PetscFunctionReturn(0);
1292c8c68bd8SToby Isaac }
1293c8c68bd8SToby Isaac 
1294768d5fceSMatthew G. Knepley /*@C
1295768d5fceSMatthew G. Knepley   DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra).
1296768d5fceSMatthew G. Knepley 
1297d083f849SBarry Smith   Collective
1298768d5fceSMatthew G. Knepley 
1299768d5fceSMatthew G. Knepley   Input Parameters:
1300768d5fceSMatthew G. Knepley + comm        - The communicator for the DM object
1301768d5fceSMatthew G. Knepley . dim         - The spatial dimension
1302768d5fceSMatthew G. Knepley . simplex     - PETSC_TRUE for simplices, PETSC_FALSE for tensor cells
1303fdbf62faSLisandro Dalcin . faces       - Number of faces per dimension, or NULL for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
1304768d5fceSMatthew G. Knepley . lower       - The lower left corner, or NULL for (0, 0, 0)
1305768d5fceSMatthew G. Knepley . upper       - The upper right corner, or NULL for (1, 1, 1)
1306fdbf62faSLisandro Dalcin . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE
1307768d5fceSMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
1308768d5fceSMatthew G. Knepley 
1309768d5fceSMatthew G. Knepley   Output Parameter:
1310768d5fceSMatthew G. Knepley . dm  - The DM object
1311768d5fceSMatthew G. Knepley 
13129318fe57SMatthew G. Knepley   Note: If you want to customize this mesh using options, you just need to
13139318fe57SMatthew G. Knepley $  DMCreate(comm, &dm);
13149318fe57SMatthew G. Knepley $  DMSetType(dm, DMPLEX);
13159318fe57SMatthew G. Knepley $  DMSetFromOptions(dm);
13169318fe57SMatthew G. Knepley and use the options on the DMSetFromOptions() page.
13171367e252SJed Brown 
13181367e252SJed Brown   Here is the numbering returned for 2 faces in each direction for tensor cells:
1319768d5fceSMatthew G. Knepley $ 10---17---11---18----12
1320768d5fceSMatthew G. Knepley $  |         |         |
1321768d5fceSMatthew G. Knepley $  |         |         |
1322768d5fceSMatthew G. Knepley $ 20    2   22    3    24
1323768d5fceSMatthew G. Knepley $  |         |         |
1324768d5fceSMatthew G. Knepley $  |         |         |
1325768d5fceSMatthew G. Knepley $  7---15----8---16----9
1326768d5fceSMatthew G. Knepley $  |         |         |
1327768d5fceSMatthew G. Knepley $  |         |         |
1328768d5fceSMatthew G. Knepley $ 19    0   21    1   23
1329768d5fceSMatthew G. Knepley $  |         |         |
1330768d5fceSMatthew G. Knepley $  |         |         |
1331768d5fceSMatthew G. Knepley $  4---13----5---14----6
1332768d5fceSMatthew G. Knepley 
1333768d5fceSMatthew G. Knepley and for simplicial cells
1334768d5fceSMatthew G. Knepley 
1335768d5fceSMatthew G. Knepley $ 14----8---15----9----16
1336768d5fceSMatthew G. Knepley $  |\     5  |\      7 |
1337768d5fceSMatthew G. Knepley $  | \       | \       |
1338768d5fceSMatthew G. Knepley $ 13   2    14    3    15
1339768d5fceSMatthew G. Knepley $  | 4   \   | 6   \   |
1340768d5fceSMatthew G. Knepley $  |       \ |       \ |
1341768d5fceSMatthew G. Knepley $ 11----6---12----7----13
1342768d5fceSMatthew G. Knepley $  |\        |\        |
1343768d5fceSMatthew G. Knepley $  | \    1  | \     3 |
1344768d5fceSMatthew G. Knepley $ 10   0    11    1    12
1345768d5fceSMatthew G. Knepley $  | 0   \   | 2   \   |
1346768d5fceSMatthew G. Knepley $  |       \ |       \ |
1347768d5fceSMatthew G. Knepley $  8----4----9----5----10
1348768d5fceSMatthew G. Knepley 
1349768d5fceSMatthew G. Knepley   Level: beginner
1350768d5fceSMatthew G. Knepley 
1351db781477SPatrick Sanan .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
1352768d5fceSMatthew G. Knepley @*/
1353d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate, DM *dm)
1354d71ae5a4SJacob Faibussowitsch {
13559318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
1356fdbf62faSLisandro Dalcin   PetscReal      low[3] = {0, 0, 0};
1357fdbf62faSLisandro Dalcin   PetscReal      upp[3] = {1, 1, 1};
1358fdbf62faSLisandro Dalcin   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
1359552f7358SJed Brown 
1360768d5fceSMatthew G. Knepley   PetscFunctionBegin;
13619566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
13629566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
13639566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Internal(*dm, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate));
13647ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
13659318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
13669318fe57SMatthew G. Knepley }
1367fdbf62faSLisandro Dalcin 
1368d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1369d71ae5a4SJacob Faibussowitsch {
13709318fe57SMatthew G. Knepley   DM       bdm, vol;
13719318fe57SMatthew G. Knepley   PetscInt i;
13729318fe57SMatthew G. Knepley 
13739318fe57SMatthew G. Knepley   PetscFunctionBegin;
137408401ef6SPierre Jolivet   for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported");
13759566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm));
13769566063dSJacob Faibussowitsch   PetscCall(DMSetType(bdm, DMPLEX));
13779566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(bdm, 2));
13789566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE));
13799566063dSJacob Faibussowitsch   PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, NULL, NULL, &vol));
13809566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&bdm));
138169d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
13829318fe57SMatthew G. Knepley   if (lower[2] != 0.0) {
13839318fe57SMatthew G. Knepley     Vec          v;
13849318fe57SMatthew G. Knepley     PetscScalar *x;
13859318fe57SMatthew G. Knepley     PetscInt     cDim, n;
13869318fe57SMatthew G. Knepley 
13879566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &v));
13889566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(v, &cDim));
13899566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(v, &n));
13909566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v, &x));
13919318fe57SMatthew G. Knepley     x += cDim;
13929318fe57SMatthew G. Knepley     for (i = 0; i < n; i += cDim) x[i] += lower[2];
13939566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v, &x));
13949566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, v));
13959318fe57SMatthew G. Knepley   }
1396552f7358SJed Brown   PetscFunctionReturn(0);
1397552f7358SJed Brown }
1398552f7358SJed Brown 
139900dabe28SStefano Zampini /*@
140000dabe28SStefano Zampini   DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tesselating the (x,y) plane and extruding in the third direction using wedge cells.
140100dabe28SStefano Zampini 
1402d083f849SBarry Smith   Collective
140300dabe28SStefano Zampini 
140400dabe28SStefano Zampini   Input Parameters:
140500dabe28SStefano Zampini + comm        - The communicator for the DM object
140600dabe28SStefano Zampini . faces       - Number of faces per dimension, or NULL for (1, 1, 1)
140700dabe28SStefano Zampini . lower       - The lower left corner, or NULL for (0, 0, 0)
140800dabe28SStefano Zampini . upper       - The upper right corner, or NULL for (1, 1, 1)
140900dabe28SStefano Zampini . periodicity - The boundary type for the X,Y,Z direction, or NULL for DM_BOUNDARY_NONE
1410d0fcb9c2SMatthew G. Knepley . orderHeight - If PETSC_TRUE, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first
141100dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces)
141200dabe28SStefano Zampini 
141300dabe28SStefano Zampini   Output Parameter:
141400dabe28SStefano Zampini . dm  - The DM object
141500dabe28SStefano Zampini 
141600dabe28SStefano Zampini   Level: beginner
141700dabe28SStefano Zampini 
1418db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
141900dabe28SStefano Zampini @*/
1420d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm)
1421d71ae5a4SJacob Faibussowitsch {
14229318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
142300dabe28SStefano Zampini   PetscReal      low[3] = {0, 0, 0};
142400dabe28SStefano Zampini   PetscReal      upp[3] = {1, 1, 1};
142500dabe28SStefano Zampini   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
142600dabe28SStefano Zampini 
142700dabe28SStefano Zampini   PetscFunctionBegin;
14289566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
14299566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
14309566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt));
1431d410b0cfSMatthew G. Knepley   if (!interpolate) {
1432d410b0cfSMatthew G. Knepley     DM udm;
143300dabe28SStefano Zampini 
14349566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(*dm, &udm));
143569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(*dm, &udm));
143600dabe28SStefano Zampini   }
14377ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
143800dabe28SStefano Zampini   PetscFunctionReturn(0);
143900dabe28SStefano Zampini }
144000dabe28SStefano Zampini 
1441a9074c1eSMatthew G. Knepley /*@C
1442a9074c1eSMatthew G. Knepley   DMPlexSetOptionsPrefix - Sets the prefix used for searching for all DM options in the database.
1443a9074c1eSMatthew G. Knepley 
1444d083f849SBarry Smith   Logically Collective on dm
1445a9074c1eSMatthew G. Knepley 
1446a9074c1eSMatthew G. Knepley   Input Parameters:
1447a9074c1eSMatthew G. Knepley + dm - the DM context
1448a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names
1449a9074c1eSMatthew G. Knepley 
1450a9074c1eSMatthew G. Knepley   Notes:
1451a9074c1eSMatthew G. Knepley   A hyphen (-) must NOT be given at the beginning of the prefix name.
1452a9074c1eSMatthew G. Knepley   The first character of all runtime options is AUTOMATICALLY the hyphen.
1453a9074c1eSMatthew G. Knepley 
1454a9074c1eSMatthew G. Knepley   Level: advanced
1455a9074c1eSMatthew G. Knepley 
1456db781477SPatrick Sanan .seealso: `SNESSetFromOptions()`
1457a9074c1eSMatthew G. Knepley @*/
1458d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[])
1459d71ae5a4SJacob Faibussowitsch {
1460a9074c1eSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
1461a9074c1eSMatthew G. Knepley 
1462a9074c1eSMatthew G. Knepley   PetscFunctionBegin;
1463a9074c1eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
14649566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
14659566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix));
1466a9074c1eSMatthew G. Knepley   PetscFunctionReturn(0);
1467a9074c1eSMatthew G. Knepley }
1468a9074c1eSMatthew G. Knepley 
14699318fe57SMatthew G. Knepley /* Remap geometry to cylinder
147061a622f3SMatthew G. Knepley    TODO: This only works for a single refinement, then it is broken
147161a622f3SMatthew G. Knepley 
14729318fe57SMatthew G. Knepley      Interior square: Linear interpolation is correct
14739318fe57SMatthew G. Knepley      The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing
14749318fe57SMatthew G. Knepley      such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance
14750510c589SMatthew G. Knepley 
14769318fe57SMatthew G. Knepley        phi     = arctan(y/x)
14779318fe57SMatthew G. Knepley        d_close = sqrt(1/8 + 1/4 sin^2(phi))
14789318fe57SMatthew G. Knepley        d_far   = sqrt(1/2 + sin^2(phi))
14790510c589SMatthew G. Knepley 
14809318fe57SMatthew G. Knepley      so we remap them using
14810510c589SMatthew G. Knepley 
14829318fe57SMatthew G. Knepley        x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close)
14839318fe57SMatthew G. Knepley        y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close)
14840510c589SMatthew G. Knepley 
14859318fe57SMatthew G. Knepley      If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y.
14869318fe57SMatthew G. Knepley */
1487d71ae5a4SJacob Faibussowitsch static void snapToCylinder(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
1488d71ae5a4SJacob Faibussowitsch {
14899318fe57SMatthew G. Knepley   const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
14909318fe57SMatthew G. Knepley   const PetscReal ds2 = 0.5 * dis;
149122cc497dSMatthew G. Knepley 
14929318fe57SMatthew G. Knepley   if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) {
14939318fe57SMatthew G. Knepley     f0[0] = u[0];
14949318fe57SMatthew G. Knepley     f0[1] = u[1];
14959318fe57SMatthew G. Knepley   } else {
14969318fe57SMatthew G. Knepley     PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc;
14970510c589SMatthew G. Knepley 
14989318fe57SMatthew G. Knepley     x    = PetscRealPart(u[0]);
14999318fe57SMatthew G. Knepley     y    = PetscRealPart(u[1]);
15009318fe57SMatthew G. Knepley     phi  = PetscAtan2Real(y, x);
15019318fe57SMatthew G. Knepley     sinp = PetscSinReal(phi);
15029318fe57SMatthew G. Knepley     cosp = PetscCosReal(phi);
15039318fe57SMatthew G. Knepley     if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) {
15049318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / sinp);
15059318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / sinp);
15069318fe57SMatthew G. Knepley       xc = ds2 * x / PetscAbsReal(y);
15079318fe57SMatthew G. Knepley       yc = ds2 * PetscSignReal(y);
15089318fe57SMatthew G. Knepley     } else {
15099318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / cosp);
15109318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / cosp);
15119318fe57SMatthew G. Knepley       xc = ds2 * PetscSignReal(x);
15129318fe57SMatthew G. Knepley       yc = ds2 * y / PetscAbsReal(x);
15139318fe57SMatthew G. Knepley     }
15149318fe57SMatthew G. Knepley     f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc);
15159318fe57SMatthew G. Knepley     f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc);
15169318fe57SMatthew G. Knepley   }
15179318fe57SMatthew G. Knepley   f0[2] = u[2];
15189318fe57SMatthew G. Knepley }
15190510c589SMatthew G. Knepley 
1520d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ)
1521d71ae5a4SJacob Faibussowitsch {
15220510c589SMatthew G. Knepley   const PetscInt dim = 3;
15239318fe57SMatthew G. Knepley   PetscInt       numCells, numVertices;
1524d8c47e87SMatthew G. Knepley   PetscMPIInt    rank;
15250510c589SMatthew G. Knepley 
15260510c589SMatthew G. Knepley   PetscFunctionBegin;
15279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
15289566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
15290510c589SMatthew G. Knepley   /* Create topology */
15300510c589SMatthew G. Knepley   {
15310510c589SMatthew G. Knepley     PetscInt cone[8], c;
15320510c589SMatthew G. Knepley 
1533dd400576SPatrick Sanan     numCells    = rank == 0 ? 5 : 0;
1534dd400576SPatrick Sanan     numVertices = rank == 0 ? 16 : 0;
1535006a8963SMatthew G. Knepley     if (periodicZ == DM_BOUNDARY_PERIODIC) {
1536ae8bcbbbSMatthew G. Knepley       numCells *= 3;
1537dd400576SPatrick Sanan       numVertices = rank == 0 ? 24 : 0;
1538006a8963SMatthew G. Knepley     }
15399566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
15409566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8));
15419566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
1542dd400576SPatrick Sanan     if (rank == 0) {
1543006a8963SMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
15449371c9d4SSatish Balay         cone[0] = 15;
15459371c9d4SSatish Balay         cone[1] = 18;
15469371c9d4SSatish Balay         cone[2] = 17;
15479371c9d4SSatish Balay         cone[3] = 16;
15489371c9d4SSatish Balay         cone[4] = 31;
15499371c9d4SSatish Balay         cone[5] = 32;
15509371c9d4SSatish Balay         cone[6] = 33;
15519371c9d4SSatish Balay         cone[7] = 34;
15529566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
15539371c9d4SSatish Balay         cone[0] = 16;
15549371c9d4SSatish Balay         cone[1] = 17;
15559371c9d4SSatish Balay         cone[2] = 24;
15569371c9d4SSatish Balay         cone[3] = 23;
15579371c9d4SSatish Balay         cone[4] = 32;
15589371c9d4SSatish Balay         cone[5] = 36;
15599371c9d4SSatish Balay         cone[6] = 37;
15609371c9d4SSatish Balay         cone[7] = 33; /* 22 25 26 21 */
15619566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
15629371c9d4SSatish Balay         cone[0] = 18;
15639371c9d4SSatish Balay         cone[1] = 27;
15649371c9d4SSatish Balay         cone[2] = 24;
15659371c9d4SSatish Balay         cone[3] = 17;
15669371c9d4SSatish Balay         cone[4] = 34;
15679371c9d4SSatish Balay         cone[5] = 33;
15689371c9d4SSatish Balay         cone[6] = 37;
15699371c9d4SSatish Balay         cone[7] = 38;
15709566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
15719371c9d4SSatish Balay         cone[0] = 29;
15729371c9d4SSatish Balay         cone[1] = 27;
15739371c9d4SSatish Balay         cone[2] = 18;
15749371c9d4SSatish Balay         cone[3] = 15;
15759371c9d4SSatish Balay         cone[4] = 35;
15769371c9d4SSatish Balay         cone[5] = 31;
15779371c9d4SSatish Balay         cone[6] = 34;
15789371c9d4SSatish Balay         cone[7] = 38;
15799566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
15809371c9d4SSatish Balay         cone[0] = 29;
15819371c9d4SSatish Balay         cone[1] = 15;
15829371c9d4SSatish Balay         cone[2] = 16;
15839371c9d4SSatish Balay         cone[3] = 23;
15849371c9d4SSatish Balay         cone[4] = 35;
15859371c9d4SSatish Balay         cone[5] = 36;
15869371c9d4SSatish Balay         cone[6] = 32;
15879371c9d4SSatish Balay         cone[7] = 31;
15889566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
1589006a8963SMatthew G. Knepley 
15909371c9d4SSatish Balay         cone[0] = 31;
15919371c9d4SSatish Balay         cone[1] = 34;
15929371c9d4SSatish Balay         cone[2] = 33;
15939371c9d4SSatish Balay         cone[3] = 32;
15949371c9d4SSatish Balay         cone[4] = 19;
15959371c9d4SSatish Balay         cone[5] = 22;
15969371c9d4SSatish Balay         cone[6] = 21;
15979371c9d4SSatish Balay         cone[7] = 20;
15989566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
15999371c9d4SSatish Balay         cone[0] = 32;
16009371c9d4SSatish Balay         cone[1] = 33;
16019371c9d4SSatish Balay         cone[2] = 37;
16029371c9d4SSatish Balay         cone[3] = 36;
16039371c9d4SSatish Balay         cone[4] = 22;
16049371c9d4SSatish Balay         cone[5] = 25;
16059371c9d4SSatish Balay         cone[6] = 26;
16069371c9d4SSatish Balay         cone[7] = 21;
16079566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 6, cone));
16089371c9d4SSatish Balay         cone[0] = 34;
16099371c9d4SSatish Balay         cone[1] = 38;
16109371c9d4SSatish Balay         cone[2] = 37;
16119371c9d4SSatish Balay         cone[3] = 33;
16129371c9d4SSatish Balay         cone[4] = 20;
16139371c9d4SSatish Balay         cone[5] = 21;
16149371c9d4SSatish Balay         cone[6] = 26;
16159371c9d4SSatish Balay         cone[7] = 28;
16169566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 7, cone));
16179371c9d4SSatish Balay         cone[0] = 35;
16189371c9d4SSatish Balay         cone[1] = 38;
16199371c9d4SSatish Balay         cone[2] = 34;
16209371c9d4SSatish Balay         cone[3] = 31;
16219371c9d4SSatish Balay         cone[4] = 30;
16229371c9d4SSatish Balay         cone[5] = 19;
16239371c9d4SSatish Balay         cone[6] = 20;
16249371c9d4SSatish Balay         cone[7] = 28;
16259566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 8, cone));
16269371c9d4SSatish Balay         cone[0] = 35;
16279371c9d4SSatish Balay         cone[1] = 31;
16289371c9d4SSatish Balay         cone[2] = 32;
16299371c9d4SSatish Balay         cone[3] = 36;
16309371c9d4SSatish Balay         cone[4] = 30;
16319371c9d4SSatish Balay         cone[5] = 25;
16329371c9d4SSatish Balay         cone[6] = 22;
16339371c9d4SSatish Balay         cone[7] = 19;
16349566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 9, cone));
1635ae8bcbbbSMatthew G. Knepley 
16369371c9d4SSatish Balay         cone[0] = 19;
16379371c9d4SSatish Balay         cone[1] = 20;
16389371c9d4SSatish Balay         cone[2] = 21;
16399371c9d4SSatish Balay         cone[3] = 22;
16409371c9d4SSatish Balay         cone[4] = 15;
16419371c9d4SSatish Balay         cone[5] = 16;
16429371c9d4SSatish Balay         cone[6] = 17;
16439371c9d4SSatish Balay         cone[7] = 18;
16449566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 10, cone));
16459371c9d4SSatish Balay         cone[0] = 22;
16469371c9d4SSatish Balay         cone[1] = 21;
16479371c9d4SSatish Balay         cone[2] = 26;
16489371c9d4SSatish Balay         cone[3] = 25;
16499371c9d4SSatish Balay         cone[4] = 16;
16509371c9d4SSatish Balay         cone[5] = 23;
16519371c9d4SSatish Balay         cone[6] = 24;
16529371c9d4SSatish Balay         cone[7] = 17;
16539566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 11, cone));
16549371c9d4SSatish Balay         cone[0] = 20;
16559371c9d4SSatish Balay         cone[1] = 28;
16569371c9d4SSatish Balay         cone[2] = 26;
16579371c9d4SSatish Balay         cone[3] = 21;
16589371c9d4SSatish Balay         cone[4] = 18;
16599371c9d4SSatish Balay         cone[5] = 17;
16609371c9d4SSatish Balay         cone[6] = 24;
16619371c9d4SSatish Balay         cone[7] = 27;
16629566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 12, cone));
16639371c9d4SSatish Balay         cone[0] = 30;
16649371c9d4SSatish Balay         cone[1] = 28;
16659371c9d4SSatish Balay         cone[2] = 20;
16669371c9d4SSatish Balay         cone[3] = 19;
16679371c9d4SSatish Balay         cone[4] = 29;
16689371c9d4SSatish Balay         cone[5] = 15;
16699371c9d4SSatish Balay         cone[6] = 18;
16709371c9d4SSatish Balay         cone[7] = 27;
16719566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 13, cone));
16729371c9d4SSatish Balay         cone[0] = 30;
16739371c9d4SSatish Balay         cone[1] = 19;
16749371c9d4SSatish Balay         cone[2] = 22;
16759371c9d4SSatish Balay         cone[3] = 25;
16769371c9d4SSatish Balay         cone[4] = 29;
16779371c9d4SSatish Balay         cone[5] = 23;
16789371c9d4SSatish Balay         cone[6] = 16;
16799371c9d4SSatish Balay         cone[7] = 15;
16809566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
1681006a8963SMatthew G. Knepley       } else {
16829371c9d4SSatish Balay         cone[0] = 5;
16839371c9d4SSatish Balay         cone[1] = 8;
16849371c9d4SSatish Balay         cone[2] = 7;
16859371c9d4SSatish Balay         cone[3] = 6;
16869371c9d4SSatish Balay         cone[4] = 9;
16879371c9d4SSatish Balay         cone[5] = 12;
16889371c9d4SSatish Balay         cone[6] = 11;
16899371c9d4SSatish Balay         cone[7] = 10;
16909566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
16919371c9d4SSatish Balay         cone[0] = 6;
16929371c9d4SSatish Balay         cone[1] = 7;
16939371c9d4SSatish Balay         cone[2] = 14;
16949371c9d4SSatish Balay         cone[3] = 13;
16959371c9d4SSatish Balay         cone[4] = 12;
16969371c9d4SSatish Balay         cone[5] = 15;
16979371c9d4SSatish Balay         cone[6] = 16;
16989371c9d4SSatish Balay         cone[7] = 11;
16999566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
17009371c9d4SSatish Balay         cone[0] = 8;
17019371c9d4SSatish Balay         cone[1] = 17;
17029371c9d4SSatish Balay         cone[2] = 14;
17039371c9d4SSatish Balay         cone[3] = 7;
17049371c9d4SSatish Balay         cone[4] = 10;
17059371c9d4SSatish Balay         cone[5] = 11;
17069371c9d4SSatish Balay         cone[6] = 16;
17079371c9d4SSatish Balay         cone[7] = 18;
17089566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
17099371c9d4SSatish Balay         cone[0] = 19;
17109371c9d4SSatish Balay         cone[1] = 17;
17119371c9d4SSatish Balay         cone[2] = 8;
17129371c9d4SSatish Balay         cone[3] = 5;
17139371c9d4SSatish Balay         cone[4] = 20;
17149371c9d4SSatish Balay         cone[5] = 9;
17159371c9d4SSatish Balay         cone[6] = 10;
17169371c9d4SSatish Balay         cone[7] = 18;
17179566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
17189371c9d4SSatish Balay         cone[0] = 19;
17199371c9d4SSatish Balay         cone[1] = 5;
17209371c9d4SSatish Balay         cone[2] = 6;
17219371c9d4SSatish Balay         cone[3] = 13;
17229371c9d4SSatish Balay         cone[4] = 20;
17239371c9d4SSatish Balay         cone[5] = 15;
17249371c9d4SSatish Balay         cone[6] = 12;
17259371c9d4SSatish Balay         cone[7] = 9;
17269566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
1727006a8963SMatthew G. Knepley       }
1728d8c47e87SMatthew G. Knepley     }
17299566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
17309566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
17310510c589SMatthew G. Knepley   }
1732dbc1dc17SMatthew G. Knepley   /* Create cube geometry */
17330510c589SMatthew G. Knepley   {
17340510c589SMatthew G. Knepley     Vec             coordinates;
17350510c589SMatthew G. Knepley     PetscSection    coordSection;
17360510c589SMatthew G. Knepley     PetscScalar    *coords;
17370510c589SMatthew G. Knepley     PetscInt        coordSize, v;
17380510c589SMatthew G. Knepley     const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
17390510c589SMatthew G. Knepley     const PetscReal ds2 = dis / 2.0;
17400510c589SMatthew G. Knepley 
17410510c589SMatthew G. Knepley     /* Build coordinates */
17429566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
17439566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
17449566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
17459566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
17460510c589SMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
17479566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
17489566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
17490510c589SMatthew G. Knepley     }
17509566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
17519566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
17529566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
17539566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
17549566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
17559566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
17569566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
17579566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
1758dd400576SPatrick Sanan     if (rank == 0) {
17599371c9d4SSatish Balay       coords[0 * dim + 0]  = -ds2;
17609371c9d4SSatish Balay       coords[0 * dim + 1]  = -ds2;
17619371c9d4SSatish Balay       coords[0 * dim + 2]  = 0.0;
17629371c9d4SSatish Balay       coords[1 * dim + 0]  = ds2;
17639371c9d4SSatish Balay       coords[1 * dim + 1]  = -ds2;
17649371c9d4SSatish Balay       coords[1 * dim + 2]  = 0.0;
17659371c9d4SSatish Balay       coords[2 * dim + 0]  = ds2;
17669371c9d4SSatish Balay       coords[2 * dim + 1]  = ds2;
17679371c9d4SSatish Balay       coords[2 * dim + 2]  = 0.0;
17689371c9d4SSatish Balay       coords[3 * dim + 0]  = -ds2;
17699371c9d4SSatish Balay       coords[3 * dim + 1]  = ds2;
17709371c9d4SSatish Balay       coords[3 * dim + 2]  = 0.0;
17719371c9d4SSatish Balay       coords[4 * dim + 0]  = -ds2;
17729371c9d4SSatish Balay       coords[4 * dim + 1]  = -ds2;
17739371c9d4SSatish Balay       coords[4 * dim + 2]  = 1.0;
17749371c9d4SSatish Balay       coords[5 * dim + 0]  = -ds2;
17759371c9d4SSatish Balay       coords[5 * dim + 1]  = ds2;
17769371c9d4SSatish Balay       coords[5 * dim + 2]  = 1.0;
17779371c9d4SSatish Balay       coords[6 * dim + 0]  = ds2;
17789371c9d4SSatish Balay       coords[6 * dim + 1]  = ds2;
17799371c9d4SSatish Balay       coords[6 * dim + 2]  = 1.0;
17809371c9d4SSatish Balay       coords[7 * dim + 0]  = ds2;
17819371c9d4SSatish Balay       coords[7 * dim + 1]  = -ds2;
17829371c9d4SSatish Balay       coords[7 * dim + 2]  = 1.0;
17839371c9d4SSatish Balay       coords[8 * dim + 0]  = dis;
17849371c9d4SSatish Balay       coords[8 * dim + 1]  = -dis;
17859371c9d4SSatish Balay       coords[8 * dim + 2]  = 0.0;
17869371c9d4SSatish Balay       coords[9 * dim + 0]  = dis;
17879371c9d4SSatish Balay       coords[9 * dim + 1]  = dis;
17889371c9d4SSatish Balay       coords[9 * dim + 2]  = 0.0;
17899371c9d4SSatish Balay       coords[10 * dim + 0] = dis;
17909371c9d4SSatish Balay       coords[10 * dim + 1] = -dis;
17919371c9d4SSatish Balay       coords[10 * dim + 2] = 1.0;
17929371c9d4SSatish Balay       coords[11 * dim + 0] = dis;
17939371c9d4SSatish Balay       coords[11 * dim + 1] = dis;
17949371c9d4SSatish Balay       coords[11 * dim + 2] = 1.0;
17959371c9d4SSatish Balay       coords[12 * dim + 0] = -dis;
17969371c9d4SSatish Balay       coords[12 * dim + 1] = dis;
17979371c9d4SSatish Balay       coords[12 * dim + 2] = 0.0;
17989371c9d4SSatish Balay       coords[13 * dim + 0] = -dis;
17999371c9d4SSatish Balay       coords[13 * dim + 1] = dis;
18009371c9d4SSatish Balay       coords[13 * dim + 2] = 1.0;
18019371c9d4SSatish Balay       coords[14 * dim + 0] = -dis;
18029371c9d4SSatish Balay       coords[14 * dim + 1] = -dis;
18039371c9d4SSatish Balay       coords[14 * dim + 2] = 0.0;
18049371c9d4SSatish Balay       coords[15 * dim + 0] = -dis;
18059371c9d4SSatish Balay       coords[15 * dim + 1] = -dis;
18069371c9d4SSatish Balay       coords[15 * dim + 2] = 1.0;
1807ae8bcbbbSMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
18089371c9d4SSatish Balay         /* 15 31 19 */ coords[16 * dim + 0] = -ds2;
18099371c9d4SSatish Balay         coords[16 * dim + 1]                = -ds2;
18109371c9d4SSatish Balay         coords[16 * dim + 2]                = 0.5;
18119371c9d4SSatish Balay         /* 16 32 22 */ coords[17 * dim + 0] = ds2;
18129371c9d4SSatish Balay         coords[17 * dim + 1]                = -ds2;
18139371c9d4SSatish Balay         coords[17 * dim + 2]                = 0.5;
18149371c9d4SSatish Balay         /* 17 33 21 */ coords[18 * dim + 0] = ds2;
18159371c9d4SSatish Balay         coords[18 * dim + 1]                = ds2;
18169371c9d4SSatish Balay         coords[18 * dim + 2]                = 0.5;
18179371c9d4SSatish Balay         /* 18 34 20 */ coords[19 * dim + 0] = -ds2;
18189371c9d4SSatish Balay         coords[19 * dim + 1]                = ds2;
18199371c9d4SSatish Balay         coords[19 * dim + 2]                = 0.5;
18209371c9d4SSatish Balay         /* 29 35 30 */ coords[20 * dim + 0] = -dis;
18219371c9d4SSatish Balay         coords[20 * dim + 1]                = -dis;
18229371c9d4SSatish Balay         coords[20 * dim + 2]                = 0.5;
18239371c9d4SSatish Balay         /* 23 36 25 */ coords[21 * dim + 0] = dis;
18249371c9d4SSatish Balay         coords[21 * dim + 1]                = -dis;
18259371c9d4SSatish Balay         coords[21 * dim + 2]                = 0.5;
18269371c9d4SSatish Balay         /* 24 37 26 */ coords[22 * dim + 0] = dis;
18279371c9d4SSatish Balay         coords[22 * dim + 1]                = dis;
18289371c9d4SSatish Balay         coords[22 * dim + 2]                = 0.5;
18299371c9d4SSatish Balay         /* 27 38 28 */ coords[23 * dim + 0] = -dis;
18309371c9d4SSatish Balay         coords[23 * dim + 1]                = dis;
18319371c9d4SSatish Balay         coords[23 * dim + 2]                = 0.5;
1832ae8bcbbbSMatthew G. Knepley       }
1833d8c47e87SMatthew G. Knepley     }
18349566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
18359566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
18369566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
18370510c589SMatthew G. Knepley   }
1838006a8963SMatthew G. Knepley   /* Create periodicity */
1839006a8963SMatthew G. Knepley   if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) {
18406858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
18416858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1842006a8963SMatthew G. Knepley     PetscReal lower[3]   = {0.0, 0.0, 0.0};
1843ae8bcbbbSMatthew G. Knepley     PetscReal upper[3]   = {1.0, 1.0, 1.5};
18446858538eSMatthew G. Knepley     PetscInt  numZCells  = 3;
1845006a8963SMatthew G. Knepley 
18466858538eSMatthew G. Knepley     L[2]       = upper[2] - lower[2];
18476858538eSMatthew G. Knepley     maxCell[2] = 1.1 * (L[2] / numZCells);
18484fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1849006a8963SMatthew G. Knepley   }
1850dbc1dc17SMatthew G. Knepley   {
18519318fe57SMatthew G. Knepley     DM          cdm;
18529318fe57SMatthew G. Knepley     PetscDS     cds;
18539318fe57SMatthew G. Knepley     PetscScalar c[2] = {1.0, 1.0};
1854dbc1dc17SMatthew G. Knepley 
18559566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToCylinder));
18569566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
18579566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
18589566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 2, c));
1859dbc1dc17SMatthew G. Knepley   }
18609318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
18619566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(dm));
18620510c589SMatthew G. Knepley   PetscFunctionReturn(0);
18630510c589SMatthew G. Knepley }
18640510c589SMatthew G. Knepley 
186524119c2aSMatthew G. Knepley /*@
18669318fe57SMatthew G. Knepley   DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra.
186724119c2aSMatthew G. Knepley 
1868d083f849SBarry Smith   Collective
186924119c2aSMatthew G. Knepley 
187024119c2aSMatthew G. Knepley   Input Parameters:
187124119c2aSMatthew G. Knepley + comm      - The communicator for the DM object
18729318fe57SMatthew G. Knepley - periodicZ - The boundary type for the Z direction
187324119c2aSMatthew G. Knepley 
187424119c2aSMatthew G. Knepley   Output Parameter:
187524119c2aSMatthew G. Knepley . dm  - The DM object
187624119c2aSMatthew G. Knepley 
18779318fe57SMatthew G. Knepley   Note:
18789318fe57SMatthew G. Knepley   Here is the output numbering looking from the bottom of the cylinder:
18799318fe57SMatthew G. Knepley $       17-----14
18809318fe57SMatthew G. Knepley $        |     |
18819318fe57SMatthew G. Knepley $        |  2  |
18829318fe57SMatthew G. Knepley $        |     |
18839318fe57SMatthew G. Knepley $ 17-----8-----7-----14
18849318fe57SMatthew G. Knepley $  |     |     |     |
18859318fe57SMatthew G. Knepley $  |  3  |  0  |  1  |
18869318fe57SMatthew G. Knepley $  |     |     |     |
18879318fe57SMatthew G. Knepley $ 19-----5-----6-----13
18889318fe57SMatthew G. Knepley $        |     |
18899318fe57SMatthew G. Knepley $        |  4  |
18909318fe57SMatthew G. Knepley $        |     |
18919318fe57SMatthew G. Knepley $       19-----13
18929318fe57SMatthew G. Knepley $
18939318fe57SMatthew G. Knepley $ and up through the top
18949318fe57SMatthew G. Knepley $
18959318fe57SMatthew G. Knepley $       18-----16
18969318fe57SMatthew G. Knepley $        |     |
18979318fe57SMatthew G. Knepley $        |  2  |
18989318fe57SMatthew G. Knepley $        |     |
18999318fe57SMatthew G. Knepley $ 18----10----11-----16
19009318fe57SMatthew G. Knepley $  |     |     |     |
19019318fe57SMatthew G. Knepley $  |  3  |  0  |  1  |
19029318fe57SMatthew G. Knepley $  |     |     |     |
19039318fe57SMatthew G. Knepley $ 20-----9----12-----15
19049318fe57SMatthew G. Knepley $        |     |
19059318fe57SMatthew G. Knepley $        |  4  |
19069318fe57SMatthew G. Knepley $        |     |
19079318fe57SMatthew G. Knepley $       20-----15
19089318fe57SMatthew G. Knepley 
190924119c2aSMatthew G. Knepley   Level: beginner
191024119c2aSMatthew G. Knepley 
1911db781477SPatrick Sanan .seealso: `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
191224119c2aSMatthew G. Knepley @*/
1913d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, DM *dm)
1914d71ae5a4SJacob Faibussowitsch {
19159318fe57SMatthew G. Knepley   PetscFunctionBegin;
19169318fe57SMatthew G. Knepley   PetscValidPointer(dm, 3);
19179566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
19189566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
19199566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ));
19209318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
19219318fe57SMatthew G. Knepley }
19229318fe57SMatthew G. Knepley 
1923d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate)
1924d71ae5a4SJacob Faibussowitsch {
192524119c2aSMatthew G. Knepley   const PetscInt dim = 3;
1926412e9a14SMatthew G. Knepley   PetscInt       numCells, numVertices, v;
19279fe9f049SMatthew G. Knepley   PetscMPIInt    rank;
192824119c2aSMatthew G. Knepley 
192924119c2aSMatthew G. Knepley   PetscFunctionBegin;
193063a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n);
19319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
19329566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
1933412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
19349566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
193524119c2aSMatthew G. Knepley   /* Create topology */
193624119c2aSMatthew G. Knepley   {
193724119c2aSMatthew G. Knepley     PetscInt cone[6], c;
193824119c2aSMatthew G. Knepley 
1939dd400576SPatrick Sanan     numCells    = rank == 0 ? n : 0;
1940dd400576SPatrick Sanan     numVertices = rank == 0 ? 2 * (n + 1) : 0;
19419566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
19429566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
19439566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
194424119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
19459371c9d4SSatish Balay       cone[0] = c + n * 1;
19469371c9d4SSatish Balay       cone[1] = (c + 1) % n + n * 1;
19479371c9d4SSatish Balay       cone[2] = 0 + 3 * n;
19489371c9d4SSatish Balay       cone[3] = c + n * 2;
19499371c9d4SSatish Balay       cone[4] = (c + 1) % n + n * 2;
19509371c9d4SSatish Balay       cone[5] = 1 + 3 * n;
19519566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(dm, c, cone));
19529566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR));
195324119c2aSMatthew G. Knepley     }
19549566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
19559566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
195624119c2aSMatthew G. Knepley   }
195748a46eb9SPierre Jolivet   for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT));
195824119c2aSMatthew G. Knepley   /* Create cylinder geometry */
195924119c2aSMatthew G. Knepley   {
196024119c2aSMatthew G. Knepley     Vec          coordinates;
196124119c2aSMatthew G. Knepley     PetscSection coordSection;
196224119c2aSMatthew G. Knepley     PetscScalar *coords;
1963412e9a14SMatthew G. Knepley     PetscInt     coordSize, c;
196424119c2aSMatthew G. Knepley 
196524119c2aSMatthew G. Knepley     /* Build coordinates */
19669566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
19679566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
19689566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
19699566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
197024119c2aSMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
19719566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
19729566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
197324119c2aSMatthew G. Knepley     }
19749566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
19759566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
19769566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
19779566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
19789566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
19799566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
19809566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
19819566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
198224119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
19839371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
19849371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
19859371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 2] = 1.0;
19869371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
19879371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
19889371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 2] = 0.0;
198924119c2aSMatthew G. Knepley     }
1990dd400576SPatrick Sanan     if (rank == 0) {
19919371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 0] = 0.0;
19929371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 1] = 0.0;
19939371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 2] = 1.0;
19949371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 0] = 0.0;
19959371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 1] = 0.0;
19969371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 2] = 0.0;
19979fe9f049SMatthew G. Knepley     }
19989566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
19999566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
20009566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
200124119c2aSMatthew G. Knepley   }
20029318fe57SMatthew G. Knepley   /* Interpolate */
20039566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
20049318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
20059318fe57SMatthew G. Knepley }
20069318fe57SMatthew G. Knepley 
20079318fe57SMatthew G. Knepley /*@
20089318fe57SMatthew G. Knepley   DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges.
20099318fe57SMatthew G. Knepley 
20109318fe57SMatthew G. Knepley   Collective
20119318fe57SMatthew G. Knepley 
20129318fe57SMatthew G. Knepley   Input Parameters:
20139318fe57SMatthew G. Knepley + comm - The communicator for the DM object
20149318fe57SMatthew G. Knepley . n    - The number of wedges around the origin
20159318fe57SMatthew G. Knepley - interpolate - Create edges and faces
20169318fe57SMatthew G. Knepley 
20179318fe57SMatthew G. Knepley   Output Parameter:
20189318fe57SMatthew G. Knepley . dm  - The DM object
20199318fe57SMatthew G. Knepley 
20209318fe57SMatthew G. Knepley   Level: beginner
20219318fe57SMatthew G. Knepley 
2022db781477SPatrick Sanan .seealso: `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
20239318fe57SMatthew G. Knepley @*/
2024d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm)
2025d71ae5a4SJacob Faibussowitsch {
20269318fe57SMatthew G. Knepley   PetscFunctionBegin;
20279318fe57SMatthew G. Knepley   PetscValidPointer(dm, 4);
20289566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
20299566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
20309566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate));
203124119c2aSMatthew G. Knepley   PetscFunctionReturn(0);
203224119c2aSMatthew G. Knepley }
203324119c2aSMatthew G. Knepley 
2034d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2035d71ae5a4SJacob Faibussowitsch {
203665a81367SMatthew G. Knepley   PetscReal prod = 0.0;
203765a81367SMatthew G. Knepley   PetscInt  i;
203865a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]);
203965a81367SMatthew G. Knepley   return PetscSqrtReal(prod);
204065a81367SMatthew G. Knepley }
2041d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2042d71ae5a4SJacob Faibussowitsch {
204365a81367SMatthew G. Knepley   PetscReal prod = 0.0;
204465a81367SMatthew G. Knepley   PetscInt  i;
204565a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += x[i] * y[i];
204665a81367SMatthew G. Knepley   return prod;
204765a81367SMatthew G. Knepley }
204865a81367SMatthew G. Knepley 
204951a74b61SMatthew G. Knepley /* The first constant is the sphere radius */
2050d71ae5a4SJacob Faibussowitsch static void snapToSphere(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
2051d71ae5a4SJacob Faibussowitsch {
205251a74b61SMatthew G. Knepley   PetscReal r     = PetscRealPart(constants[0]);
205351a74b61SMatthew G. Knepley   PetscReal norm2 = 0.0, fac;
205451a74b61SMatthew G. Knepley   PetscInt  n     = uOff[1] - uOff[0], d;
205551a74b61SMatthew G. Knepley 
205651a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d]));
205751a74b61SMatthew G. Knepley   fac = r / PetscSqrtReal(norm2);
205851a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) f0[d] = u[d] * fac;
205951a74b61SMatthew G. Knepley }
206051a74b61SMatthew G. Knepley 
2061d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R)
2062d71ae5a4SJacob Faibussowitsch {
206365a81367SMatthew G. Knepley   const PetscInt embedDim = dim + 1;
206465a81367SMatthew G. Knepley   PetscSection   coordSection;
206565a81367SMatthew G. Knepley   Vec            coordinates;
206665a81367SMatthew G. Knepley   PetscScalar   *coords;
206765a81367SMatthew G. Knepley   PetscReal     *coordsIn;
2068064cae4fSPierre Jolivet   PetscInt       numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, c, e;
206965a81367SMatthew G. Knepley   PetscMPIInt    rank;
207065a81367SMatthew G. Knepley 
207165a81367SMatthew G. Knepley   PetscFunctionBegin;
20729318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, simplex, 3);
20739566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
20749566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim + 1));
20759566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
207665a81367SMatthew G. Knepley   switch (dim) {
207765a81367SMatthew G. Knepley   case 2:
207865a81367SMatthew G. Knepley     if (simplex) {
207951a74b61SMatthew G. Knepley       const PetscReal radius    = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI);
208051a74b61SMatthew G. Knepley       const PetscReal edgeLen   = 2.0 / (1.0 + PETSC_PHI) * (R / radius);
208165a81367SMatthew G. Knepley       const PetscInt  degree    = 5;
208251a74b61SMatthew G. Knepley       PetscReal       vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)};
208365a81367SMatthew G. Knepley       PetscInt        s[3]      = {1, 1, 1};
208465a81367SMatthew G. Knepley       PetscInt        cone[3];
208565a81367SMatthew G. Knepley       PetscInt       *graph, p, i, j, k;
208665a81367SMatthew G. Knepley 
20879371c9d4SSatish Balay       vertex[0] *= R / radius;
20889371c9d4SSatish Balay       vertex[1] *= R / radius;
20899371c9d4SSatish Balay       vertex[2] *= R / radius;
2090dd400576SPatrick Sanan       numCells    = rank == 0 ? 20 : 0;
2091dd400576SPatrick Sanan       numVerts    = rank == 0 ? 12 : 0;
209265a81367SMatthew G. Knepley       firstVertex = numCells;
209351a74b61SMatthew G. Knepley       /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of
209465a81367SMatthew G. Knepley 
209565a81367SMatthew G. Knepley            (0, \pm 1/\phi+1, \pm \phi/\phi+1)
209665a81367SMatthew G. Knepley 
209765a81367SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
209851a74b61SMatthew G. Knepley          length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393.
209965a81367SMatthew G. Knepley       */
210065a81367SMatthew G. Knepley       /* Construct vertices */
21019566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2102dd400576SPatrick Sanan       if (rank == 0) {
210365a81367SMatthew G. Knepley         for (p = 0, i = 0; p < embedDim; ++p) {
210465a81367SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
210565a81367SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
210665a81367SMatthew G. Knepley               for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim];
210765a81367SMatthew G. Knepley               ++i;
210865a81367SMatthew G. Knepley             }
210965a81367SMatthew G. Knepley           }
211065a81367SMatthew G. Knepley         }
211145da822fSValeria Barra       }
211265a81367SMatthew G. Knepley       /* Construct graph */
21139566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
211465a81367SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
211565a81367SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
21169371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
21179371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
21189371c9d4SSatish Balay             ++k;
21199371c9d4SSatish Balay           }
212065a81367SMatthew G. Knepley         }
212163a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
212265a81367SMatthew G. Knepley       }
212365a81367SMatthew G. Knepley       /* Build Topology */
21249566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
212548a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
21269566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
212765a81367SMatthew G. Knepley       /* Cells */
212865a81367SMatthew G. Knepley       for (i = 0, c = 0; i < numVerts; ++i) {
212965a81367SMatthew G. Knepley         for (j = 0; j < i; ++j) {
213065a81367SMatthew G. Knepley           for (k = 0; k < j; ++k) {
213165a81367SMatthew G. Knepley             if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) {
21329371c9d4SSatish Balay               cone[0] = firstVertex + i;
21339371c9d4SSatish Balay               cone[1] = firstVertex + j;
21349371c9d4SSatish Balay               cone[2] = firstVertex + k;
213565a81367SMatthew G. Knepley               /* Check orientation */
213665a81367SMatthew G. Knepley               {
21379371c9d4SSatish Balay                 const PetscInt epsilon[3][3][3] = {
21389371c9d4SSatish Balay                   {{0, 0, 0},  {0, 0, 1},  {0, -1, 0}},
21399371c9d4SSatish Balay                   {{0, 0, -1}, {0, 0, 0},  {1, 0, 0} },
21409371c9d4SSatish Balay                   {{0, 1, 0},  {-1, 0, 0}, {0, 0, 0} }
21419371c9d4SSatish Balay                 };
214265a81367SMatthew G. Knepley                 PetscReal normal[3];
214365a81367SMatthew G. Knepley                 PetscInt  e, f;
214465a81367SMatthew G. Knepley 
214565a81367SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) {
214665a81367SMatthew G. Knepley                   normal[d] = 0.0;
214765a81367SMatthew G. Knepley                   for (e = 0; e < embedDim; ++e) {
2148ad540459SPierre Jolivet                     for (f = 0; f < embedDim; ++f) normal[d] += epsilon[d][e][f] * (coordsIn[j * embedDim + e] - coordsIn[i * embedDim + e]) * (coordsIn[k * embedDim + f] - coordsIn[i * embedDim + f]);
214965a81367SMatthew G. Knepley                   }
215065a81367SMatthew G. Knepley                 }
21519371c9d4SSatish Balay                 if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
21529371c9d4SSatish Balay                   PetscInt tmp = cone[1];
21539371c9d4SSatish Balay                   cone[1]      = cone[2];
21549371c9d4SSatish Balay                   cone[2]      = tmp;
215565a81367SMatthew G. Knepley                 }
215665a81367SMatthew G. Knepley               }
21579566063dSJacob Faibussowitsch               PetscCall(DMPlexSetCone(dm, c++, cone));
215865a81367SMatthew G. Knepley             }
215965a81367SMatthew G. Knepley           }
216065a81367SMatthew G. Knepley         }
216165a81367SMatthew G. Knepley       }
21629566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
21639566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
21649566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
216565a81367SMatthew G. Knepley     } else {
21662829fed8SMatthew G. Knepley       /*
21672829fed8SMatthew G. Knepley         12-21--13
21682829fed8SMatthew G. Knepley          |     |
21692829fed8SMatthew G. Knepley         25  4  24
21702829fed8SMatthew G. Knepley          |     |
21712829fed8SMatthew G. Knepley   12-25--9-16--8-24--13
21722829fed8SMatthew G. Knepley    |     |     |     |
21732829fed8SMatthew G. Knepley   23  5 17  0 15  3  22
21742829fed8SMatthew G. Knepley    |     |     |     |
21752829fed8SMatthew G. Knepley   10-20--6-14--7-19--11
21762829fed8SMatthew G. Knepley          |     |
21772829fed8SMatthew G. Knepley         20  1  19
21782829fed8SMatthew G. Knepley          |     |
21792829fed8SMatthew G. Knepley         10-18--11
21802829fed8SMatthew G. Knepley          |     |
21812829fed8SMatthew G. Knepley         23  2  22
21822829fed8SMatthew G. Knepley          |     |
21832829fed8SMatthew G. Knepley         12-21--13
21842829fed8SMatthew G. Knepley        */
21852829fed8SMatthew G. Knepley       PetscInt cone[4], ornt[4];
21862829fed8SMatthew G. Knepley 
2187dd400576SPatrick Sanan       numCells    = rank == 0 ? 6 : 0;
2188dd400576SPatrick Sanan       numEdges    = rank == 0 ? 12 : 0;
2189dd400576SPatrick Sanan       numVerts    = rank == 0 ? 8 : 0;
219065a81367SMatthew G. Knepley       firstVertex = numCells;
219165a81367SMatthew G. Knepley       firstEdge   = numCells + numVerts;
21922829fed8SMatthew G. Knepley       /* Build Topology */
21939566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts));
219448a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4));
219548a46eb9SPierre Jolivet       for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
21969566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2197dd400576SPatrick Sanan       if (rank == 0) {
21982829fed8SMatthew G. Knepley         /* Cell 0 */
21999371c9d4SSatish Balay         cone[0] = 14;
22009371c9d4SSatish Balay         cone[1] = 15;
22019371c9d4SSatish Balay         cone[2] = 16;
22029371c9d4SSatish Balay         cone[3] = 17;
22039566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
22049371c9d4SSatish Balay         ornt[0] = 0;
22059371c9d4SSatish Balay         ornt[1] = 0;
22069371c9d4SSatish Balay         ornt[2] = 0;
22079371c9d4SSatish Balay         ornt[3] = 0;
22089566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 0, ornt));
22092829fed8SMatthew G. Knepley         /* Cell 1 */
22109371c9d4SSatish Balay         cone[0] = 18;
22119371c9d4SSatish Balay         cone[1] = 19;
22129371c9d4SSatish Balay         cone[2] = 14;
22139371c9d4SSatish Balay         cone[3] = 20;
22149566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
22159371c9d4SSatish Balay         ornt[0] = 0;
22169371c9d4SSatish Balay         ornt[1] = 0;
22179371c9d4SSatish Balay         ornt[2] = -1;
22189371c9d4SSatish Balay         ornt[3] = 0;
22199566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 1, ornt));
22202829fed8SMatthew G. Knepley         /* Cell 2 */
22219371c9d4SSatish Balay         cone[0] = 21;
22229371c9d4SSatish Balay         cone[1] = 22;
22239371c9d4SSatish Balay         cone[2] = 18;
22249371c9d4SSatish Balay         cone[3] = 23;
22259566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
22269371c9d4SSatish Balay         ornt[0] = 0;
22279371c9d4SSatish Balay         ornt[1] = 0;
22289371c9d4SSatish Balay         ornt[2] = -1;
22299371c9d4SSatish Balay         ornt[3] = 0;
22309566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 2, ornt));
22312829fed8SMatthew G. Knepley         /* Cell 3 */
22329371c9d4SSatish Balay         cone[0] = 19;
22339371c9d4SSatish Balay         cone[1] = 22;
22349371c9d4SSatish Balay         cone[2] = 24;
22359371c9d4SSatish Balay         cone[3] = 15;
22369566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
22379371c9d4SSatish Balay         ornt[0] = -1;
22389371c9d4SSatish Balay         ornt[1] = -1;
22399371c9d4SSatish Balay         ornt[2] = 0;
22409371c9d4SSatish Balay         ornt[3] = -1;
22419566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 3, ornt));
22422829fed8SMatthew G. Knepley         /* Cell 4 */
22439371c9d4SSatish Balay         cone[0] = 16;
22449371c9d4SSatish Balay         cone[1] = 24;
22459371c9d4SSatish Balay         cone[2] = 21;
22469371c9d4SSatish Balay         cone[3] = 25;
22479566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
22489371c9d4SSatish Balay         ornt[0] = -1;
22499371c9d4SSatish Balay         ornt[1] = -1;
22509371c9d4SSatish Balay         ornt[2] = -1;
22519371c9d4SSatish Balay         ornt[3] = 0;
22529566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 4, ornt));
22532829fed8SMatthew G. Knepley         /* Cell 5 */
22549371c9d4SSatish Balay         cone[0] = 20;
22559371c9d4SSatish Balay         cone[1] = 17;
22569371c9d4SSatish Balay         cone[2] = 25;
22579371c9d4SSatish Balay         cone[3] = 23;
22589566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
22599371c9d4SSatish Balay         ornt[0] = -1;
22609371c9d4SSatish Balay         ornt[1] = -1;
22619371c9d4SSatish Balay         ornt[2] = -1;
22629371c9d4SSatish Balay         ornt[3] = -1;
22639566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 5, ornt));
22642829fed8SMatthew G. Knepley         /* Edges */
22659371c9d4SSatish Balay         cone[0] = 6;
22669371c9d4SSatish Balay         cone[1] = 7;
22679566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
22689371c9d4SSatish Balay         cone[0] = 7;
22699371c9d4SSatish Balay         cone[1] = 8;
22709566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 15, cone));
22719371c9d4SSatish Balay         cone[0] = 8;
22729371c9d4SSatish Balay         cone[1] = 9;
22739566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 16, cone));
22749371c9d4SSatish Balay         cone[0] = 9;
22759371c9d4SSatish Balay         cone[1] = 6;
22769566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 17, cone));
22779371c9d4SSatish Balay         cone[0] = 10;
22789371c9d4SSatish Balay         cone[1] = 11;
22799566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 18, cone));
22809371c9d4SSatish Balay         cone[0] = 11;
22819371c9d4SSatish Balay         cone[1] = 7;
22829566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 19, cone));
22839371c9d4SSatish Balay         cone[0] = 6;
22849371c9d4SSatish Balay         cone[1] = 10;
22859566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 20, cone));
22869371c9d4SSatish Balay         cone[0] = 12;
22879371c9d4SSatish Balay         cone[1] = 13;
22889566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 21, cone));
22899371c9d4SSatish Balay         cone[0] = 13;
22909371c9d4SSatish Balay         cone[1] = 11;
22919566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 22, cone));
22929371c9d4SSatish Balay         cone[0] = 10;
22939371c9d4SSatish Balay         cone[1] = 12;
22949566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 23, cone));
22959371c9d4SSatish Balay         cone[0] = 13;
22969371c9d4SSatish Balay         cone[1] = 8;
22979566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 24, cone));
22989371c9d4SSatish Balay         cone[0] = 12;
22999371c9d4SSatish Balay         cone[1] = 9;
23009566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 25, cone));
230145da822fSValeria Barra       }
23029566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
23039566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
23042829fed8SMatthew G. Knepley       /* Build coordinates */
23059566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2306dd400576SPatrick Sanan       if (rank == 0) {
23079371c9d4SSatish Balay         coordsIn[0 * embedDim + 0] = -R;
23089371c9d4SSatish Balay         coordsIn[0 * embedDim + 1] = R;
23099371c9d4SSatish Balay         coordsIn[0 * embedDim + 2] = -R;
23109371c9d4SSatish Balay         coordsIn[1 * embedDim + 0] = R;
23119371c9d4SSatish Balay         coordsIn[1 * embedDim + 1] = R;
23129371c9d4SSatish Balay         coordsIn[1 * embedDim + 2] = -R;
23139371c9d4SSatish Balay         coordsIn[2 * embedDim + 0] = R;
23149371c9d4SSatish Balay         coordsIn[2 * embedDim + 1] = -R;
23159371c9d4SSatish Balay         coordsIn[2 * embedDim + 2] = -R;
23169371c9d4SSatish Balay         coordsIn[3 * embedDim + 0] = -R;
23179371c9d4SSatish Balay         coordsIn[3 * embedDim + 1] = -R;
23189371c9d4SSatish Balay         coordsIn[3 * embedDim + 2] = -R;
23199371c9d4SSatish Balay         coordsIn[4 * embedDim + 0] = -R;
23209371c9d4SSatish Balay         coordsIn[4 * embedDim + 1] = R;
23219371c9d4SSatish Balay         coordsIn[4 * embedDim + 2] = R;
23229371c9d4SSatish Balay         coordsIn[5 * embedDim + 0] = R;
23239371c9d4SSatish Balay         coordsIn[5 * embedDim + 1] = R;
23249371c9d4SSatish Balay         coordsIn[5 * embedDim + 2] = R;
23259371c9d4SSatish Balay         coordsIn[6 * embedDim + 0] = -R;
23269371c9d4SSatish Balay         coordsIn[6 * embedDim + 1] = -R;
23279371c9d4SSatish Balay         coordsIn[6 * embedDim + 2] = R;
23289371c9d4SSatish Balay         coordsIn[7 * embedDim + 0] = R;
23299371c9d4SSatish Balay         coordsIn[7 * embedDim + 1] = -R;
23309371c9d4SSatish Balay         coordsIn[7 * embedDim + 2] = R;
233165a81367SMatthew G. Knepley       }
233245da822fSValeria Barra     }
233365a81367SMatthew G. Knepley     break;
233465a81367SMatthew G. Knepley   case 3:
2335116ded15SMatthew G. Knepley     if (simplex) {
2336116ded15SMatthew G. Knepley       const PetscReal edgeLen         = 1.0 / PETSC_PHI;
233751a74b61SMatthew G. Knepley       PetscReal       vertexA[4]      = {0.5, 0.5, 0.5, 0.5};
233851a74b61SMatthew G. Knepley       PetscReal       vertexB[4]      = {1.0, 0.0, 0.0, 0.0};
233951a74b61SMatthew G. Knepley       PetscReal       vertexC[4]      = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0};
2340116ded15SMatthew G. Knepley       const PetscInt  degree          = 12;
2341116ded15SMatthew G. Knepley       PetscInt        s[4]            = {1, 1, 1};
23429371c9d4SSatish Balay       PetscInt        evenPerm[12][4] = {
23439371c9d4SSatish Balay         {0, 1, 2, 3},
23449371c9d4SSatish Balay         {0, 2, 3, 1},
23459371c9d4SSatish Balay         {0, 3, 1, 2},
23469371c9d4SSatish Balay         {1, 0, 3, 2},
23479371c9d4SSatish Balay         {1, 2, 0, 3},
23489371c9d4SSatish Balay         {1, 3, 2, 0},
23499371c9d4SSatish Balay         {2, 0, 1, 3},
23509371c9d4SSatish Balay         {2, 1, 3, 0},
23519371c9d4SSatish Balay         {2, 3, 0, 1},
23529371c9d4SSatish Balay         {3, 0, 2, 1},
23539371c9d4SSatish Balay         {3, 1, 0, 2},
23549371c9d4SSatish Balay         {3, 2, 1, 0}
23559371c9d4SSatish Balay       };
2356116ded15SMatthew G. Knepley       PetscInt  cone[4];
2357116ded15SMatthew G. Knepley       PetscInt *graph, p, i, j, k, l;
2358116ded15SMatthew G. Knepley 
23599371c9d4SSatish Balay       vertexA[0] *= R;
23609371c9d4SSatish Balay       vertexA[1] *= R;
23619371c9d4SSatish Balay       vertexA[2] *= R;
23629371c9d4SSatish Balay       vertexA[3] *= R;
23639371c9d4SSatish Balay       vertexB[0] *= R;
23649371c9d4SSatish Balay       vertexB[1] *= R;
23659371c9d4SSatish Balay       vertexB[2] *= R;
23669371c9d4SSatish Balay       vertexB[3] *= R;
23679371c9d4SSatish Balay       vertexC[0] *= R;
23689371c9d4SSatish Balay       vertexC[1] *= R;
23699371c9d4SSatish Balay       vertexC[2] *= R;
23709371c9d4SSatish Balay       vertexC[3] *= R;
2371dd400576SPatrick Sanan       numCells    = rank == 0 ? 600 : 0;
2372dd400576SPatrick Sanan       numVerts    = rank == 0 ? 120 : 0;
2373116ded15SMatthew G. Knepley       firstVertex = numCells;
2374116ded15SMatthew G. Knepley       /* Use the 600-cell, which for a unit sphere has coordinates which are
2375116ded15SMatthew G. Knepley 
2376116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm 1,    \pm 1, \pm 1)                          16
2377116ded15SMatthew G. Knepley                (\pm 1,    0,       0,      0)  all cyclic permutations   8
2378116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm phi, \pm 1/phi, 0)  all even permutations    96
2379116ded15SMatthew G. Knepley 
2380116ded15SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
23816333ae4fSvaleriabarra          length is then given by 1/\phi = 0.61803.
2382116ded15SMatthew G. Knepley 
2383116ded15SMatthew G. Knepley          http://buzzard.pugetsound.edu/sage-practice/ch03s03.html
2384116ded15SMatthew G. Knepley          http://mathworld.wolfram.com/600-Cell.html
2385116ded15SMatthew G. Knepley       */
2386116ded15SMatthew G. Knepley       /* Construct vertices */
23879566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2388116ded15SMatthew G. Knepley       i = 0;
2389dd400576SPatrick Sanan       if (rank == 0) {
2390116ded15SMatthew G. Knepley         for (s[0] = -1; s[0] < 2; s[0] += 2) {
2391116ded15SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
2392116ded15SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
2393116ded15SMatthew G. Knepley               for (s[3] = -1; s[3] < 2; s[3] += 2) {
2394116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d];
2395116ded15SMatthew G. Knepley                 ++i;
2396116ded15SMatthew G. Knepley               }
2397116ded15SMatthew G. Knepley             }
2398116ded15SMatthew G. Knepley           }
2399116ded15SMatthew G. Knepley         }
2400116ded15SMatthew G. Knepley         for (p = 0; p < embedDim; ++p) {
2401116ded15SMatthew G. Knepley           s[1] = s[2] = s[3] = 1;
2402116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2403116ded15SMatthew G. Knepley             for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim];
2404116ded15SMatthew G. Knepley             ++i;
2405116ded15SMatthew G. Knepley           }
2406116ded15SMatthew G. Knepley         }
2407116ded15SMatthew G. Knepley         for (p = 0; p < 12; ++p) {
2408116ded15SMatthew G. Knepley           s[3] = 1;
2409116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2410116ded15SMatthew G. Knepley             for (s[1] = -1; s[1] < 2; s[1] += 2) {
2411116ded15SMatthew G. Knepley               for (s[2] = -1; s[2] < 2; s[2] += 2) {
2412116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]];
2413116ded15SMatthew G. Knepley                 ++i;
2414116ded15SMatthew G. Knepley               }
2415116ded15SMatthew G. Knepley             }
2416116ded15SMatthew G. Knepley           }
2417116ded15SMatthew G. Knepley         }
241845da822fSValeria Barra       }
241963a3b9bcSJacob Faibussowitsch       PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts);
2420116ded15SMatthew G. Knepley       /* Construct graph */
24219566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
2422116ded15SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
2423116ded15SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
24249371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
24259371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
24269371c9d4SSatish Balay             ++k;
24279371c9d4SSatish Balay           }
2428116ded15SMatthew G. Knepley         }
242963a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
2430116ded15SMatthew G. Knepley       }
2431116ded15SMatthew G. Knepley       /* Build Topology */
24329566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
243348a46eb9SPierre Jolivet       for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
24349566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2435116ded15SMatthew G. Knepley       /* Cells */
2436dd400576SPatrick Sanan       if (rank == 0) {
2437116ded15SMatthew G. Knepley         for (i = 0, c = 0; i < numVerts; ++i) {
2438116ded15SMatthew G. Knepley           for (j = 0; j < i; ++j) {
2439116ded15SMatthew G. Knepley             for (k = 0; k < j; ++k) {
2440116ded15SMatthew G. Knepley               for (l = 0; l < k; ++l) {
24419371c9d4SSatish Balay                 if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i] && graph[l * numVerts + i] && graph[l * numVerts + j] && graph[l * numVerts + k]) {
24429371c9d4SSatish Balay                   cone[0] = firstVertex + i;
24439371c9d4SSatish Balay                   cone[1] = firstVertex + j;
24449371c9d4SSatish Balay                   cone[2] = firstVertex + k;
24459371c9d4SSatish Balay                   cone[3] = firstVertex + l;
2446116ded15SMatthew G. Knepley                   /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */
2447116ded15SMatthew G. Knepley                   {
24489371c9d4SSatish Balay                     const PetscInt epsilon[4][4][4][4] = {
24499371c9d4SSatish Balay                       {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},  {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 1}, {0, 0, -1, 0}}, {{0, 0, 0, 0}, {0, 0, 0, -1}, {0, 0, 0, 0}, {0, 1, 0, 0}}, {{0, 0, 0, 0}, {0, 0, 1, 0}, {0, -1, 0, 0}, {0, 0, 0, 0}}},
2450116ded15SMatthew G. Knepley 
24519371c9d4SSatish Balay                       {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, -1}, {0, 0, 1, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},  {{0, 0, 0, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}, {-1, 0, 0, 0}}, {{0, 0, -1, 0}, {0, 0, 0, 0}, {1, 0, 0, 0}, {0, 0, 0, 0}}},
2452116ded15SMatthew G. Knepley 
24539371c9d4SSatish Balay                       {{{0, 0, 0, 0}, {0, 0, 0, 1}, {0, 0, 0, 0}, {0, -1, 0, 0}}, {{0, 0, 0, -1}, {0, 0, 0, 0}, {0, 0, 0, 0}, {1, 0, 0, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}},  {{0, 1, 0, 0}, {-1, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}},
2454116ded15SMatthew G. Knepley 
24559371c9d4SSatish Balay                       {{{0, 0, 0, 0}, {0, 0, -1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}}, {{0, 0, 1, 0}, {0, 0, 0, 0}, {-1, 0, 0, 0}, {0, 0, 0, 0}}, {{0, -1, 0, 0}, {1, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}} }
24569371c9d4SSatish Balay                     };
2457116ded15SMatthew G. Knepley                     PetscReal normal[4];
2458116ded15SMatthew G. Knepley                     PetscInt  e, f, g;
2459116ded15SMatthew G. Knepley 
2460116ded15SMatthew G. Knepley                     for (d = 0; d < embedDim; ++d) {
2461116ded15SMatthew G. Knepley                       normal[d] = 0.0;
2462116ded15SMatthew G. Knepley                       for (e = 0; e < embedDim; ++e) {
2463116ded15SMatthew G. Knepley                         for (f = 0; f < embedDim; ++f) {
2464116ded15SMatthew G. Knepley                           for (g = 0; g < embedDim; ++g) {
2465116ded15SMatthew 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]);
2466116ded15SMatthew G. Knepley                           }
2467116ded15SMatthew G. Knepley                         }
2468116ded15SMatthew G. Knepley                       }
2469116ded15SMatthew G. Knepley                     }
24709371c9d4SSatish Balay                     if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
24719371c9d4SSatish Balay                       PetscInt tmp = cone[1];
24729371c9d4SSatish Balay                       cone[1]      = cone[2];
24739371c9d4SSatish Balay                       cone[2]      = tmp;
24749371c9d4SSatish Balay                     }
2475116ded15SMatthew G. Knepley                   }
24769566063dSJacob Faibussowitsch                   PetscCall(DMPlexSetCone(dm, c++, cone));
2477116ded15SMatthew G. Knepley                 }
2478116ded15SMatthew G. Knepley               }
2479116ded15SMatthew G. Knepley             }
2480116ded15SMatthew G. Knepley           }
2481116ded15SMatthew G. Knepley         }
248245da822fSValeria Barra       }
24839566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
24849566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
24859566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
2486116ded15SMatthew G. Knepley     }
2487f4d061e9SPierre Jolivet     break;
2488d71ae5a4SJacob Faibussowitsch   default:
2489d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim);
249065a81367SMatthew G. Knepley   }
249165a81367SMatthew G. Knepley   /* Create coordinates */
24929566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
24939566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
24949566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim));
24959566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts));
24962829fed8SMatthew G. Knepley   for (v = firstVertex; v < firstVertex + numVerts; ++v) {
24979566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, embedDim));
24989566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim));
24992829fed8SMatthew G. Knepley   }
25009566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
25019566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
25029566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
25039566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, embedDim));
25049566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
25059566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
25069566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
25079566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
25089371c9d4SSatish Balay   for (v = 0; v < numVerts; ++v)
2509ad540459SPierre Jolivet     for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d];
25109566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
25119566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
25129566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
25139566063dSJacob Faibussowitsch   PetscCall(PetscFree(coordsIn));
251451a74b61SMatthew G. Knepley   {
251551a74b61SMatthew G. Knepley     DM          cdm;
251651a74b61SMatthew G. Knepley     PetscDS     cds;
25179318fe57SMatthew G. Knepley     PetscScalar c = R;
251851a74b61SMatthew G. Knepley 
25199566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, snapToSphere));
25209566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
25219566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
25229566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 1, &c));
252351a74b61SMatthew G. Knepley   }
25249318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
25259566063dSJacob Faibussowitsch   if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
25269318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
25279318fe57SMatthew G. Knepley }
25289318fe57SMatthew G. Knepley 
2529b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]);
2530b7f5c055SJed Brown 
2531b7f5c055SJed Brown /*
2532b7f5c055SJed Brown  The Schwarz P implicit surface is
2533b7f5c055SJed Brown 
2534b7f5c055SJed Brown      f(x) = cos(x0) + cos(x1) + cos(x2) = 0
2535b7f5c055SJed Brown */
2536d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
2537d71ae5a4SJacob Faibussowitsch {
2538b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)};
2539b7f5c055SJed Brown   PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)};
2540b7f5c055SJed Brown   f[0]           = c[0] + c[1] + c[2];
2541b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
2542b7f5c055SJed Brown     grad[i] = PETSC_PI * g[i];
2543ad540459SPierre Jolivet     for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.;
2544b7f5c055SJed Brown   }
2545b7f5c055SJed Brown }
2546b7f5c055SJed Brown 
25474663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
2548d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
2549d71ae5a4SJacob Faibussowitsch {
2550ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI);
25514663dae6SJed Brown   return 0;
25524663dae6SJed Brown }
25534663dae6SJed Brown 
2554b7f5c055SJed Brown /*
2555b7f5c055SJed Brown  The Gyroid implicit surface is
2556b7f5c055SJed Brown 
2557b7f5c055SJed 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)
2558b7f5c055SJed Brown 
2559b7f5c055SJed Brown */
2560d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
2561d71ae5a4SJacob Faibussowitsch {
2562b7f5c055SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))};
2563b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))};
2564b7f5c055SJed Brown   f[0]           = s[0] * c[1] + s[1] * c[2] + s[2] * c[0];
2565b7f5c055SJed Brown   grad[0]        = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
2566b7f5c055SJed Brown   grad[1]        = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
2567b7f5c055SJed Brown   grad[2]        = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
2568b7f5c055SJed Brown   hess[0][0]     = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]);
2569b7f5c055SJed Brown   hess[0][1]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2570b7f5c055SJed Brown   hess[0][2]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2571b7f5c055SJed Brown   hess[1][0]     = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]);
2572b7f5c055SJed Brown   hess[1][1]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2573b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
2574b7f5c055SJed Brown   hess[2][0]     = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]);
2575b7f5c055SJed Brown   hess[2][1]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
2576b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
2577b7f5c055SJed Brown }
2578b7f5c055SJed Brown 
25794663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
2580d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
2581d71ae5a4SJacob Faibussowitsch {
25824663dae6SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))};
25834663dae6SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))};
25844663dae6SJed Brown   u[0]           = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
25854663dae6SJed Brown   u[1]           = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
25864663dae6SJed Brown   u[2]           = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
25874663dae6SJed Brown   return 0;
25884663dae6SJed Brown }
25894663dae6SJed Brown 
2590b7f5c055SJed Brown /*
2591b7f5c055SJed Brown    We wish to solve
2592b7f5c055SJed Brown 
2593b7f5c055SJed Brown          min_y || y - x ||^2  subject to f(y) = 0
2594b7f5c055SJed Brown 
2595b7f5c055SJed Brown    Let g(y) = grad(f).  The minimization problem is equivalent to asking to satisfy
2596b7f5c055SJed 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
2597b7f5c055SJed Brown    tangent space and ask for both components in the tangent space to be zero.
2598b7f5c055SJed Brown 
2599b7f5c055SJed Brown    Take g to be a column vector and compute the "full QR" factorization Q R = g,
2600b7f5c055SJed Brown    where Q = I - 2 n n^T is a symmetric orthogonal matrix.
2601b7f5c055SJed Brown    The first column of Q is parallel to g so the remaining two columns span the null space.
2602b7f5c055SJed Brown    Let Qn = Q[:,1:] be those remaining columns.  Then Qn Qn^T is an orthogonal projector into the tangent space.
2603b7f5c055SJed Brown    Since Q is symmetric, this is equivalent to multipyling by Q and taking the last two entries.
2604b7f5c055SJed Brown    In total, we have a system of 3 equations in 3 unknowns:
2605b7f5c055SJed Brown 
2606b7f5c055SJed Brown      f(y) = 0                       1 equation
2607b7f5c055SJed Brown      Qn^T (y - x) = 0               2 equations
2608b7f5c055SJed Brown 
2609b7f5c055SJed Brown    Here, we compute the residual and Jacobian of this system.
2610b7f5c055SJed Brown */
2611d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[])
2612d71ae5a4SJacob Faibussowitsch {
2613b7f5c055SJed Brown   PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])};
2614b7f5c055SJed Brown   PetscReal d[3]     = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])};
26152f0490c0SSatish Balay   PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign;
26169371c9d4SSatish Balay   PetscReal n_y[3][3] = {
26179371c9d4SSatish Balay     {0, 0, 0},
26189371c9d4SSatish Balay     {0, 0, 0},
26199371c9d4SSatish Balay     {0, 0, 0}
26209371c9d4SSatish Balay   };
2621b7f5c055SJed Brown 
2622b7f5c055SJed Brown   feval(yreal, &f, grad, n_y);
2623b7f5c055SJed Brown 
2624b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n[i] = grad[i];
2625b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
2626ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i];
2627b7f5c055SJed Brown 
2628b7f5c055SJed Brown   // Define the Householder reflector
2629b7f5c055SJed Brown   sign = n[0] >= 0 ? 1. : -1.;
2630b7f5c055SJed Brown   n[0] += norm * sign;
2631b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign;
2632b7f5c055SJed Brown 
2633b7f5c055SJed Brown   norm      = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
2634b7f5c055SJed Brown   norm_y[0] = 1. / norm * (n[0] * n_y[0][0]);
2635b7f5c055SJed Brown   norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]);
2636b7f5c055SJed Brown   norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]);
2637b7f5c055SJed Brown 
2638b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
2639b7f5c055SJed Brown     n[i] /= norm;
2640b7f5c055SJed Brown     for (PetscInt j = 0; j < 3; j++) {
2641b7f5c055SJed Brown       // note that n[i] is n_old[i]/norm when executing the code below
2642b7f5c055SJed Brown       n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j];
2643b7f5c055SJed Brown     }
2644b7f5c055SJed Brown   }
2645b7f5c055SJed Brown 
2646b7f5c055SJed Brown   nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2];
2647b7f5c055SJed 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];
2648b7f5c055SJed Brown 
2649b7f5c055SJed Brown   res[0] = f;
2650b7f5c055SJed Brown   res[1] = d[1] - 2 * n[1] * nd;
2651b7f5c055SJed Brown   res[2] = d[2] - 2 * n[2] * nd;
2652b7f5c055SJed Brown   // J[j][i] is J_{ij} (column major)
2653b7f5c055SJed Brown   for (PetscInt j = 0; j < 3; j++) {
2654b7f5c055SJed Brown     J[0 + j * 3] = grad[j];
2655b7f5c055SJed Brown     J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]);
2656b7f5c055SJed Brown     J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]);
2657b7f5c055SJed Brown   }
2658b7f5c055SJed Brown }
2659b7f5c055SJed Brown 
2660b7f5c055SJed Brown /*
2661b7f5c055SJed Brown    Project x to the nearest point on the implicit surface using Newton's method.
2662b7f5c055SJed Brown */
2663d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[])
2664d71ae5a4SJacob Faibussowitsch {
2665b7f5c055SJed Brown   PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess
2666b7f5c055SJed Brown 
2667b7f5c055SJed Brown   PetscFunctionBegin;
2668b7f5c055SJed Brown   for (PetscInt iter = 0; iter < 10; iter++) {
2669b7f5c055SJed Brown     PetscScalar res[3], J[9];
2670b7f5c055SJed Brown     PetscReal   resnorm;
2671b7f5c055SJed Brown     TPSNearestPointResJac(feval, x, y, res, J);
2672b7f5c055SJed Brown     resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2])));
2673b7f5c055SJed Brown     if (0) { // Turn on this monitor if you need to confirm quadratic convergence
267463a3b9bcSJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%" PetscInt_FMT "] res [%g %g %g]\n", iter, (double)PetscRealPart(res[0]), (double)PetscRealPart(res[1]), (double)PetscRealPart(res[2])));
2675b7f5c055SJed Brown     }
2676b7f5c055SJed Brown     if (resnorm < PETSC_SMALL) break;
2677b7f5c055SJed Brown 
2678b7f5c055SJed Brown     // Take the Newton step
26799566063dSJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL));
2680b7f5c055SJed Brown     PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res);
2681b7f5c055SJed Brown   }
2682b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) x[i] = y[i];
2683b7f5c055SJed Brown   PetscFunctionReturn(0);
2684b7f5c055SJed Brown }
2685b7f5c055SJed Brown 
2686b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL};
2687b7f5c055SJed Brown 
2688d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness)
2689d71ae5a4SJacob Faibussowitsch {
2690b7f5c055SJed Brown   PetscMPIInt rank;
2691b7f5c055SJed Brown   PetscInt    topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0;
2692b7f5c055SJed Brown   PetscInt(*edges)[2] = NULL, *edgeSets = NULL;
2693b7f5c055SJed Brown   PetscInt            *cells_flat = NULL;
2694b7f5c055SJed Brown   PetscReal           *vtxCoords  = NULL;
2695b7f5c055SJed Brown   TPSEvaluateFunc      evalFunc   = NULL;
26964663dae6SJed Brown   PetscSimplePointFunc normalFunc = NULL;
2697b7f5c055SJed Brown   DMLabel              label;
2698b7f5c055SJed Brown 
2699b7f5c055SJed Brown   PetscFunctionBegin;
27009566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
270163a3b9bcSJacob Faibussowitsch   PetscCheck((layers != 0) ^ (thickness == 0.), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Layers %" PetscInt_FMT " must be nonzero iff thickness %g is nonzero", layers, (double)thickness);
2702b7f5c055SJed Brown   switch (tpstype) {
2703b7f5c055SJed Brown   case DMPLEX_TPS_SCHWARZ_P:
2704b7f5c055SJed 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");
2705c5853193SPierre Jolivet     if (rank == 0) {
2706b7f5c055SJed Brown       PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn]
2707b7f5c055SJed Brown       PetscInt  Njunctions = 0, Ncuts = 0, Npipes[3], vcount;
2708b7f5c055SJed Brown       PetscReal L = 1;
2709b7f5c055SJed Brown 
2710b7f5c055SJed Brown       Npipes[0]   = (extent[0] + 1) * extent[1] * extent[2];
2711b7f5c055SJed Brown       Npipes[1]   = extent[0] * (extent[1] + 1) * extent[2];
2712b7f5c055SJed Brown       Npipes[2]   = extent[0] * extent[1] * (extent[2] + 1);
2713b7f5c055SJed Brown       Njunctions  = extent[0] * extent[1] * extent[2];
2714b7f5c055SJed Brown       Ncuts       = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]);
2715b7f5c055SJed Brown       numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions;
27169566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords));
27179566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Njunctions, &cells));
27189566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edges));
27199566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets));
2720b7f5c055SJed Brown       // x-normal pipes
2721b7f5c055SJed Brown       vcount = 0;
2722b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0] + 1; i++) {
2723b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2724b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2725b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2726b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * i - 1) * L;
2727b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2728b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2729b7f5c055SJed Brown             }
2730b7f5c055SJed Brown           }
2731b7f5c055SJed Brown         }
2732b7f5c055SJed Brown       }
2733b7f5c055SJed Brown       // y-normal pipes
2734b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2735b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1] + 1; j++) {
2736b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2737b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2738b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2739b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * j - 1) * L;
2740b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2741b7f5c055SJed Brown             }
2742b7f5c055SJed Brown           }
2743b7f5c055SJed Brown         }
2744b7f5c055SJed Brown       }
2745b7f5c055SJed Brown       // z-normal pipes
2746b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2747b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2748b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2] + 1; k++) {
2749b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
2750b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2751b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
2752b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * k - 1) * L;
2753b7f5c055SJed Brown             }
2754b7f5c055SJed Brown           }
2755b7f5c055SJed Brown         }
2756b7f5c055SJed Brown       }
2757b7f5c055SJed Brown       // junctions
2758b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
2759b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
2760b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
2761b7f5c055SJed Brown             const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8;
2762b7f5c055SJed Brown             PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count");
2763b7f5c055SJed Brown             for (PetscInt ii = 0; ii < 2; ii++) {
2764b7f5c055SJed Brown               for (PetscInt jj = 0; jj < 2; jj++) {
2765b7f5c055SJed Brown                 for (PetscInt kk = 0; kk < 2; kk++) {
2766b7f5c055SJed Brown                   double Ls           = (1 - sqrt(2) / 4) * L;
2767b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls;
2768b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls;
2769b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls;
2770b7f5c055SJed Brown                 }
2771b7f5c055SJed Brown               }
2772b7f5c055SJed Brown             }
2773b7f5c055SJed Brown             const PetscInt jfaces[3][2][4] = {
2774b7f5c055SJed Brown               {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned
2775b7f5c055SJed Brown               {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned
2776b7f5c055SJed Brown               {{6, 2, 0, 4}, {7, 3, 1, 5}}  // z-aligned
2777b7f5c055SJed Brown             };
2778b7f5c055SJed Brown             const PetscInt pipe_lo[3] = {// vertex numbers of pipes
27799371c9d4SSatish Balay                                          ((i * extent[1] + j) * extent[2] + k) * 4, ((i * (extent[1] + 1) + j) * extent[2] + k + Npipes[0]) * 4, ((i * extent[1] + j) * (extent[2] + 1) + k + Npipes[0] + Npipes[1]) * 4};
2780b7f5c055SJed Brown             const PetscInt pipe_hi[3] = {// vertex numbers of pipes
27819371c9d4SSatish Balay                                          (((i + 1) * extent[1] + j) * extent[2] + k) * 4, ((i * (extent[1] + 1) + j + 1) * extent[2] + k + Npipes[0]) * 4, ((i * extent[1] + j) * (extent[2] + 1) + k + 1 + Npipes[0] + Npipes[1]) * 4};
2782b7f5c055SJed Brown             for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z
2783b7f5c055SJed Brown               const PetscInt ijk[3] = {i, j, k};
2784b7f5c055SJed Brown               for (PetscInt l = 0; l < 4; l++) { // rotations
2785b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l;
2786b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l];
2787b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4];
2788b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4;
2789b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l];
2790b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l;
2791b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4;
2792b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4];
2793b7f5c055SJed Brown                 if (ijk[dir] == 0) {
2794b7f5c055SJed Brown                   edges[numEdges][0] = pipe_lo[dir] + l;
2795b7f5c055SJed Brown                   edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4;
2796b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 1;
2797b7f5c055SJed Brown                   numEdges++;
2798b7f5c055SJed Brown                 }
2799b7f5c055SJed Brown                 if (ijk[dir] + 1 == extent[dir]) {
2800b7f5c055SJed Brown                   edges[numEdges][0] = pipe_hi[dir] + l;
2801b7f5c055SJed Brown                   edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4;
2802b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 2;
2803b7f5c055SJed Brown                   numEdges++;
2804b7f5c055SJed Brown                 }
2805b7f5c055SJed Brown               }
2806b7f5c055SJed Brown             }
2807b7f5c055SJed Brown           }
2808b7f5c055SJed Brown         }
2809b7f5c055SJed Brown       }
281063a3b9bcSJacob Faibussowitsch       PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts);
2811b7f5c055SJed Brown       numFaces   = 24 * Njunctions;
2812b7f5c055SJed Brown       cells_flat = cells[0][0][0];
2813b7f5c055SJed Brown     }
2814b7f5c055SJed Brown     evalFunc   = TPSEvaluate_SchwarzP;
28154663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_SchwarzP;
2816b7f5c055SJed Brown     break;
2817b7f5c055SJed Brown   case DMPLEX_TPS_GYROID:
2818c5853193SPierre Jolivet     if (rank == 0) {
2819b7f5c055SJed Brown       // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set
2820b7f5c055SJed Brown       //
2821b7f5c055SJed 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)
2822b7f5c055SJed Brown       //
2823b7f5c055SJed Brown       // on the cell [0,2]^3.
2824b7f5c055SJed Brown       //
2825b7f5c055SJed Brown       // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2].
2826b7f5c055SJed Brown       // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins
2827b7f5c055SJed Brown       // like a boomerang:
2828b7f5c055SJed Brown       //
2829b7f5c055SJed Brown       //     z = 0          z = 1/4        z = 1/2        z = 3/4     //
2830b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2831b7f5c055SJed Brown       //                                                              //
2832b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2833b7f5c055SJed Brown       //      \                                   /            \      //
2834b7f5c055SJed Brown       //       \            `-_   _-'            /              }     //
2835b7f5c055SJed Brown       //        *-_            `-'            _-'              /      //
2836b7f5c055SJed Brown       //     +     `-+      +       +      +-'     +      +   /   +   //
2837b7f5c055SJed Brown       //                                                              //
2838b7f5c055SJed Brown       //                                                              //
2839b7f5c055SJed Brown       //     z = 1          z = 5/4        z = 3/2        z = 7/4     //
2840b7f5c055SJed Brown       //     -----          -------        -------        -------     //
2841b7f5c055SJed Brown       //                                                              //
2842b7f5c055SJed Brown       //     +-_     +      +       +      +     _-+      +   /   +   //
2843b7f5c055SJed Brown       //        `-_            _-_            _-`            /        //
2844b7f5c055SJed Brown       //           \        _-'   `-_        /              {         //
2845b7f5c055SJed Brown       //            \                       /                \        //
2846b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
2847b7f5c055SJed Brown       //
2848b7f5c055SJed Brown       //
2849b7f5c055SJed Brown       // This course mesh approximates each of these slices by two line segments,
2850b7f5c055SJed Brown       // and then connects the segments in consecutive layers with quadrilateral faces.
2851b7f5c055SJed Brown       // All of the end points of the segments are multiples of 1/4 except for the
2852b7f5c055SJed Brown       // point * in the picture for z = 0 above and the similar points in other layers.
2853b7f5c055SJed Brown       // That point is at (gamma, gamma, 0), where gamma is calculated below.
2854b7f5c055SJed Brown       //
2855b7f5c055SJed Brown       // The column  [1,2]x[1,2]x[0,2] looks the same as this column;
2856b7f5c055SJed Brown       // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images.
2857b7f5c055SJed Brown       //
2858b7f5c055SJed Brown       // As for how this method turned into the names given to the vertices:
2859b7f5c055SJed Brown       // that was not systematic, it was just the way it worked out in my handwritten notes.
2860b7f5c055SJed Brown 
2861b7f5c055SJed Brown       PetscInt facesPerBlock = 64;
2862b7f5c055SJed Brown       PetscInt vertsPerBlock = 56;
2863b7f5c055SJed Brown       PetscInt extentPlus[3];
2864b7f5c055SJed Brown       PetscInt numBlocks, numBlocksPlus;
28659371c9d4SSatish Balay       const PetscInt A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7, II = 8, J = 9, K = 10, L = 11, M = 12, N = 13, O = 14, P = 15, Q = 16, R = 17, S = 18, T = 19, U = 20, V = 21, W = 22, X = 23, Y = 24, Z = 25, Ap = 26, Bp = 27, Cp = 28, Dp = 29, Ep = 30, Fp = 31, Gp = 32, Hp = 33, Ip = 34, Jp = 35, Kp = 36, Lp = 37, Mp = 38, Np = 39, Op = 40, Pp = 41, Qp = 42, Rp = 43, Sp = 44, Tp = 45, Up = 46, Vp = 47, Wp = 48, Xp = 49, Yp = 50, Zp = 51, Aq = 52, Bq = 53, Cq = 54, Dq = 55;
28669371c9d4SSatish Balay       const PetscInt pattern[64][4] = {
28679371c9d4SSatish Balay   /* face to vertex within the coarse discretization of a single gyroid block */
2868b7f5c055SJed Brown   /* layer 0 */
28699371c9d4SSatish Balay         {A,           C,           K,           G          },
28709371c9d4SSatish Balay         {C,           B,           II,          K          },
28719371c9d4SSatish Balay         {D,           A,           H,           L          },
28729371c9d4SSatish Balay         {B + 56 * 1,  D,           L,           J          },
28739371c9d4SSatish Balay         {E,           B + 56 * 1,  J,           N          },
28749371c9d4SSatish Balay         {A + 56 * 2,  E,           N,           H + 56 * 2 },
28759371c9d4SSatish Balay         {F,           A + 56 * 2,  G + 56 * 2,  M          },
28769371c9d4SSatish Balay         {B,           F,           M,           II         },
2877b7f5c055SJed Brown  /* layer 1 */
28789371c9d4SSatish Balay         {G,           K,           Q,           O          },
28799371c9d4SSatish Balay         {K,           II,          P,           Q          },
28809371c9d4SSatish Balay         {L,           H,           O + 56 * 1,  R          },
28819371c9d4SSatish Balay         {J,           L,           R,           P          },
28829371c9d4SSatish Balay         {N,           J,           P,           S          },
28839371c9d4SSatish Balay         {H + 56 * 2,  N,           S,           O + 56 * 3 },
28849371c9d4SSatish Balay         {M,           G + 56 * 2,  O + 56 * 2,  T          },
28859371c9d4SSatish Balay         {II,          M,           T,           P          },
2886b7f5c055SJed Brown  /* layer 2 */
28879371c9d4SSatish Balay         {O,           Q,           Y,           U          },
28889371c9d4SSatish Balay         {Q,           P,           W,           Y          },
28899371c9d4SSatish Balay         {R,           O + 56 * 1,  U + 56 * 1,  Ap         },
28909371c9d4SSatish Balay         {P,           R,           Ap,          W          },
28919371c9d4SSatish Balay         {S,           P,           X,           Bp         },
28929371c9d4SSatish Balay         {O + 56 * 3,  S,           Bp,          V + 56 * 1 },
28939371c9d4SSatish Balay         {T,           O + 56 * 2,  V,           Z          },
28949371c9d4SSatish Balay         {P,           T,           Z,           X          },
2895b7f5c055SJed Brown  /* layer 3 */
28969371c9d4SSatish Balay         {U,           Y,           Ep,          Dp         },
28979371c9d4SSatish Balay         {Y,           W,           Cp,          Ep         },
28989371c9d4SSatish Balay         {Ap,          U + 56 * 1,  Dp + 56 * 1, Gp         },
28999371c9d4SSatish Balay         {W,           Ap,          Gp,          Cp         },
29009371c9d4SSatish Balay         {Bp,          X,           Cp + 56 * 2, Fp         },
29019371c9d4SSatish Balay         {V + 56 * 1,  Bp,          Fp,          Dp + 56 * 1},
29029371c9d4SSatish Balay         {Z,           V,           Dp,          Hp         },
29039371c9d4SSatish Balay         {X,           Z,           Hp,          Cp + 56 * 2},
2904b7f5c055SJed Brown  /* layer 4 */
29059371c9d4SSatish Balay         {Dp,          Ep,          Mp,          Kp         },
29069371c9d4SSatish Balay         {Ep,          Cp,          Ip,          Mp         },
29079371c9d4SSatish Balay         {Gp,          Dp + 56 * 1, Lp,          Np         },
29089371c9d4SSatish Balay         {Cp,          Gp,          Np,          Jp         },
29099371c9d4SSatish Balay         {Fp,          Cp + 56 * 2, Jp + 56 * 2, Pp         },
29109371c9d4SSatish Balay         {Dp + 56 * 1, Fp,          Pp,          Lp         },
29119371c9d4SSatish Balay         {Hp,          Dp,          Kp,          Op         },
29129371c9d4SSatish Balay         {Cp + 56 * 2, Hp,          Op,          Ip + 56 * 2},
2913b7f5c055SJed Brown  /* layer 5 */
29149371c9d4SSatish Balay         {Kp,          Mp,          Sp,          Rp         },
29159371c9d4SSatish Balay         {Mp,          Ip,          Qp,          Sp         },
29169371c9d4SSatish Balay         {Np,          Lp,          Rp,          Tp         },
29179371c9d4SSatish Balay         {Jp,          Np,          Tp,          Qp + 56 * 1},
29189371c9d4SSatish Balay         {Pp,          Jp + 56 * 2, Qp + 56 * 3, Up         },
29199371c9d4SSatish Balay         {Lp,          Pp,          Up,          Rp         },
29209371c9d4SSatish Balay         {Op,          Kp,          Rp,          Vp         },
29219371c9d4SSatish Balay         {Ip + 56 * 2, Op,          Vp,          Qp + 56 * 2},
2922b7f5c055SJed Brown  /* layer 6 */
29239371c9d4SSatish Balay         {Rp,          Sp,          Aq,          Yp         },
29249371c9d4SSatish Balay         {Sp,          Qp,          Wp,          Aq         },
29259371c9d4SSatish Balay         {Tp,          Rp,          Yp,          Cq         },
29269371c9d4SSatish Balay         {Qp + 56 * 1, Tp,          Cq,          Wp + 56 * 1},
29279371c9d4SSatish Balay         {Up,          Qp + 56 * 3, Xp + 56 * 1, Dq         },
29289371c9d4SSatish Balay         {Rp,          Up,          Dq,          Zp         },
29299371c9d4SSatish Balay         {Vp,          Rp,          Zp,          Bq         },
29309371c9d4SSatish Balay         {Qp + 56 * 2, Vp,          Bq,          Xp         },
2931b7f5c055SJed Brown  /* layer 7 (the top is the periodic image of the bottom of layer 0) */
29329371c9d4SSatish Balay         {Yp,          Aq,          C + 56 * 4,  A + 56 * 4 },
29339371c9d4SSatish Balay         {Aq,          Wp,          B + 56 * 4,  C + 56 * 4 },
29349371c9d4SSatish Balay         {Cq,          Yp,          A + 56 * 4,  D + 56 * 4 },
29359371c9d4SSatish Balay         {Wp + 56 * 1, Cq,          D + 56 * 4,  B + 56 * 5 },
29369371c9d4SSatish Balay         {Dq,          Xp + 56 * 1, B + 56 * 5,  E + 56 * 4 },
29379371c9d4SSatish Balay         {Zp,          Dq,          E + 56 * 4,  A + 56 * 6 },
29389371c9d4SSatish Balay         {Bq,          Zp,          A + 56 * 6,  F + 56 * 4 },
29399371c9d4SSatish Balay         {Xp,          Bq,          F + 56 * 4,  B + 56 * 4 }
2940b7f5c055SJed Brown       };
2941b7f5c055SJed Brown       const PetscReal gamma                = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI;
29429371c9d4SSatish Balay       const PetscReal patternCoords[56][3] = {
2943bee3fc89SBarry Smith         {1.,        0.,        0.  }, /* A  */
2944bee3fc89SBarry Smith         {0.,        1.,        0.  }, /* B  */
2945bee3fc89SBarry Smith         {gamma,     gamma,     0.  }, /* C  */
2946bee3fc89SBarry Smith         {1 + gamma, 1 - gamma, 0.  }, /* D  */
2947bee3fc89SBarry Smith         {2 - gamma, 2 - gamma, 0.  }, /* E  */
2948bee3fc89SBarry Smith         {1 - gamma, 1 + gamma, 0.  }, /* F  */
2949b7f5c055SJed Brown 
2950bee3fc89SBarry Smith         {.5,        0,         .25 }, /* G  */
2951bee3fc89SBarry Smith         {1.5,       0.,        .25 }, /* H  */
2952bee3fc89SBarry Smith         {.5,        1.,        .25 }, /* II */
2953bee3fc89SBarry Smith         {1.5,       1.,        .25 }, /* J  */
2954bee3fc89SBarry Smith         {.25,       .5,        .25 }, /* K  */
2955bee3fc89SBarry Smith         {1.25,      .5,        .25 }, /* L  */
2956bee3fc89SBarry Smith         {.75,       1.5,       .25 }, /* M  */
2957bee3fc89SBarry Smith         {1.75,      1.5,       .25 }, /* N  */
2958b7f5c055SJed Brown 
2959bee3fc89SBarry Smith         {0.,        0.,        .5  }, /* O  */
2960bee3fc89SBarry Smith         {1.,        1.,        .5  }, /* P  */
2961bee3fc89SBarry Smith         {gamma,     1 - gamma, .5  }, /* Q  */
2962bee3fc89SBarry Smith         {1 + gamma, gamma,     .5  }, /* R  */
2963bee3fc89SBarry Smith         {2 - gamma, 1 + gamma, .5  }, /* S  */
2964bee3fc89SBarry Smith         {1 - gamma, 2 - gamma, .5  }, /* T  */
2965b7f5c055SJed Brown 
2966bee3fc89SBarry Smith         {0.,        .5,        .75 }, /* U  */
2967bee3fc89SBarry Smith         {0.,        1.5,       .75 }, /* V  */
2968bee3fc89SBarry Smith         {1.,        .5,        .75 }, /* W  */
2969bee3fc89SBarry Smith         {1.,        1.5,       .75 }, /* X  */
2970bee3fc89SBarry Smith         {.5,        .75,       .75 }, /* Y  */
2971bee3fc89SBarry Smith         {.5,        1.75,      .75 }, /* Z  */
2972bee3fc89SBarry Smith         {1.5,       .25,       .75 }, /* Ap */
2973bee3fc89SBarry Smith         {1.5,       1.25,      .75 }, /* Bp */
2974b7f5c055SJed Brown 
2975bee3fc89SBarry Smith         {1.,        0.,        1.  }, /* Cp */
2976bee3fc89SBarry Smith         {0.,        1.,        1.  }, /* Dp */
2977bee3fc89SBarry Smith         {1 - gamma, 1 - gamma, 1.  }, /* Ep */
2978bee3fc89SBarry Smith         {1 + gamma, 1 + gamma, 1.  }, /* Fp */
2979bee3fc89SBarry Smith         {2 - gamma, gamma,     1.  }, /* Gp */
2980bee3fc89SBarry Smith         {gamma,     2 - gamma, 1.  }, /* Hp */
2981b7f5c055SJed Brown 
2982bee3fc89SBarry Smith         {.5,        0.,        1.25}, /* Ip */
2983bee3fc89SBarry Smith         {1.5,       0.,        1.25}, /* Jp */
2984bee3fc89SBarry Smith         {.5,        1.,        1.25}, /* Kp */
2985bee3fc89SBarry Smith         {1.5,       1.,        1.25}, /* Lp */
2986bee3fc89SBarry Smith         {.75,       .5,        1.25}, /* Mp */
2987bee3fc89SBarry Smith         {1.75,      .5,        1.25}, /* Np */
2988bee3fc89SBarry Smith         {.25,       1.5,       1.25}, /* Op */
2989bee3fc89SBarry Smith         {1.25,      1.5,       1.25}, /* Pp */
2990b7f5c055SJed Brown 
2991bee3fc89SBarry Smith         {0.,        0.,        1.5 }, /* Qp */
2992bee3fc89SBarry Smith         {1.,        1.,        1.5 }, /* Rp */
2993bee3fc89SBarry Smith         {1 - gamma, gamma,     1.5 }, /* Sp */
2994bee3fc89SBarry Smith         {2 - gamma, 1 - gamma, 1.5 }, /* Tp */
2995bee3fc89SBarry Smith         {1 + gamma, 2 - gamma, 1.5 }, /* Up */
2996bee3fc89SBarry Smith         {gamma,     1 + gamma, 1.5 }, /* Vp */
2997b7f5c055SJed Brown 
2998bee3fc89SBarry Smith         {0.,        .5,        1.75}, /* Wp */
2999bee3fc89SBarry Smith         {0.,        1.5,       1.75}, /* Xp */
3000bee3fc89SBarry Smith         {1.,        .5,        1.75}, /* Yp */
3001bee3fc89SBarry Smith         {1.,        1.5,       1.75}, /* Zp */
3002bee3fc89SBarry Smith         {.5,        .25,       1.75}, /* Aq */
3003bee3fc89SBarry Smith         {.5,        1.25,      1.75}, /* Bq */
3004bee3fc89SBarry Smith         {1.5,       .75,       1.75}, /* Cq */
3005bee3fc89SBarry Smith         {1.5,       1.75,      1.75}, /* Dq */
3006b7f5c055SJed Brown       };
3007b7f5c055SJed Brown       PetscInt(*cells)[64][4] = NULL;
3008b7f5c055SJed Brown       PetscBool *seen;
3009b7f5c055SJed Brown       PetscInt  *vertToTrueVert;
3010b7f5c055SJed Brown       PetscInt   count;
3011b7f5c055SJed Brown 
3012b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1;
3013b7f5c055SJed Brown       numBlocks = 1;
3014b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i];
3015b7f5c055SJed Brown       numBlocksPlus = 1;
3016b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i];
3017b7f5c055SJed Brown       numFaces = numBlocks * facesPerBlock;
30189566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocks, &cells));
30199566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen));
3020b7f5c055SJed Brown       for (PetscInt k = 0; k < extent[2]; k++) {
3021b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3022b7f5c055SJed Brown           for (PetscInt i = 0; i < extent[0]; i++) {
3023b7f5c055SJed Brown             for (PetscInt f = 0; f < facesPerBlock; f++) {
3024b7f5c055SJed Brown               for (PetscInt v = 0; v < 4; v++) {
3025b7f5c055SJed Brown                 PetscInt vertRaw     = pattern[f][v];
3026b7f5c055SJed Brown                 PetscInt blockidx    = vertRaw / 56;
3027b7f5c055SJed Brown                 PetscInt patternvert = vertRaw % 56;
3028b7f5c055SJed Brown                 PetscInt xplus       = (blockidx & 1);
3029b7f5c055SJed Brown                 PetscInt yplus       = (blockidx & 2) >> 1;
3030b7f5c055SJed Brown                 PetscInt zplus       = (blockidx & 4) >> 2;
3031b7f5c055SJed Brown                 PetscInt zcoord      = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus);
3032b7f5c055SJed Brown                 PetscInt ycoord      = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus);
3033b7f5c055SJed Brown                 PetscInt xcoord      = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus);
3034b7f5c055SJed Brown                 PetscInt vert        = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert;
3035b7f5c055SJed Brown 
3036b7f5c055SJed Brown                 cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert;
3037b7f5c055SJed Brown                 seen[vert]                                       = PETSC_TRUE;
3038b7f5c055SJed Brown               }
3039b7f5c055SJed Brown             }
3040b7f5c055SJed Brown           }
3041b7f5c055SJed Brown         }
3042b7f5c055SJed Brown       }
30439371c9d4SSatish Balay       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++)
30449371c9d4SSatish Balay         if (seen[i]) numVertices++;
3045b7f5c055SJed Brown       count = 0;
30469566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert));
30479566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords));
3048b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1;
3049b7f5c055SJed Brown       for (PetscInt k = 0; k < extentPlus[2]; k++) {
3050b7f5c055SJed Brown         for (PetscInt j = 0; j < extentPlus[1]; j++) {
3051b7f5c055SJed Brown           for (PetscInt i = 0; i < extentPlus[0]; i++) {
3052b7f5c055SJed Brown             for (PetscInt v = 0; v < vertsPerBlock; v++) {
3053b7f5c055SJed Brown               PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v;
3054b7f5c055SJed Brown 
3055b7f5c055SJed Brown               if (seen[vIdx]) {
3056b7f5c055SJed Brown                 PetscInt thisVert;
3057b7f5c055SJed Brown 
3058b7f5c055SJed Brown                 vertToTrueVert[vIdx] = thisVert = count++;
3059b7f5c055SJed Brown 
3060b7f5c055SJed Brown                 for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d];
3061b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 0] += i * 2;
3062b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 1] += j * 2;
3063b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 2] += k * 2;
3064b7f5c055SJed Brown               }
3065b7f5c055SJed Brown             }
3066b7f5c055SJed Brown           }
3067b7f5c055SJed Brown         }
3068b7f5c055SJed Brown       }
3069b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocks; i++) {
3070b7f5c055SJed Brown         for (PetscInt f = 0; f < facesPerBlock; f++) {
3071ad540459SPierre Jolivet           for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]];
3072b7f5c055SJed Brown         }
3073b7f5c055SJed Brown       }
30749566063dSJacob Faibussowitsch       PetscCall(PetscFree(vertToTrueVert));
30759566063dSJacob Faibussowitsch       PetscCall(PetscFree(seen));
3076b7f5c055SJed Brown       cells_flat = cells[0][0];
3077b7f5c055SJed Brown       numEdges   = 0;
3078b7f5c055SJed Brown       for (PetscInt i = 0; i < numFaces; i++) {
3079b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3080b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3081b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3082b7f5c055SJed Brown 
3083b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3084b7f5c055SJed Brown             if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) {
3085b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++;
3086b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++;
3087b7f5c055SJed Brown             }
3088b7f5c055SJed Brown           }
3089b7f5c055SJed Brown         }
3090b7f5c055SJed Brown       }
30919566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edges));
30929566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edgeSets));
3093b7f5c055SJed Brown       for (PetscInt edge = 0, i = 0; i < numFaces; i++) {
3094b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3095b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3096b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3097b7f5c055SJed Brown 
3098b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3099b7f5c055SJed Brown             if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) {
3100b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) {
3101b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3102b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3103b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d;
3104b7f5c055SJed Brown               }
3105b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) {
3106b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3107b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3108b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d + 1;
3109b7f5c055SJed Brown               }
3110b7f5c055SJed Brown             }
3111b7f5c055SJed Brown           }
3112b7f5c055SJed Brown         }
3113b7f5c055SJed Brown       }
3114b7f5c055SJed Brown     }
3115b7f5c055SJed Brown     evalFunc   = TPSEvaluate_Gyroid;
31164663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_Gyroid;
3117b7f5c055SJed Brown     break;
3118b7f5c055SJed Brown   }
3119b7f5c055SJed Brown 
31209566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, topoDim));
3121c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat));
31229566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL));
31239566063dSJacob Faibussowitsch   PetscCall(PetscFree(cells_flat));
3124b7f5c055SJed Brown   {
3125b7f5c055SJed Brown     DM idm;
31269566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
312769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &idm));
3128b7f5c055SJed Brown   }
3129c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords));
31309566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL));
31319566063dSJacob Faibussowitsch   PetscCall(PetscFree(vtxCoords));
3132b7f5c055SJed Brown 
31339566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
31349566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
3135b7f5c055SJed Brown   for (PetscInt e = 0; e < numEdges; e++) {
3136b7f5c055SJed Brown     PetscInt        njoin;
3137b7f5c055SJed Brown     const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]};
31389566063dSJacob Faibussowitsch     PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join));
313963a3b9bcSJacob Faibussowitsch     PetscCheck(njoin == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected unique join of vertices %" PetscInt_FMT " and %" PetscInt_FMT, edges[e][0], edges[e][1]);
31409566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(label, join[0], edgeSets[e]));
31419566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join));
3142b7f5c055SJed Brown   }
31439566063dSJacob Faibussowitsch   PetscCall(PetscFree(edges));
31449566063dSJacob Faibussowitsch   PetscCall(PetscFree(edgeSets));
31451436d7faSJed Brown   if (tps_distribute) {
31461436d7faSJed Brown     DM               pdm = NULL;
31471436d7faSJed Brown     PetscPartitioner part;
31481436d7faSJed Brown 
31499566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
31509566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
31519566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm));
315248a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
31531436d7faSJed Brown     // Do not auto-distribute again
31549566063dSJacob Faibussowitsch     PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
31551436d7faSJed Brown   }
3156b7f5c055SJed Brown 
31579566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
3158b7f5c055SJed Brown   for (PetscInt refine = 0; refine < refinements; refine++) {
3159b7f5c055SJed Brown     PetscInt     m;
3160b7f5c055SJed Brown     DM           dmf;
3161b7f5c055SJed Brown     Vec          X;
3162b7f5c055SJed Brown     PetscScalar *x;
31639566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf));
316469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmf));
3165b7f5c055SJed Brown 
31669566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &X));
31679566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(X, &m));
31689566063dSJacob Faibussowitsch     PetscCall(VecGetArray(X, &x));
316948a46eb9SPierre Jolivet     for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i]));
31709566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(X, &x));
3171b7f5c055SJed Brown   }
3172b7f5c055SJed Brown 
3173b7f5c055SJed Brown   // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices.
31749566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
31759566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, label));
3176b7f5c055SJed Brown 
3177b7f5c055SJed Brown   if (thickness > 0) {
31784663dae6SJed Brown     DM              edm, cdm, ecdm;
31794663dae6SJed Brown     DMPlexTransform tr;
31804663dae6SJed Brown     const char     *prefix;
31814663dae6SJed Brown     PetscOptions    options;
31824663dae6SJed Brown     // Code from DMPlexExtrude
31834663dae6SJed Brown     PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr));
31844663dae6SJed Brown     PetscCall(DMPlexTransformSetDM(tr, dm));
31854663dae6SJed Brown     PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE));
31864663dae6SJed Brown     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
31874663dae6SJed Brown     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix));
31884663dae6SJed Brown     PetscCall(PetscObjectGetOptions((PetscObject)dm, &options));
31894663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, options));
31904663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers));
31914663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness));
31924663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE));
31934663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE));
31944663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc));
31954663dae6SJed Brown     PetscCall(DMPlexTransformSetFromOptions(tr));
31964663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL));
31974663dae6SJed Brown     PetscCall(DMPlexTransformSetUp(tr));
31984663dae6SJed Brown     PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view"));
31994663dae6SJed Brown     PetscCall(DMPlexTransformApply(tr, dm, &edm));
32004663dae6SJed Brown     PetscCall(DMCopyDisc(dm, edm));
32014663dae6SJed Brown     PetscCall(DMGetCoordinateDM(dm, &cdm));
32024663dae6SJed Brown     PetscCall(DMGetCoordinateDM(edm, &ecdm));
32034663dae6SJed Brown     PetscCall(DMCopyDisc(cdm, ecdm));
32044663dae6SJed Brown     PetscCall(DMPlexTransformCreateDiscLabels(tr, edm));
32054663dae6SJed Brown     PetscCall(DMPlexTransformDestroy(&tr));
32064663dae6SJed Brown     if (edm) {
32074663dae6SJed Brown       ((DM_Plex *)edm->data)->printFEM    = ((DM_Plex *)dm->data)->printFEM;
32084663dae6SJed Brown       ((DM_Plex *)edm->data)->printL2     = ((DM_Plex *)dm->data)->printL2;
3209f5867de0SMatthew G. Knepley       ((DM_Plex *)edm->data)->printLocate = ((DM_Plex *)dm->data)->printLocate;
32104663dae6SJed Brown     }
321169d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
3212b7f5c055SJed Brown   }
3213b7f5c055SJed Brown   PetscFunctionReturn(0);
3214b7f5c055SJed Brown }
3215b7f5c055SJed Brown 
3216b7f5c055SJed Brown /*@
3217b7f5c055SJed Brown   DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface
3218b7f5c055SJed Brown 
3219b7f5c055SJed Brown   Collective
3220b7f5c055SJed Brown 
3221b7f5c055SJed Brown   Input Parameters:
3222b7f5c055SJed Brown + comm   - The communicator for the DM object
3223b7f5c055SJed Brown . tpstype - Type of triply-periodic surface
3224b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction
3225b7f5c055SJed Brown . periodic - array of length 3 with periodicity, or NULL for non-periodic
32261436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable)
3227817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh
32281436d7faSJed Brown . layers - Number of cell layers extruded in normal direction
3229817da375SSatish Balay - thickness - Thickness in normal direction
3230b7f5c055SJed Brown 
3231b7f5c055SJed Brown   Output Parameter:
3232b7f5c055SJed Brown . dm  - The DM object
3233b7f5c055SJed Brown 
3234b7f5c055SJed Brown   Notes:
3235b7f5c055SJed 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.
3236b7f5c055SJed Brown   https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22) and can be cut with "clean" boundaries.
3237b7f5c055SJed 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.
3238b7f5c055SJed Brown   Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested.
3239b7f5c055SJed Brown   On each refinement, all vertices are projected to their nearest point on the surface.
3240b7f5c055SJed Brown   This projection could readily be extended to related surfaces.
3241b7f5c055SJed Brown 
3242b7f5c055SJed Brown   The face (edge) sets for the Schwarz P surface are numbered 1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z).
3243b7f5c055SJed Brown   When the mesh is refined, "Face Sets" contain the new vertices (created during refinement).  Use DMPlexLabelComplete() to propagate to coarse-level vertices.
3244b7f5c055SJed Brown 
3245b7f5c055SJed Brown   References:
3246606c0280SSatish 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
3247b7f5c055SJed Brown 
3248b7f5c055SJed Brown   Developer Notes:
3249b7f5c055SJed Brown   The Gyroid mesh does not currently mark boundary sets.
3250b7f5c055SJed Brown 
3251b7f5c055SJed Brown   Level: beginner
3252b7f5c055SJed Brown 
3253db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()`
3254b7f5c055SJed Brown @*/
3255d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateTPSMesh(MPI_Comm comm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness, DM *dm)
3256d71ae5a4SJacob Faibussowitsch {
3257b7f5c055SJed Brown   PetscFunctionBegin;
32589566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
32599566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
32609566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness));
3261b7f5c055SJed Brown   PetscFunctionReturn(0);
3262b7f5c055SJed Brown }
3263b7f5c055SJed Brown 
32649318fe57SMatthew G. Knepley /*@
32659318fe57SMatthew G. Knepley   DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d.
32669318fe57SMatthew G. Knepley 
32679318fe57SMatthew G. Knepley   Collective
32689318fe57SMatthew G. Knepley 
32699318fe57SMatthew G. Knepley   Input Parameters:
32709318fe57SMatthew G. Knepley + comm    - The communicator for the DM object
32719318fe57SMatthew G. Knepley . dim     - The dimension
32729318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells
32739318fe57SMatthew G. Knepley - R       - The radius
32749318fe57SMatthew G. Knepley 
32759318fe57SMatthew G. Knepley   Output Parameter:
32769318fe57SMatthew G. Knepley . dm  - The DM object
32779318fe57SMatthew G. Knepley 
32789318fe57SMatthew G. Knepley   Level: beginner
32799318fe57SMatthew G. Knepley 
3280db781477SPatrick Sanan .seealso: `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
32819318fe57SMatthew G. Knepley @*/
3282d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm)
3283d71ae5a4SJacob Faibussowitsch {
32849318fe57SMatthew G. Knepley   PetscFunctionBegin;
32859318fe57SMatthew G. Knepley   PetscValidPointer(dm, 5);
32869566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
32879566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
32889566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R));
32899318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
32909318fe57SMatthew G. Knepley }
32919318fe57SMatthew G. Knepley 
3292d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R)
3293d71ae5a4SJacob Faibussowitsch {
32949318fe57SMatthew G. Knepley   DM      sdm, vol;
32959318fe57SMatthew G. Knepley   DMLabel bdlabel;
32969318fe57SMatthew G. Knepley 
32979318fe57SMatthew G. Knepley   PetscFunctionBegin;
32989566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm));
32999566063dSJacob Faibussowitsch   PetscCall(DMSetType(sdm, DMPLEX));
33009566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sdm, "bd_"));
33019566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R));
33029566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(sdm));
33039566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view"));
33049566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol));
33059566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&sdm));
330669d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
33079566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
33089566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
33099566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
33109566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, bdlabel));
331151a74b61SMatthew G. Knepley   PetscFunctionReturn(0);
331251a74b61SMatthew G. Knepley }
331351a74b61SMatthew G. Knepley 
331451a74b61SMatthew G. Knepley /*@
331551a74b61SMatthew G. Knepley   DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d.
331651a74b61SMatthew G. Knepley 
331751a74b61SMatthew G. Knepley   Collective
331851a74b61SMatthew G. Knepley 
331951a74b61SMatthew G. Knepley   Input Parameters:
332051a74b61SMatthew G. Knepley + comm  - The communicator for the DM object
332151a74b61SMatthew G. Knepley . dim   - The dimension
332251a74b61SMatthew G. Knepley - R     - The radius
332351a74b61SMatthew G. Knepley 
332451a74b61SMatthew G. Knepley   Output Parameter:
332551a74b61SMatthew G. Knepley . dm  - The DM object
332651a74b61SMatthew G. Knepley 
332751a74b61SMatthew G. Knepley   Options Database Keys:
332851a74b61SMatthew G. Knepley - bd_dm_refine - This will refine the surface mesh preserving the sphere geometry
332951a74b61SMatthew G. Knepley 
333051a74b61SMatthew G. Knepley   Level: beginner
333151a74b61SMatthew G. Knepley 
3332db781477SPatrick Sanan .seealso: `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
333351a74b61SMatthew G. Knepley @*/
3334d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm)
3335d71ae5a4SJacob Faibussowitsch {
333651a74b61SMatthew G. Knepley   PetscFunctionBegin;
33379566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
33389566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
33399566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R));
33402829fed8SMatthew G. Knepley   PetscFunctionReturn(0);
33412829fed8SMatthew G. Knepley }
33422829fed8SMatthew G. Knepley 
3343d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct)
3344d71ae5a4SJacob Faibussowitsch {
33450a6ba040SMatthew G. Knepley   PetscFunctionBegin;
33469318fe57SMatthew G. Knepley   switch (ct) {
33479371c9d4SSatish Balay   case DM_POLYTOPE_POINT: {
33489318fe57SMatthew G. Knepley     PetscInt    numPoints[1]        = {1};
33499318fe57SMatthew G. Knepley     PetscInt    coneSize[1]         = {0};
33509318fe57SMatthew G. Knepley     PetscInt    cones[1]            = {0};
33519318fe57SMatthew G. Knepley     PetscInt    coneOrientations[1] = {0};
33529318fe57SMatthew G. Knepley     PetscScalar vertexCoords[1]     = {0.0};
33539318fe57SMatthew G. Knepley 
33549566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 0));
33559566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33569371c9d4SSatish Balay   } break;
33579371c9d4SSatish Balay   case DM_POLYTOPE_SEGMENT: {
33589318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
33599318fe57SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
33609318fe57SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
33619318fe57SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
33629318fe57SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
33639318fe57SMatthew G. Knepley 
33649566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
33659566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33669371c9d4SSatish Balay   } break;
33679371c9d4SSatish Balay   case DM_POLYTOPE_POINT_PRISM_TENSOR: {
3368b5a892a1SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
3369b5a892a1SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
3370b5a892a1SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
3371b5a892a1SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
3372b5a892a1SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
3373b5a892a1SMatthew G. Knepley 
33749566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
33759566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33769371c9d4SSatish Balay   } break;
33779371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
33789318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {3, 1};
33799318fe57SMatthew G. Knepley     PetscInt    coneSize[4]         = {3, 0, 0, 0};
33809318fe57SMatthew G. Knepley     PetscInt    cones[3]            = {1, 2, 3};
33819318fe57SMatthew G. Knepley     PetscInt    coneOrientations[3] = {0, 0, 0};
33829318fe57SMatthew G. Knepley     PetscScalar vertexCoords[6]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0};
33839318fe57SMatthew G. Knepley 
33849566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
33859566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33869371c9d4SSatish Balay   } break;
33879371c9d4SSatish Balay   case DM_POLYTOPE_QUADRILATERAL: {
33889318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
33899318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
33909318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
33919318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
33929318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0};
33939318fe57SMatthew G. Knepley 
33949566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
33959566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
33969371c9d4SSatish Balay   } break;
33979371c9d4SSatish Balay   case DM_POLYTOPE_SEG_PRISM_TENSOR: {
33989318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
33999318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
34009318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
34019318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
34029318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0};
34039318fe57SMatthew G. Knepley 
34049566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
34059566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34069371c9d4SSatish Balay   } break;
34079371c9d4SSatish Balay   case DM_POLYTOPE_TETRAHEDRON: {
34089318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
34099318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
3410f0edb160SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
34119318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
3412f0edb160SMatthew 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};
34139318fe57SMatthew G. Knepley 
34149566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34159566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34169371c9d4SSatish Balay   } break;
34179371c9d4SSatish Balay   case DM_POLYTOPE_HEXAHEDRON: {
34189318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
34199318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
3420f0edb160SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
34219318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34229371c9d4SSatish Balay     PetscScalar vertexCoords[24]    = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0};
34239318fe57SMatthew G. Knepley 
34249566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34259566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34269371c9d4SSatish Balay   } break;
34279371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM: {
34289318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
34299318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
3430f0edb160SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
34319318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
34329371c9d4SSatish Balay     PetscScalar vertexCoords[18]    = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0};
34339318fe57SMatthew G. Knepley 
34349566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34359566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34369371c9d4SSatish Balay   } break;
34379371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM_TENSOR: {
34389318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
34399318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
34409318fe57SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
34419318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
34429371c9d4SSatish Balay     PetscScalar vertexCoords[18]    = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0};
34439318fe57SMatthew G. Knepley 
34449566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34459566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34469371c9d4SSatish Balay   } break;
34479371c9d4SSatish Balay   case DM_POLYTOPE_QUAD_PRISM_TENSOR: {
34489318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
34499318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
34509318fe57SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
34519318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34529371c9d4SSatish Balay     PetscScalar vertexCoords[24]    = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0};
34539318fe57SMatthew G. Knepley 
34549566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34559566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34569371c9d4SSatish Balay   } break;
34579371c9d4SSatish Balay   case DM_POLYTOPE_PYRAMID: {
34589318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {5, 1};
34599318fe57SMatthew G. Knepley     PetscInt    coneSize[6]         = {5, 0, 0, 0, 0, 0};
3460f0edb160SMatthew G. Knepley     PetscInt    cones[5]            = {1, 2, 3, 4, 5};
34619318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
34629371c9d4SSatish Balay     PetscScalar vertexCoords[24]    = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 0.0, 0.0, 1.0};
34639318fe57SMatthew G. Knepley 
34649566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
34659566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
34669371c9d4SSatish Balay   } break;
3467d71ae5a4SJacob Faibussowitsch   default:
3468d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]);
34699318fe57SMatthew G. Knepley   }
34709318fe57SMatthew G. Knepley   {
34719318fe57SMatthew G. Knepley     PetscInt Nv, v;
34729318fe57SMatthew G. Knepley 
34739318fe57SMatthew G. Knepley     /* Must create the celltype label here so that we do not automatically try to compute the types */
34749566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(rdm, "celltype"));
34759566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(rdm, 0, ct));
34769566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(rdm, NULL, &Nv));
34779566063dSJacob Faibussowitsch     for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT));
34789318fe57SMatthew G. Knepley   }
34799566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(rdm));
34809566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct]));
34810a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
34820a6ba040SMatthew G. Knepley }
34830a6ba040SMatthew G. Knepley 
34849318fe57SMatthew G. Knepley /*@
34859318fe57SMatthew G. Knepley   DMPlexCreateReferenceCell - Create a DMPLEX with the appropriate FEM reference cell
34869318fe57SMatthew G. Knepley 
34879318fe57SMatthew G. Knepley   Collective
34889318fe57SMatthew G. Knepley 
34899318fe57SMatthew G. Knepley   Input Parameters:
34909318fe57SMatthew G. Knepley + comm - The communicator
34919318fe57SMatthew G. Knepley - ct   - The cell type of the reference cell
34929318fe57SMatthew G. Knepley 
34939318fe57SMatthew G. Knepley   Output Parameter:
34949318fe57SMatthew G. Knepley . refdm - The reference cell
34959318fe57SMatthew G. Knepley 
34969318fe57SMatthew G. Knepley   Level: intermediate
34979318fe57SMatthew G. Knepley 
3498db781477SPatrick Sanan .seealso: `DMPlexCreateReferenceCell()`, `DMPlexCreateBoxMesh()`
34999318fe57SMatthew G. Knepley @*/
3500d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm)
3501d71ae5a4SJacob Faibussowitsch {
35020a6ba040SMatthew G. Knepley   PetscFunctionBegin;
35039566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, refdm));
35049566063dSJacob Faibussowitsch   PetscCall(DMSetType(*refdm, DMPLEX));
35059566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct));
35069318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
35079318fe57SMatthew G. Knepley }
350879a015ccSMatthew G. Knepley 
3509d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[])
3510d71ae5a4SJacob Faibussowitsch {
35119318fe57SMatthew G. Knepley   DM        plex;
35129318fe57SMatthew G. Knepley   DMLabel   label;
35139318fe57SMatthew G. Knepley   PetscBool hasLabel;
35140a6ba040SMatthew G. Knepley 
3515c22d3578SMatthew G. Knepley   PetscFunctionBegin;
35169566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &hasLabel));
35179318fe57SMatthew G. Knepley   if (hasLabel) PetscFunctionReturn(0);
35189566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, name));
35199566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
35209566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
35219566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label));
35221c8afea9SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(plex, label));
35239566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
35249318fe57SMatthew G. Knepley   PetscFunctionReturn(0);
35259318fe57SMatthew G. Knepley }
3526acdc6f61SToby Isaac 
3527669647acSMatthew G. Knepley /*
3528669647acSMatthew G. Knepley   We use the last coordinate as the radius, the inner radius is lower[dim-1] and the outer radius is upper[dim-1]. Then we map the first coordinate around the circle.
3529669647acSMatthew G. Knepley 
3530669647acSMatthew G. Knepley     (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0]))
3531669647acSMatthew G. Knepley */
3532d71ae5a4SJacob Faibussowitsch static void boxToAnnulus(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[])
3533d71ae5a4SJacob Faibussowitsch {
3534669647acSMatthew G. Knepley   const PetscReal low = PetscRealPart(constants[0]);
3535669647acSMatthew G. Knepley   const PetscReal upp = PetscRealPart(constants[1]);
3536669647acSMatthew G. Knepley   const PetscReal r   = PetscRealPart(u[1]);
3537669647acSMatthew G. Knepley   const PetscReal th  = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low);
3538669647acSMatthew G. Knepley 
3539669647acSMatthew G. Knepley   f0[0] = r * PetscCosReal(th);
3540669647acSMatthew G. Knepley   f0[1] = r * PetscSinReal(th);
3541669647acSMatthew G. Knepley }
3542669647acSMatthew G. Knepley 
3543669647acSMatthew G. Knepley const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "unknown", "DMPlexShape", "DM_SHAPE_", NULL};
35449318fe57SMatthew G. Knepley 
3545d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm)
3546d71ae5a4SJacob Faibussowitsch {
35479318fe57SMatthew G. Knepley   DMPlexShape    shape   = DM_SHAPE_BOX;
35489318fe57SMatthew G. Knepley   DMPolytopeType cell    = DM_POLYTOPE_TRIANGLE;
35499318fe57SMatthew G. Knepley   PetscInt       dim     = 2;
35509318fe57SMatthew G. Knepley   PetscBool      simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE;
3551cd7e8a5eSksagiyam   PetscBool      flg, flg2, fflg, bdfflg, nameflg;
35529318fe57SMatthew G. Knepley   MPI_Comm       comm;
3553ed5e4e85SVaclav Hapla   char           filename[PETSC_MAX_PATH_LEN]   = "<unspecified>";
3554ed5e4e85SVaclav Hapla   char           bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>";
3555ed5e4e85SVaclav Hapla   char           plexname[PETSC_MAX_PATH_LEN]   = "";
35569318fe57SMatthew G. Knepley 
35579318fe57SMatthew G. Knepley   PetscFunctionBegin;
35589566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
35599318fe57SMatthew G. Knepley   /* TODO Turn this into a registration interface */
35609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg));
35619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg));
35629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg));
35639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL));
35649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL));
35659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg));
35669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0));
356763a3b9bcSJacob Faibussowitsch   PetscCheck(!(dim < 0) && !(dim > 3), comm, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " should be in [1, 3]", dim);
35689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg));
35699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg));
35709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg));
35719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2));
35729566063dSJacob Faibussowitsch   if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure));
35739318fe57SMatthew G. Knepley 
357461a622f3SMatthew G. Knepley   switch (cell) {
357561a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT:
357661a622f3SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
357761a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
357861a622f3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
357961a622f3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
358061a622f3SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
3581d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_HEXAHEDRON:
3582d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_TRUE;
3583d71ae5a4SJacob Faibussowitsch     break;
3584d71ae5a4SJacob Faibussowitsch   default:
3585d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_FALSE;
3586d71ae5a4SJacob Faibussowitsch     break;
358761a622f3SMatthew G. Knepley   }
358861a622f3SMatthew G. Knepley 
35899318fe57SMatthew G. Knepley   if (fflg) {
35909318fe57SMatthew G. Knepley     DM dmnew;
35919318fe57SMatthew G. Knepley 
35929566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, plexname, interpolate, &dmnew));
35935de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
359469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
35959318fe57SMatthew G. Knepley   } else if (refDomain) {
35969566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell));
35979318fe57SMatthew G. Knepley   } else if (bdfflg) {
35989318fe57SMatthew G. Knepley     DM bdm, dmnew;
35999318fe57SMatthew G. Knepley 
36009566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, plexname, interpolate, &bdm));
36019566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_"));
36029566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(bdm));
36039566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew));
36049566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&bdm));
36055de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
360669d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
36079318fe57SMatthew G. Knepley   } else {
36089566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape]));
36099318fe57SMatthew G. Knepley     switch (shape) {
3610669647acSMatthew G. Knepley     case DM_SHAPE_BOX:
3611669647acSMatthew G. Knepley     case DM_SHAPE_ANNULUS: {
36129318fe57SMatthew G. Knepley       PetscInt       faces[3]  = {0, 0, 0};
36139318fe57SMatthew G. Knepley       PetscReal      lower[3]  = {0, 0, 0};
36149318fe57SMatthew G. Knepley       PetscReal      upper[3]  = {1, 1, 1};
36159318fe57SMatthew G. Knepley       DMBoundaryType bdt[3]    = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
3616669647acSMatthew G. Knepley       PetscBool      isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE;
36179318fe57SMatthew G. Knepley       PetscInt       i, n;
36189318fe57SMatthew G. Knepley 
36199318fe57SMatthew G. Knepley       n = dim;
36209318fe57SMatthew G. Knepley       for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim);
36219566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
36229318fe57SMatthew G. Knepley       n = 3;
36239566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
362463a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
36259318fe57SMatthew G. Knepley       n = 3;
36269566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
362763a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
36289318fe57SMatthew G. Knepley       n = 3;
36299566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
363063a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
3631669647acSMatthew G. Knepley 
3632669647acSMatthew G. Knepley       PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented");
3633669647acSMatthew G. Knepley       if (isAnnular)
3634669647acSMatthew G. Knepley         for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC;
3635669647acSMatthew G. Knepley 
36369318fe57SMatthew G. Knepley       switch (cell) {
363761a622f3SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
36389566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt));
3639d410b0cfSMatthew G. Knepley         if (!interpolate) {
3640d410b0cfSMatthew G. Knepley           DM udm;
3641d410b0cfSMatthew G. Knepley 
36429566063dSJacob Faibussowitsch           PetscCall(DMPlexUninterpolate(dm, &udm));
364369d8a87bSksagiyam           PetscCall(DMPlexReplace_Internal(dm, &udm));
3644d410b0cfSMatthew G. Knepley         }
36459318fe57SMatthew G. Knepley         break;
3646d71ae5a4SJacob Faibussowitsch       default:
3647d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateBoxMesh_Internal(dm, dim, simplex, faces, lower, upper, bdt, interpolate));
3648d71ae5a4SJacob Faibussowitsch         break;
36499318fe57SMatthew G. Knepley       }
3650669647acSMatthew G. Knepley       if (isAnnular) {
3651669647acSMatthew G. Knepley         DM          cdm;
3652669647acSMatthew G. Knepley         PetscDS     cds;
3653669647acSMatthew G. Knepley         PetscScalar bounds[2] = {lower[0], upper[0]};
3654669647acSMatthew G. Knepley 
3655669647acSMatthew G. Knepley         // Fix coordinates for annular region
3656669647acSMatthew G. Knepley         PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL));
3657669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinatesLocal(dm, NULL));
3658669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinates(dm, NULL));
3659669647acSMatthew G. Knepley         PetscCall(DMPlexCreateCoordinateSpace(dm, 1, NULL));
3660669647acSMatthew G. Knepley         PetscCall(DMGetCoordinateDM(dm, &cdm));
3661669647acSMatthew G. Knepley         PetscCall(DMGetDS(cdm, &cds));
3662669647acSMatthew G. Knepley         PetscCall(PetscDSSetConstants(cds, 2, bounds));
3663669647acSMatthew G. Knepley         PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus));
3664669647acSMatthew G. Knepley       }
36659371c9d4SSatish Balay     } break;
36669371c9d4SSatish Balay     case DM_SHAPE_BOX_SURFACE: {
36679318fe57SMatthew G. Knepley       PetscInt  faces[3] = {0, 0, 0};
36689318fe57SMatthew G. Knepley       PetscReal lower[3] = {0, 0, 0};
36699318fe57SMatthew G. Knepley       PetscReal upper[3] = {1, 1, 1};
36709318fe57SMatthew G. Knepley       PetscInt  i, n;
36719318fe57SMatthew G. Knepley 
36729318fe57SMatthew G. Knepley       n = dim + 1;
36739318fe57SMatthew G. Knepley       for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1));
36749566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
36759318fe57SMatthew G. Knepley       n = 3;
36769566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
367763a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim + 1), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim + 1);
36789318fe57SMatthew G. Knepley       n = 3;
36799566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
368063a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim + 1), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim + 1);
36819566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate));
36829371c9d4SSatish Balay     } break;
36839371c9d4SSatish Balay     case DM_SHAPE_SPHERE: {
36849318fe57SMatthew G. Knepley       PetscReal R = 1.0;
36859318fe57SMatthew G. Knepley 
36869566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg));
36879566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R));
36889371c9d4SSatish Balay     } break;
36899371c9d4SSatish Balay     case DM_SHAPE_BALL: {
36909318fe57SMatthew G. Knepley       PetscReal R = 1.0;
36919318fe57SMatthew G. Knepley 
36929566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg));
36939566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R));
36949371c9d4SSatish Balay     } break;
36959371c9d4SSatish Balay     case DM_SHAPE_CYLINDER: {
36969318fe57SMatthew G. Knepley       DMBoundaryType bdt = DM_BOUNDARY_NONE;
36979318fe57SMatthew G. Knepley       PetscInt       Nw  = 6;
36989318fe57SMatthew G. Knepley 
36999566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL));
37009566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL));
37019318fe57SMatthew G. Knepley       switch (cell) {
3702d71ae5a4SJacob Faibussowitsch       case DM_POLYTOPE_TRI_PRISM_TENSOR:
3703d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate));
3704d71ae5a4SJacob Faibussowitsch         break;
3705d71ae5a4SJacob Faibussowitsch       default:
3706d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt));
3707d71ae5a4SJacob Faibussowitsch         break;
37089318fe57SMatthew G. Knepley       }
37099371c9d4SSatish Balay     } break;
3710b7f5c055SJed Brown     case DM_SHAPE_SCHWARZ_P: // fallthrough
37119371c9d4SSatish Balay     case DM_SHAPE_GYROID: {
3712b7f5c055SJed Brown       PetscInt       extent[3] = {1, 1, 1}, refine = 0, layers = 0, three;
3713b7f5c055SJed Brown       PetscReal      thickness   = 0.;
3714b7f5c055SJed Brown       DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
3715b7f5c055SJed Brown       DMPlexTPSType  tps_type    = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID;
37161436d7faSJed Brown       PetscBool      tps_distribute;
37179566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL));
37189566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL));
37199566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL));
37209566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL));
37219566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL));
37229566063dSJacob Faibussowitsch       PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute));
37239566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL));
37249566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness));
37259371c9d4SSatish Balay     } break;
37269371c9d4SSatish Balay     case DM_SHAPE_DOUBLET: {
372705bd46c0SStefano Zampini       DM        dmnew;
372805bd46c0SStefano Zampini       PetscReal rl = 0.0;
372905bd46c0SStefano Zampini 
373005bd46c0SStefano Zampini       PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL));
373105bd46c0SStefano Zampini       PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew));
37325de52c6dSVaclav Hapla       PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
373369d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &dmnew));
37349371c9d4SSatish Balay     } break;
3735d71ae5a4SJacob Faibussowitsch     default:
3736d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]);
37379318fe57SMatthew G. Knepley     }
37389318fe57SMatthew G. Knepley   }
37399566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
374048a46eb9SPierre Jolivet   if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname));
37410a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
37420a6ba040SMatthew G. Knepley }
37430a6ba040SMatthew G. Knepley 
3744d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
3745d71ae5a4SJacob Faibussowitsch {
37460a6ba040SMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
37477f9d8d6cSVaclav Hapla   PetscBool flg, flg2;
37489318fe57SMatthew G. Knepley   char      bdLabel[PETSC_MAX_PATH_LEN];
37490a6ba040SMatthew G. Knepley 
37500a6ba040SMatthew G. Knepley   PetscFunctionBegin;
37510a6ba040SMatthew G. Knepley   /* Handle viewing */
37529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL));
37539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0));
37549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL));
37559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0));
3756f5867de0SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0));
37579566063dSJacob Faibussowitsch   PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg));
37589566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscLogDefaultBegin());
37599318fe57SMatthew G. Knepley   /* Labeling */
37609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg));
37619566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel));
3762953fc75cSMatthew G. Knepley   /* Point Location */
37639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL));
37640848f4b5SMatthew G. Knepley   /* Partitioning and distribution */
37659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL));
37662e62ab5aSMatthew G. Knepley   /* Generation and remeshing */
37679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL));
3768b29cfa1cSToby Isaac   /* Projection behavior */
3769*d5b43468SJose E. Roman   PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0));
37709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL));
3771f12cf164SMatthew G. Knepley   /* Checking structure */
3772f12cf164SMatthew G. Knepley   {
37737f9d8d6cSVaclav Hapla     PetscBool all = PETSC_FALSE;
3774f12cf164SMatthew G. Knepley 
37757f9d8d6cSVaclav Hapla     PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL));
37767f9d8d6cSVaclav Hapla     if (all) {
37777f9d8d6cSVaclav Hapla       PetscCall(DMPlexCheck(dm));
37787f9d8d6cSVaclav Hapla     } else {
37799566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2));
37807f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm));
37819566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_skeleton", "Check that each cell has the correct number of vertices (only for homogeneous simplex or tensor meshes)", "DMPlexCheckSkeleton", PETSC_FALSE, &flg, &flg2));
37827f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0));
37839566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_faces", "Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type", "DMPlexCheckFaces", PETSC_FALSE, &flg, &flg2));
37847f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0));
37859566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2));
37867f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm));
37879566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2));
3788d7d32a9aSMatthew G. Knepley       if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
37899566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_interface_cones", "Check points on inter-partition interfaces have conforming order of cone points", "DMPlexCheckInterfaceCones", PETSC_FALSE, &flg, &flg2));
37907f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm));
37917f9d8d6cSVaclav Hapla     }
37929566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2));
37939566063dSJacob Faibussowitsch     if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE));
3794f12cf164SMatthew G. Knepley   }
37959318fe57SMatthew G. Knepley   {
37969318fe57SMatthew G. Knepley     PetscReal scale = 1.0;
37974f3833eaSMatthew G. Knepley 
37989566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg));
37999318fe57SMatthew G. Knepley     if (flg) {
38009318fe57SMatthew G. Knepley       Vec coordinates, coordinatesLocal;
38019318fe57SMatthew G. Knepley 
38029566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinates(dm, &coordinates));
38039566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
38049566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinates, scale));
38059566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinatesLocal, scale));
38069318fe57SMatthew G. Knepley     }
38079318fe57SMatthew G. Knepley   }
38089566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner));
380968d4fef7SMatthew G. Knepley   PetscFunctionReturn(0);
381068d4fef7SMatthew G. Knepley }
381168d4fef7SMatthew G. Knepley 
3812d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap)
3813d71ae5a4SJacob Faibussowitsch {
3814c506a872SMatthew G. Knepley   PetscInt  numOvLabels = 16, numOvExLabels = 16;
3815c506a872SMatthew G. Knepley   char     *ovLabelNames[16], *ovExLabelNames[16];
3816c506a872SMatthew G. Knepley   PetscInt  numOvValues = 16, numOvExValues = 16, l;
3817c506a872SMatthew G. Knepley   PetscBool flg;
3818c506a872SMatthew G. Knepley 
3819c506a872SMatthew G. Knepley   PetscFunctionBegin;
3820c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0));
3821c506a872SMatthew G. Knepley   PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg));
3822c506a872SMatthew G. Knepley   if (!flg) numOvLabels = 0;
3823c506a872SMatthew G. Knepley   if (numOvLabels) {
3824c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvLabels = numOvLabels;
3825c506a872SMatthew G. Knepley     for (l = 0; l < numOvLabels; ++l) {
3826c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l]));
3827c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]);
3828c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovLabelNames[l]));
3829c506a872SMatthew G. Knepley     }
3830c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg));
3831c506a872SMatthew G. Knepley     if (!flg) numOvValues = 0;
3832c506a872SMatthew G. Knepley     PetscCheck(numOvLabels == numOvValues, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "The number of labels %" PetscInt_FMT " must match the number of values %" PetscInt_FMT, numOvLabels, numOvValues);
3833c506a872SMatthew G. Knepley 
3834c506a872SMatthew G. Knepley     PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg));
3835c506a872SMatthew G. Knepley     if (!flg) numOvExLabels = 0;
3836c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels;
3837c506a872SMatthew G. Knepley     for (l = 0; l < numOvExLabels; ++l) {
3838c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l]));
3839c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]);
3840c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovExLabelNames[l]));
3841c506a872SMatthew G. Knepley     }
3842c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg));
3843c506a872SMatthew G. Knepley     if (!flg) numOvExValues = 0;
3844c506a872SMatthew G. Knepley     PetscCheck(numOvExLabels == numOvExValues, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "The number of exclude labels %" PetscInt_FMT " must match the number of values %" PetscInt_FMT, numOvExLabels, numOvExValues);
3845c506a872SMatthew G. Knepley   }
3846c506a872SMatthew G. Knepley   PetscFunctionReturn(0);
3847c506a872SMatthew G. Knepley }
3848c506a872SMatthew G. Knepley 
3849d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
3850d71ae5a4SJacob Faibussowitsch {
3851bdf63967SMatthew G. Knepley   PetscFunctionList        ordlist;
3852bdf63967SMatthew G. Knepley   char                     oname[256];
3853d410b0cfSMatthew G. Knepley   PetscReal                volume    = -1.0;
38549318fe57SMatthew G. Knepley   PetscInt                 prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim;
3855e600fa54SMatthew 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;
38566bc1bd01Sksagiyam   DMPlexReorderDefaultFlag reorder;
385768d4fef7SMatthew G. Knepley 
385868d4fef7SMatthew G. Knepley   PetscFunctionBegin;
3859d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options");
38609318fe57SMatthew G. Knepley   /* Handle automatic creation */
38619566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
38626bc1bd01Sksagiyam   if (dim < 0) {
38636bc1bd01Sksagiyam     PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));
38646bc1bd01Sksagiyam     created = PETSC_TRUE;
38656bc1bd01Sksagiyam   }
38666bc1bd01Sksagiyam   PetscCall(DMGetDimension(dm, &dim));
3867d89e6e46SMatthew G. Knepley   /* Handle interpolation before distribution */
38689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg));
3869d89e6e46SMatthew G. Knepley   if (flg) {
3870d89e6e46SMatthew G. Knepley     DMPlexInterpolatedFlag interpolated;
3871d89e6e46SMatthew G. Knepley 
38729566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpolated));
3873d89e6e46SMatthew G. Knepley     if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) {
3874d89e6e46SMatthew G. Knepley       DM udm;
3875d89e6e46SMatthew G. Knepley 
38769566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(dm, &udm));
387769d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &udm));
3878d89e6e46SMatthew G. Knepley     } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) {
3879d89e6e46SMatthew G. Knepley       DM idm;
3880d89e6e46SMatthew G. Knepley 
38819566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(dm, &idm));
388269d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &idm));
3883d89e6e46SMatthew G. Knepley     }
3884d89e6e46SMatthew G. Knepley   }
38859b44eab4SMatthew G. Knepley   /* Handle DMPlex refinement before distribution */
38869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_ignore_model", "Flag to ignore the geometry model when refining", "DMCreate", ignoreModel, &ignoreModel, &flg));
3887ad540459SPierre Jolivet   if (flg) ((DM_Plex *)dm->data)->ignoreModel = ignoreModel;
38889566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig));
38899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0));
38909566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
38919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg));
38929566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform));
38939566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg));
38949318fe57SMatthew G. Knepley   if (flg) {
38959566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE));
38969566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(dm, volume));
38979318fe57SMatthew G. Knepley     prerefine = PetscMax(prerefine, 1);
38989318fe57SMatthew G. Knepley   }
38999b44eab4SMatthew G. Knepley   for (r = 0; r < prerefine; ++r) {
39009b44eab4SMatthew G. Knepley     DM             rdm;
39019b44eab4SMatthew G. Knepley     PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
39029b44eab4SMatthew G. Knepley 
3903dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
39049566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
390569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &rdm));
3906dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
390761a622f3SMatthew G. Knepley     if (coordFunc && remap) {
39089566063dSJacob Faibussowitsch       PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
39099b44eab4SMatthew G. Knepley       ((DM_Plex *)dm->data)->coordFunc = coordFunc;
39109b44eab4SMatthew G. Knepley     }
39119b44eab4SMatthew G. Knepley   }
39129566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig));
39139318fe57SMatthew G. Knepley   /* Handle DMPlex extrusion before distribution */
39149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0));
39159318fe57SMatthew G. Knepley   if (extLayers) {
39169318fe57SMatthew G. Knepley     DM edm;
39179318fe57SMatthew G. Knepley 
39189566063dSJacob Faibussowitsch     PetscCall(DMExtrude(dm, extLayers, &edm));
391969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
392048d16a33SMatthew G. Knepley     ((DM_Plex *)dm->data)->coordFunc = NULL;
3921dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
3922d410b0cfSMatthew G. Knepley     extLayers = 0;
39239318fe57SMatthew G. Knepley   }
3924bdf63967SMatthew G. Knepley   /* Handle DMPlex reordering before distribution */
39256bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dm, &reorder));
39269566063dSJacob Faibussowitsch   PetscCall(MatGetOrderingList(&ordlist));
39276bc1bd01Sksagiyam   PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname)));
39289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg));
39296bc1bd01Sksagiyam   if (reorder == DMPLEX_REORDER_DEFAULT_TRUE || flg) {
3930bdf63967SMatthew G. Knepley     DM pdm;
3931bdf63967SMatthew G. Knepley     IS perm;
3932bdf63967SMatthew G. Knepley 
39339566063dSJacob Faibussowitsch     PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm));
39349566063dSJacob Faibussowitsch     PetscCall(DMPlexPermute(dm, perm, &pdm));
39359566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&perm));
393669d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &pdm));
3937dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
3938bdf63967SMatthew G. Knepley   }
39399b44eab4SMatthew G. Knepley   /* Handle DMPlex distribution */
39409566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dm, &distribute));
3941c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL));
3942dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap));
39439b44eab4SMatthew G. Knepley   if (distribute) {
39449b44eab4SMatthew G. Knepley     DM               pdm = NULL;
39459b44eab4SMatthew G. Knepley     PetscPartitioner part;
39469b44eab4SMatthew G. Knepley 
39479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
39489566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
39499566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm));
395048a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
39519b44eab4SMatthew G. Knepley   }
39529318fe57SMatthew G. Knepley   /* Create coordinate space */
39539318fe57SMatthew G. Knepley   if (created) {
395461a622f3SMatthew G. Knepley     DM_Plex  *mesh   = (DM_Plex *)dm->data;
39559318fe57SMatthew G. Knepley     PetscInt  degree = 1;
39566858538eSMatthew G. Knepley     PetscBool flg;
39579318fe57SMatthew G. Knepley 
39589566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg));
39599566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, &degree, NULL));
39609566063dSJacob Faibussowitsch     if (coordSpace) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, mesh->coordFunc));
396161a622f3SMatthew G. Knepley     if (flg && !coordSpace) {
396261a622f3SMatthew G. Knepley       DM           cdm;
396361a622f3SMatthew G. Knepley       PetscDS      cds;
396461a622f3SMatthew G. Knepley       PetscObject  obj;
396561a622f3SMatthew G. Knepley       PetscClassId id;
396661a622f3SMatthew G. Knepley 
39679566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinateDM(dm, &cdm));
39689566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdm, &cds));
39699566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
39709566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
397161a622f3SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
397261a622f3SMatthew G. Knepley         PetscContainer dummy;
397361a622f3SMatthew G. Knepley 
39749566063dSJacob Faibussowitsch         PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy));
39759566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates"));
39769566063dSJacob Faibussowitsch         PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy));
39779566063dSJacob Faibussowitsch         PetscCall(PetscContainerDestroy(&dummy));
39789566063dSJacob Faibussowitsch         PetscCall(DMClearDS(cdm));
397961a622f3SMatthew G. Knepley       }
398061a622f3SMatthew G. Knepley       mesh->coordFunc = NULL;
398161a622f3SMatthew G. Knepley     }
39826858538eSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "", dm->sparseLocalize, &dm->sparseLocalize, &flg));
39839566063dSJacob Faibussowitsch     PetscCall(DMLocalizeCoordinates(dm));
39849318fe57SMatthew G. Knepley   }
398568d4fef7SMatthew G. Knepley   /* Handle DMPlex refinement */
398661a622f3SMatthew G. Knepley   remap = PETSC_TRUE;
39879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0));
39889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
39899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0));
39909566063dSJacob Faibussowitsch   if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
399168d4fef7SMatthew G. Knepley   if (refine && isHierarchy) {
3992acdc6f61SToby Isaac     DM *dms, coarseDM;
399368d4fef7SMatthew G. Knepley 
39949566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &coarseDM));
39959566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarseDM));
39969566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(refine, &dms));
39979566063dSJacob Faibussowitsch     PetscCall(DMRefineHierarchy(dm, refine, dms));
399868d4fef7SMatthew G. Knepley     /* Total hack since we do not pass in a pointer */
39999566063dSJacob Faibussowitsch     PetscCall(DMPlexSwap_Static(dm, dms[refine - 1]));
400068d4fef7SMatthew G. Knepley     if (refine == 1) {
40019566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[0]));
40029566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
400368d4fef7SMatthew G. Knepley     } else {
40049566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[refine - 2]));
40059566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
40069566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1]));
40079566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE));
400868d4fef7SMatthew G. Knepley     }
40099566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM));
40109566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coarseDM));
401168d4fef7SMatthew G. Knepley     /* Free DMs */
401268d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
4013dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
40149566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
401568d4fef7SMatthew G. Knepley     }
40169566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
401768d4fef7SMatthew G. Knepley   } else {
401868d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
40199318fe57SMatthew G. Knepley       DM             rdm;
402051a74b61SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
402168d4fef7SMatthew G. Knepley 
4022dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40239566063dSJacob Faibussowitsch       PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
402468d4fef7SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
402569d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
4026dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
402761a622f3SMatthew G. Knepley       if (coordFunc && remap) {
40289566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
402951a74b61SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
403051a74b61SMatthew G. Knepley       }
403168d4fef7SMatthew G. Knepley     }
403268d4fef7SMatthew G. Knepley   }
40333cf6fe12SMatthew G. Knepley   /* Handle DMPlex coarsening */
40349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0));
40359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0));
4036b653a561SMatthew G. Knepley   if (coarsen && isHierarchy) {
4037b653a561SMatthew G. Knepley     DM *dms;
4038b653a561SMatthew G. Knepley 
40399566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coarsen, &dms));
40409566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHierarchy(dm, coarsen, dms));
4041b653a561SMatthew G. Knepley     /* Free DMs */
4042b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
4043dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
40449566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
4045b653a561SMatthew G. Knepley     }
40469566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
4047b653a561SMatthew G. Knepley   } else {
4048b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
40499318fe57SMatthew G. Knepley       DM             cdm;
40509318fe57SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
40513cf6fe12SMatthew G. Knepley 
4052dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40539566063dSJacob Faibussowitsch       PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm));
40543cf6fe12SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
405569d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &cdm));
4056dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
40579318fe57SMatthew G. Knepley       if (coordFunc) {
40589566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
40599318fe57SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
40609318fe57SMatthew G. Knepley       }
40613cf6fe12SMatthew G. Knepley     }
4062b653a561SMatthew G. Knepley   }
4063909dfd52SMatthew G. Knepley   /* Handle ghost cells */
40649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL));
4065909dfd52SMatthew G. Knepley   if (ghostCells) {
4066909dfd52SMatthew G. Knepley     DM   gdm;
4067909dfd52SMatthew G. Knepley     char lname[PETSC_MAX_PATH_LEN];
4068909dfd52SMatthew G. Knepley 
4069909dfd52SMatthew G. Knepley     lname[0] = '\0';
40709566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg));
40719566063dSJacob Faibussowitsch     PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm));
407269d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &gdm));
4073909dfd52SMatthew G. Knepley   }
40746913077dSMatthew G. Knepley   /* Handle 1D order */
40756bc1bd01Sksagiyam   if (reorder != DMPLEX_REORDER_DEFAULT_FALSE && dim == 1) {
40766913077dSMatthew G. Knepley     DM           cdm, rdm;
40776913077dSMatthew G. Knepley     PetscDS      cds;
40786913077dSMatthew G. Knepley     PetscObject  obj;
40796913077dSMatthew G. Knepley     PetscClassId id = PETSC_OBJECT_CLASSID;
40806913077dSMatthew G. Knepley     IS           perm;
40816bc1bd01Sksagiyam     PetscInt     Nf;
40826913077dSMatthew G. Knepley     PetscBool    distributed;
40836913077dSMatthew G. Knepley 
40849566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(dm, &distributed));
40859566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
40869566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
40879566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(cds, &Nf));
40886913077dSMatthew G. Knepley     if (Nf) {
40899566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
40909566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
40916913077dSMatthew G. Knepley     }
40926bc1bd01Sksagiyam     if (!distributed && id != PETSCFE_CLASSID) {
40939566063dSJacob Faibussowitsch       PetscCall(DMPlexGetOrdering1D(dm, &perm));
40949566063dSJacob Faibussowitsch       PetscCall(DMPlexPermute(dm, perm, &rdm));
409569d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
40969566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&perm));
40976913077dSMatthew G. Knepley     }
40986913077dSMatthew G. Knepley   }
40993cf6fe12SMatthew G. Knepley   /* Handle */
4100dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
4101d0609cedSBarry Smith   PetscOptionsHeadEnd();
41020a6ba040SMatthew G. Knepley   PetscFunctionReturn(0);
41030a6ba040SMatthew G. Knepley }
41040a6ba040SMatthew G. Knepley 
4105d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec)
4106d71ae5a4SJacob Faibussowitsch {
4107552f7358SJed Brown   PetscFunctionBegin;
41089566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector_Section_Private(dm, vec));
41099566063dSJacob Faibussowitsch   /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
41109566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex));
41119566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native));
41129566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex));
41139566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native));
4114552f7358SJed Brown   PetscFunctionReturn(0);
4115552f7358SJed Brown }
4116552f7358SJed Brown 
4117d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec)
4118d71ae5a4SJacob Faibussowitsch {
4119552f7358SJed Brown   PetscFunctionBegin;
41209566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector_Section_Private(dm, vec));
41219566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local));
41229566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local));
4123552f7358SJed Brown   PetscFunctionReturn(0);
4124552f7358SJed Brown }
4125552f7358SJed Brown 
4126d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
4127d71ae5a4SJacob Faibussowitsch {
4128793f3fe5SMatthew G. Knepley   PetscInt depth, d;
4129793f3fe5SMatthew G. Knepley 
4130793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
41319566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
4132793f3fe5SMatthew G. Knepley   if (depth == 1) {
41339566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &d));
41349566063dSJacob Faibussowitsch     if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
41359566063dSJacob Faibussowitsch     else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd));
41369371c9d4SSatish Balay     else {
41379371c9d4SSatish Balay       *pStart = 0;
41389371c9d4SSatish Balay       *pEnd   = 0;
41399371c9d4SSatish Balay     }
4140793f3fe5SMatthew G. Knepley   } else {
41419566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
4142793f3fe5SMatthew G. Knepley   }
4143793f3fe5SMatthew G. Knepley   PetscFunctionReturn(0);
4144793f3fe5SMatthew G. Knepley }
4145793f3fe5SMatthew G. Knepley 
4146d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
4147d71ae5a4SJacob Faibussowitsch {
4148502a2867SDave May   PetscSF            sf;
41490a19bb7dSprj-   PetscInt           niranks, njranks, n;
41500a19bb7dSprj-   const PetscMPIInt *iranks, *jranks;
41510a19bb7dSprj-   DM_Plex           *data = (DM_Plex *)dm->data;
4152502a2867SDave May 
41532f356facSMatthew G. Knepley   PetscFunctionBegin;
41549566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
41550a19bb7dSprj-   if (!data->neighbors) {
41569566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sf));
41579566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL));
41589566063dSJacob Faibussowitsch     PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL));
41599566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors));
41609566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks));
41619566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks));
41620a19bb7dSprj-     n = njranks + niranks;
41639566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1));
41640a19bb7dSprj-     /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */
41659566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(n, data->neighbors));
41660a19bb7dSprj-   }
41670a19bb7dSprj-   if (nranks) *nranks = data->neighbors[0];
41680a19bb7dSprj-   if (ranks) {
41690a19bb7dSprj-     if (data->neighbors[0]) *ranks = data->neighbors + 1;
41700a19bb7dSprj-     else *ranks = NULL;
41710a19bb7dSprj-   }
4172502a2867SDave May   PetscFunctionReturn(0);
4173502a2867SDave May }
4174502a2867SDave May 
41751eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec);
41761eb70e55SToby Isaac 
4177d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm)
4178d71ae5a4SJacob Faibussowitsch {
4179552f7358SJed Brown   PetscFunctionBegin;
4180552f7358SJed Brown   dm->ops->view                      = DMView_Plex;
41812c40f234SMatthew G. Knepley   dm->ops->load                      = DMLoad_Plex;
4182552f7358SJed Brown   dm->ops->setfromoptions            = DMSetFromOptions_Plex;
418338221697SMatthew G. Knepley   dm->ops->clone                     = DMClone_Plex;
4184552f7358SJed Brown   dm->ops->setup                     = DMSetUp_Plex;
41851bb6d2a8SBarry Smith   dm->ops->createlocalsection        = DMCreateLocalSection_Plex;
418666ad2231SToby Isaac   dm->ops->createdefaultconstraints  = DMCreateDefaultConstraints_Plex;
4187552f7358SJed Brown   dm->ops->createglobalvector        = DMCreateGlobalVector_Plex;
4188552f7358SJed Brown   dm->ops->createlocalvector         = DMCreateLocalVector_Plex;
4189184d77edSJed Brown   dm->ops->getlocaltoglobalmapping   = NULL;
41900298fd71SBarry Smith   dm->ops->createfieldis             = NULL;
4191552f7358SJed Brown   dm->ops->createcoordinatedm        = DMCreateCoordinateDM_Plex;
4192f19dbd58SToby Isaac   dm->ops->createcoordinatefield     = DMCreateCoordinateField_Plex;
41930a6ba040SMatthew G. Knepley   dm->ops->getcoloring               = NULL;
4194552f7358SJed Brown   dm->ops->creatematrix              = DMCreateMatrix_Plex;
4195bceba477SMatthew G. Knepley   dm->ops->createinterpolation       = DMCreateInterpolation_Plex;
4196bd041c0cSMatthew G. Knepley   dm->ops->createmassmatrix          = DMCreateMassMatrix_Plex;
4197b4937a87SMatthew G. Knepley   dm->ops->createmassmatrixlumped    = DMCreateMassMatrixLumped_Plex;
41985a84ad33SLisandro Dalcin   dm->ops->createinjection           = DMCreateInjection_Plex;
4199552f7358SJed Brown   dm->ops->refine                    = DMRefine_Plex;
42000a6ba040SMatthew G. Knepley   dm->ops->coarsen                   = DMCoarsen_Plex;
42010a6ba040SMatthew G. Knepley   dm->ops->refinehierarchy           = DMRefineHierarchy_Plex;
4202b653a561SMatthew G. Knepley   dm->ops->coarsenhierarchy          = DMCoarsenHierarchy_Plex;
4203d410b0cfSMatthew G. Knepley   dm->ops->extrude                   = DMExtrude_Plex;
42040298fd71SBarry Smith   dm->ops->globaltolocalbegin        = NULL;
42050298fd71SBarry Smith   dm->ops->globaltolocalend          = NULL;
42060298fd71SBarry Smith   dm->ops->localtoglobalbegin        = NULL;
42070298fd71SBarry Smith   dm->ops->localtoglobalend          = NULL;
4208552f7358SJed Brown   dm->ops->destroy                   = DMDestroy_Plex;
4209552f7358SJed Brown   dm->ops->createsubdm               = DMCreateSubDM_Plex;
42102adcc780SMatthew G. Knepley   dm->ops->createsuperdm             = DMCreateSuperDM_Plex;
4211793f3fe5SMatthew G. Knepley   dm->ops->getdimpoints              = DMGetDimPoints_Plex;
4212552f7358SJed Brown   dm->ops->locatepoints              = DMLocatePoints_Plex;
42130709b2feSToby Isaac   dm->ops->projectfunctionlocal      = DMProjectFunctionLocal_Plex;
42140709b2feSToby Isaac   dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex;
4215bfc4295aSToby Isaac   dm->ops->projectfieldlocal         = DMProjectFieldLocal_Plex;
42168c6c5593SMatthew G. Knepley   dm->ops->projectfieldlabellocal    = DMProjectFieldLabelLocal_Plex;
4217ece3a9fcSMatthew G. Knepley   dm->ops->projectbdfieldlabellocal  = DMProjectBdFieldLabelLocal_Plex;
42180709b2feSToby Isaac   dm->ops->computel2diff             = DMComputeL2Diff_Plex;
4219b698f381SToby Isaac   dm->ops->computel2gradientdiff     = DMComputeL2GradientDiff_Plex;
42202a16baeaSToby Isaac   dm->ops->computel2fielddiff        = DMComputeL2FieldDiff_Plex;
422128d58a37SPierre Jolivet   dm->ops->getneighbors              = DMGetNeighbors_Plex;
42229566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex));
42239566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerviativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex));
42249566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex));
42259566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex));
42269566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
42279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex));
42289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex));
42296bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex));
42306bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex));
42319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex));
4232c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
4233c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex));
4234552f7358SJed Brown   PetscFunctionReturn(0);
4235552f7358SJed Brown }
4236552f7358SJed Brown 
4237d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm)
4238d71ae5a4SJacob Faibussowitsch {
423963a16f15SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
424063a16f15SMatthew G. Knepley 
424163a16f15SMatthew G. Knepley   PetscFunctionBegin;
424263a16f15SMatthew G. Knepley   mesh->refct++;
424363a16f15SMatthew G. Knepley   (*newdm)->data = mesh;
42449566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX));
42459566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(*newdm));
424663a16f15SMatthew G. Knepley   PetscFunctionReturn(0);
424763a16f15SMatthew G. Knepley }
424863a16f15SMatthew G. Knepley 
42498818961aSMatthew G Knepley /*MC
42508818961aSMatthew G Knepley   DMPLEX = "plex" - A DM object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram.
42518818961aSMatthew G Knepley                     In the local representation, Vecs contain all unknowns in the interior and shared boundary. This is
42528818961aSMatthew G Knepley                     specified by a PetscSection object. Ownership in the global representation is determined by
42538818961aSMatthew G Knepley                     ownership of the underlying DMPlex points. This is specified by another PetscSection object.
42548818961aSMatthew G Knepley 
4255e5893cccSMatthew G. Knepley   Options Database Keys:
4256250712c9SMatthew G. Knepley + -dm_refine_pre                     - Refine mesh before distribution
4257250712c9SMatthew G. Knepley + -dm_refine_uniform_pre             - Choose uniform or generator-based refinement
4258250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre        - Cell volume limit after pre-refinement using generator
4259250712c9SMatthew G. Knepley . -dm_distribute                     - Distribute mesh across processes
4260250712c9SMatthew G. Knepley . -dm_distribute_overlap             - Number of cells to overlap for distribution
4261250712c9SMatthew G. Knepley . -dm_refine                         - Refine mesh after distribution
4262250712c9SMatthew G. Knepley . -dm_plex_hash_location             - Use grid hashing for point location
4263ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p>    - The number of divisions in each direction of the grid hash
4264f12cf164SMatthew G. Knepley . -dm_plex_partition_balance         - Attempt to evenly divide points on partition boundary between processes
4265f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd                 - Allow changes to the boundary on remeshing
4266*d5b43468SJose E. Roman . -dm_plex_max_projection_height     - Maximum mesh point height used to project locally
4267f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement        - Use special nested projection algorithm for regular refinement
4268250712c9SMatthew G. Knepley . -dm_plex_check_all                 - Perform all shecks below
4269f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry            - Check that the adjacency information in the mesh is symmetric
4270f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices
4271f12cf164SMatthew 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
4272f12cf164SMatthew G. Knepley . -dm_plex_check_geometry            - Check that cells have positive volume
4273f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex     - View the mesh in LaTeX/TikZ
4274e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num>          - Scale the TikZ
4275e5893cccSMatthew G. Knepley - -dm_plex_print_fem <num>           - View FEM assembly information, such as element vectors and matrices
4276e5893cccSMatthew G. Knepley 
42778818961aSMatthew G Knepley   Level: intermediate
42788818961aSMatthew G Knepley 
4279db781477SPatrick Sanan .seealso: `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`
42808818961aSMatthew G Knepley M*/
42818818961aSMatthew G Knepley 
4282d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
4283d71ae5a4SJacob Faibussowitsch {
4284552f7358SJed Brown   DM_Plex *mesh;
4285412e9a14SMatthew G. Knepley   PetscInt unit;
4286552f7358SJed Brown 
4287552f7358SJed Brown   PetscFunctionBegin;
4288552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
42894dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&mesh));
4290552f7358SJed Brown   dm->data = mesh;
4291552f7358SJed Brown 
4292552f7358SJed Brown   mesh->refct = 1;
42939566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection));
42949566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection));
4295552f7358SJed Brown   mesh->refinementUniform      = PETSC_TRUE;
4296552f7358SJed Brown   mesh->refinementLimit        = -1.0;
4297e600fa54SMatthew G. Knepley   mesh->distDefault            = PETSC_TRUE;
42986bc1bd01Sksagiyam   mesh->reorderDefault         = DMPLEX_REORDER_DEFAULT_NOTSET;
42991d1f2f2aSksagiyam   mesh->distributionName       = NULL;
43007d0f5628SVaclav Hapla   mesh->interpolated           = DMPLEX_INTERPOLATED_INVALID;
43017d0f5628SVaclav Hapla   mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID;
4302552f7358SJed Brown 
43039566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner));
43042e62ab5aSMatthew G. Knepley   mesh->remeshBd = PETSC_FALSE;
4305d9deefdfSMatthew G. Knepley 
43068865f1eaSKarl Rupp   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
4307552f7358SJed Brown 
4308df0420ecSMatthew G. Knepley   mesh->depthState    = -1;
4309ba2698f1SMatthew G. Knepley   mesh->celltypeState = -1;
43106113b454SMatthew G. Knepley   mesh->printTol      = 1.0e-10;
4311552f7358SJed Brown 
43129566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
4313552f7358SJed Brown   PetscFunctionReturn(0);
4314552f7358SJed Brown }
4315552f7358SJed Brown 
4316552f7358SJed Brown /*@
4317552f7358SJed Brown   DMPlexCreate - Creates a DMPlex object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
4318552f7358SJed Brown 
4319d083f849SBarry Smith   Collective
4320552f7358SJed Brown 
4321552f7358SJed Brown   Input Parameter:
4322552f7358SJed Brown . comm - The communicator for the DMPlex object
4323552f7358SJed Brown 
4324552f7358SJed Brown   Output Parameter:
4325552f7358SJed Brown . mesh  - The DMPlex object
4326552f7358SJed Brown 
4327552f7358SJed Brown   Level: beginner
4328552f7358SJed Brown 
4329552f7358SJed Brown @*/
4330d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
4331d71ae5a4SJacob Faibussowitsch {
4332552f7358SJed Brown   PetscFunctionBegin;
4333552f7358SJed Brown   PetscValidPointer(mesh, 2);
43349566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, mesh));
43359566063dSJacob Faibussowitsch   PetscCall(DMSetType(*mesh, DMPLEX));
4336552f7358SJed Brown   PetscFunctionReturn(0);
4337552f7358SJed Brown }
4338552f7358SJed Brown 
4339b09969d6SVaclav Hapla /*@C
4340b09969d6SVaclav Hapla   DMPlexBuildFromCellListParallel - Build distributed DMPLEX topology from a list of vertices for each cell (common mesh generator output)
4341b09969d6SVaclav Hapla 
4342b09969d6SVaclav Hapla   Input Parameters:
4343b09969d6SVaclav Hapla + dm - The DM
4344b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
4345325d53feSBarry Smith . numVertices - The number of vertices to be owned by this process, or PETSC_DECIDE
4346325d53feSBarry Smith . NVertices - The global number of vertices, or PETSC_DETERMINE
4347b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell
43485e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
4349b09969d6SVaclav Hapla 
4350be8c289dSNicolas Barral   Output Parameters:
4351be8c289dSNicolas Barral + vertexSF - (Optional) SF describing complete vertex ownership
4352be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
4353b09969d6SVaclav Hapla 
4354b09969d6SVaclav Hapla   Notes:
4355b09969d6SVaclav Hapla   Two triangles sharing a face
4356b09969d6SVaclav Hapla $
4357b09969d6SVaclav Hapla $        2
4358b09969d6SVaclav Hapla $      / | \
4359b09969d6SVaclav Hapla $     /  |  \
4360b09969d6SVaclav Hapla $    /   |   \
4361b09969d6SVaclav Hapla $   0  0 | 1  3
4362b09969d6SVaclav Hapla $    \   |   /
4363b09969d6SVaclav Hapla $     \  |  /
4364b09969d6SVaclav Hapla $      \ | /
4365b09969d6SVaclav Hapla $        1
4366b09969d6SVaclav Hapla would have input
4367b09969d6SVaclav Hapla $  numCells = 2, numVertices = 4
4368b09969d6SVaclav Hapla $  cells = [0 1 2  1 3 2]
4369b09969d6SVaclav Hapla $
4370b09969d6SVaclav Hapla which would result in the DMPlex
4371b09969d6SVaclav Hapla $
4372b09969d6SVaclav Hapla $        4
4373b09969d6SVaclav Hapla $      / | \
4374b09969d6SVaclav Hapla $     /  |  \
4375b09969d6SVaclav Hapla $    /   |   \
4376b09969d6SVaclav Hapla $   2  0 | 1  5
4377b09969d6SVaclav Hapla $    \   |   /
4378b09969d6SVaclav Hapla $     \  |  /
4379b09969d6SVaclav Hapla $      \ | /
4380b09969d6SVaclav Hapla $        3
4381b09969d6SVaclav Hapla 
438225b6865aSVaclav Hapla   Vertices are implicitly numbered consecutively 0,...,NVertices.
438325b6865aSVaclav Hapla   Each rank owns a chunk of numVertices consecutive vertices.
438425b6865aSVaclav Hapla   If numVertices is PETSC_DECIDE, PETSc will distribute them as evenly as possible using PetscLayout.
4385325d53feSBarry Smith   If NVertices is PETSC_DETERMINE and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
4386325d53feSBarry Smith   If only NVertices is PETSC_DETERMINE, it is computed as the sum of numVertices over all ranks.
438725b6865aSVaclav Hapla 
4388b09969d6SVaclav Hapla   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
4389b09969d6SVaclav Hapla 
4390b09969d6SVaclav Hapla   Not currently supported in Fortran.
4391b09969d6SVaclav Hapla 
4392b09969d6SVaclav Hapla   Level: advanced
4393b09969d6SVaclav Hapla 
4394db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`
4395b09969d6SVaclav Hapla @*/
4396d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved)
4397d71ae5a4SJacob Faibussowitsch {
43982464107aSksagiyam   PetscSF     sfPoint;
43992464107aSksagiyam   PetscLayout layout;
440082fb893eSVaclav Hapla   PetscInt    numVerticesAdj, *verticesAdj, *cones, c, p;
4401a47d0d45SMatthew G. Knepley 
4402a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
440325b6865aSVaclav Hapla   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
44049566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
440525b6865aSVaclav Hapla   /* Get/check global number of vertices */
440625b6865aSVaclav Hapla   {
440725b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
440825b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
440925b6865aSVaclav Hapla 
441025b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
441125b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
44129371c9d4SSatish Balay     for (i = 0; i < len; i++)
44139371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
441425b6865aSVaclav Hapla     ++NVerticesInCells;
44159566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
441625b6865aSVaclav Hapla 
441725b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
44189371c9d4SSatish Balay     else
44199371c9d4SSatish Balay       PetscCheck(NVertices == PETSC_DECIDE || NVertices >= NVerticesInCells, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Specified global number of vertices %" PetscInt_FMT " must be greater than or equal to the number of vertices in cells %" PetscInt_FMT, NVertices, NVerticesInCells);
442025b6865aSVaclav Hapla   }
44219079aca8SVaclav Hapla   /* Count locally unique vertices */
44229079aca8SVaclav Hapla   {
44239079aca8SVaclav Hapla     PetscHSetI vhash;
44249079aca8SVaclav Hapla     PetscInt   off = 0;
44259079aca8SVaclav Hapla 
44269566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&vhash));
4427a47d0d45SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
442848a46eb9SPierre Jolivet       for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p]));
4429a47d0d45SMatthew G. Knepley     }
44309566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
44319566063dSJacob Faibussowitsch     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
4432ad540459SPierre Jolivet     else verticesAdj = *verticesAdjSaved;
44339566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
44349566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&vhash));
443563a3b9bcSJacob Faibussowitsch     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
4436a47d0d45SMatthew G. Knepley   }
44379566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
4438a47d0d45SMatthew G. Knepley   /* Create cones */
44399566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
44409566063dSJacob Faibussowitsch   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
44419566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
44429566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
4443a47d0d45SMatthew G. Knepley   for (c = 0; c < numCells; ++c) {
4444a47d0d45SMatthew G. Knepley     for (p = 0; p < numCorners; ++p) {
4445a47d0d45SMatthew G. Knepley       const PetscInt gv = cells[c * numCorners + p];
4446a47d0d45SMatthew G. Knepley       PetscInt       lv;
4447a47d0d45SMatthew G. Knepley 
44489079aca8SVaclav Hapla       /* Positions within verticesAdj form 0-based local vertex numbering;
44499079aca8SVaclav Hapla          we need to shift it by numCells to get correct DAG points (cells go first) */
44509566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
445163a3b9bcSJacob Faibussowitsch       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
4452961cfab0SVaclav Hapla       cones[c * numCorners + p] = lv + numCells;
4453a47d0d45SMatthew G. Knepley     }
4454a47d0d45SMatthew G. Knepley   }
44552464107aSksagiyam   /* Build point sf */
44569566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
44579566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(layout, NVertices));
44589566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
44599566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
44609566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
44619566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
44629566063dSJacob Faibussowitsch   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
44639566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
44642464107aSksagiyam   if (dm->sf) {
44652464107aSksagiyam     const char *prefix;
44662464107aSksagiyam 
44679566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
44689566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
44692464107aSksagiyam   }
44709566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sfPoint));
44719566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfPoint));
44729566063dSJacob Faibussowitsch   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)(*vertexSF), "Vertex Ownership SF"));
4473a47d0d45SMatthew G. Knepley   /* Fill in the rest of the topology structure */
44749566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
44759566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
44769566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
4477a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4478a47d0d45SMatthew G. Knepley }
4479a47d0d45SMatthew G. Knepley 
4480b09969d6SVaclav Hapla /*@C
4481b09969d6SVaclav Hapla   DMPlexBuildCoordinatesFromCellListParallel - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4482b09969d6SVaclav Hapla 
4483b09969d6SVaclav Hapla   Input Parameters:
4484b09969d6SVaclav Hapla + dm - The DM
4485b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4486b09969d6SVaclav Hapla . sfVert - SF describing complete vertex ownership
4487b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4488b09969d6SVaclav Hapla 
4489b09969d6SVaclav Hapla   Level: advanced
4490b09969d6SVaclav Hapla 
4491b09969d6SVaclav Hapla   Notes:
4492b09969d6SVaclav Hapla   Not currently supported in Fortran.
4493b09969d6SVaclav Hapla 
4494db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()`
4495b09969d6SVaclav Hapla @*/
4496d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[])
4497d71ae5a4SJacob Faibussowitsch {
4498a47d0d45SMatthew G. Knepley   PetscSection coordSection;
4499a47d0d45SMatthew G. Knepley   Vec          coordinates;
4500a47d0d45SMatthew G. Knepley   PetscScalar *coords;
45011edcf0b2SVaclav Hapla   PetscInt     numVertices, numVerticesAdj, coordSize, v, vStart, vEnd;
4502a47d0d45SMatthew G. Knepley 
4503a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
45049566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
45059566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
45061dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
45079566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
45089566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL));
45091dca8a05SBarry Smith   PetscCheck(vEnd - vStart == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Supplied sfVert has wrong number of leaves = %" PetscInt_FMT " != %" PetscInt_FMT " = vEnd - vStart", numVerticesAdj, vEnd - vStart);
45109566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
45119566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
45129566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
45139566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
45141edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
45159566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
45169566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4517a47d0d45SMatthew G. Knepley   }
45189566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
45199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
45209566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
45219566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
45229566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
45239566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
45249566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
45259566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
4526a47d0d45SMatthew G. Knepley   {
4527a47d0d45SMatthew G. Knepley     MPI_Datatype coordtype;
4528a47d0d45SMatthew G. Knepley 
4529a47d0d45SMatthew G. Knepley     /* Need a temp buffer for coords if we have complex/single */
45309566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_contiguous(spaceDim, MPIU_SCALAR, &coordtype));
45319566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&coordtype));
453221016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX)
453321016a8bSBarry Smith     {
453421016a8bSBarry Smith       PetscScalar *svertexCoords;
453521016a8bSBarry Smith       PetscInt     i;
45369566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords));
45373612f820SVaclav Hapla       for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i];
45389566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
45399566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
45409566063dSJacob Faibussowitsch       PetscCall(PetscFree(svertexCoords));
454121016a8bSBarry Smith     }
454221016a8bSBarry Smith #else
45439566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
45449566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
454521016a8bSBarry Smith #endif
45469566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&coordtype));
4547a47d0d45SMatthew G. Knepley   }
45489566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
45499566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
45509566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
45519566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
4552a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4553a47d0d45SMatthew G. Knepley }
4554a47d0d45SMatthew G. Knepley 
4555c3edce3dSSatish Balay /*@
4556b09969d6SVaclav Hapla   DMPlexCreateFromCellListParallelPetsc - Create distributed DMPLEX from a list of vertices for each cell (common mesh generator output)
4557a47d0d45SMatthew G. Knepley 
4558a47d0d45SMatthew G. Knepley   Input Parameters:
4559a47d0d45SMatthew G. Knepley + comm - The communicator
4560a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh
4561a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process
456225b6865aSVaclav Hapla . numVertices - The number of vertices owned by this process, or PETSC_DECIDE
456325b6865aSVaclav Hapla . NVertices - The global number of vertices, or PETSC_DECIDE
4564a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell
4565a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
4566a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
4567a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates
4568a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4569a47d0d45SMatthew G. Knepley 
4570d8d19677SJose E. Roman   Output Parameters:
457118d54ad4SMichael Lange + dm - The DM
4572be8c289dSNicolas Barral . vertexSF - (Optional) SF describing complete vertex ownership
4573be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
4574a47d0d45SMatthew G. Knepley 
4575b09969d6SVaclav Hapla   Notes:
4576b09969d6SVaclav Hapla   This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(),
4577b09969d6SVaclav Hapla   DMPlexBuildFromCellListParallel(), DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellListParallel()
4578a47d0d45SMatthew G. Knepley 
457925b6865aSVaclav Hapla   See DMPlexBuildFromCellListParallel() for an example and details about the topology-related parameters.
458025b6865aSVaclav Hapla   See DMPlexBuildCoordinatesFromCellListParallel() for details about the geometry-related parameters.
458125b6865aSVaclav Hapla 
4582b09969d6SVaclav Hapla   Level: intermediate
4583a47d0d45SMatthew G. Knepley 
4584db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
4585a47d0d45SMatthew G. Knepley @*/
4586d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromCellListParallelPetsc(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PetscSF *vertexSF, PetscInt **verticesAdj, DM *dm)
4587d71ae5a4SJacob Faibussowitsch {
4588a47d0d45SMatthew G. Knepley   PetscSF sfVert;
4589a47d0d45SMatthew G. Knepley 
4590a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
45919566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
45929566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
4593a47d0d45SMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
4594064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
45959566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
45969566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj));
4597a47d0d45SMatthew G. Knepley   if (interpolate) {
45985fd9971aSMatthew G. Knepley     DM idm;
4599a47d0d45SMatthew G. Knepley 
46009566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
46019566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
4602a47d0d45SMatthew G. Knepley     *dm = idm;
4603a47d0d45SMatthew G. Knepley   }
46049566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
460518d54ad4SMichael Lange   if (vertexSF) *vertexSF = sfVert;
46069566063dSJacob Faibussowitsch   else PetscCall(PetscSFDestroy(&sfVert));
4607a47d0d45SMatthew G. Knepley   PetscFunctionReturn(0);
4608a47d0d45SMatthew G. Knepley }
4609a47d0d45SMatthew G. Knepley 
4610b09969d6SVaclav Hapla /*@C
4611b09969d6SVaclav Hapla   DMPlexBuildFromCellList - Build DMPLEX topology from a list of vertices for each cell (common mesh generator output)
46129298eaa6SMatthew G Knepley 
46139298eaa6SMatthew G Knepley   Input Parameters:
4614b09969d6SVaclav Hapla + dm - The DM
4615b09969d6SVaclav Hapla . numCells - The number of cells owned by this process
4616325d53feSBarry Smith . numVertices - The number of vertices owned by this process, or PETSC_DETERMINE
46179298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell
46185e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell
46199298eaa6SMatthew G Knepley 
4620b09969d6SVaclav Hapla   Level: advanced
46219298eaa6SMatthew G Knepley 
4622b09969d6SVaclav Hapla   Notes:
4623b09969d6SVaclav Hapla   Two triangles sharing a face
46249298eaa6SMatthew G Knepley $
46259298eaa6SMatthew G Knepley $        2
46269298eaa6SMatthew G Knepley $      / | \
46279298eaa6SMatthew G Knepley $     /  |  \
46289298eaa6SMatthew G Knepley $    /   |   \
46299298eaa6SMatthew G Knepley $   0  0 | 1  3
46309298eaa6SMatthew G Knepley $    \   |   /
46319298eaa6SMatthew G Knepley $     \  |  /
46329298eaa6SMatthew G Knepley $      \ | /
46339298eaa6SMatthew G Knepley $        1
46349298eaa6SMatthew G Knepley would have input
46359298eaa6SMatthew G Knepley $  numCells = 2, numVertices = 4
46369298eaa6SMatthew G Knepley $  cells = [0 1 2  1 3 2]
46379298eaa6SMatthew G Knepley $
46389298eaa6SMatthew G Knepley which would result in the DMPlex
46399298eaa6SMatthew G Knepley $
46409298eaa6SMatthew G Knepley $        4
46419298eaa6SMatthew G Knepley $      / | \
46429298eaa6SMatthew G Knepley $     /  |  \
46439298eaa6SMatthew G Knepley $    /   |   \
46449298eaa6SMatthew G Knepley $   2  0 | 1  5
46459298eaa6SMatthew G Knepley $    \   |   /
46469298eaa6SMatthew G Knepley $     \  |  /
46479298eaa6SMatthew G Knepley $      \ | /
46489298eaa6SMatthew G Knepley $        3
46499298eaa6SMatthew G Knepley 
4650325d53feSBarry Smith   If numVertices is PETSC_DETERMINE, it is computed by PETSc as the maximum vertex index in cells + 1.
465125b6865aSVaclav Hapla 
4652b09969d6SVaclav Hapla   Not currently supported in Fortran.
46539298eaa6SMatthew G Knepley 
4654db781477SPatrick Sanan .seealso: `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()`
4655b09969d6SVaclav Hapla @*/
4656d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[])
4657d71ae5a4SJacob Faibussowitsch {
4658961cfab0SVaclav Hapla   PetscInt *cones, c, p, dim;
4659b09969d6SVaclav Hapla 
4660b09969d6SVaclav Hapla   PetscFunctionBegin;
46619566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
46629566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
466325b6865aSVaclav Hapla   /* Get/check global number of vertices */
466425b6865aSVaclav Hapla   {
466525b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
466625b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
466725b6865aSVaclav Hapla 
466825b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
466925b6865aSVaclav Hapla     NVerticesInCells = PETSC_MIN_INT;
46709371c9d4SSatish Balay     for (i = 0; i < len; i++)
46719371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
467225b6865aSVaclav Hapla     ++NVerticesInCells;
467325b6865aSVaclav Hapla 
467425b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells;
46759371c9d4SSatish Balay     else
46769371c9d4SSatish Balay       PetscCheck(numVertices >= NVerticesInCells, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Specified number of vertices %" PetscInt_FMT " must be greater than or equal to the number of vertices in cells %" PetscInt_FMT, numVertices, NVerticesInCells);
467725b6865aSVaclav Hapla   }
46789566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
467948a46eb9SPierre Jolivet   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
46809566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
46819566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
4682b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
4683ad540459SPierre Jolivet     for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells;
4684b09969d6SVaclav Hapla   }
46859566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
46869566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
46879566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
4688b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4689b09969d6SVaclav Hapla }
4690b09969d6SVaclav Hapla 
4691b09969d6SVaclav Hapla /*@C
4692b09969d6SVaclav Hapla   DMPlexBuildCoordinatesFromCellList - Build DM coordinates from a list of coordinates for each owned vertex (common mesh generator output)
4693b09969d6SVaclav Hapla 
4694b09969d6SVaclav Hapla   Input Parameters:
4695b09969d6SVaclav Hapla + dm - The DM
4696b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
4697b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
4698b09969d6SVaclav Hapla 
4699b09969d6SVaclav Hapla   Level: advanced
4700b09969d6SVaclav Hapla 
4701b09969d6SVaclav Hapla   Notes:
4702b09969d6SVaclav Hapla   Not currently supported in Fortran.
4703b09969d6SVaclav Hapla 
4704db781477SPatrick Sanan .seealso: `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()`
4705b09969d6SVaclav Hapla @*/
4706d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[])
4707d71ae5a4SJacob Faibussowitsch {
4708b09969d6SVaclav Hapla   PetscSection coordSection;
4709b09969d6SVaclav Hapla   Vec          coordinates;
4710b09969d6SVaclav Hapla   DM           cdm;
4711b09969d6SVaclav Hapla   PetscScalar *coords;
47121edcf0b2SVaclav Hapla   PetscInt     v, vStart, vEnd, d;
4713b09969d6SVaclav Hapla 
4714b09969d6SVaclav Hapla   PetscFunctionBegin;
47159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
47169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
47171dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
47189566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
47199566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
47209566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
47219566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
47229566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
47231edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
47249566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
47259566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
4726b09969d6SVaclav Hapla   }
47279566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
4728b09969d6SVaclav Hapla 
47299566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
47309566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(cdm, &coordinates));
47319566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
47329566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
47339566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(coordinates, &coords));
47341edcf0b2SVaclav Hapla   for (v = 0; v < vEnd - vStart; ++v) {
4735ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d];
4736b09969d6SVaclav Hapla   }
47379566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
47389566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
47399566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
47409566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
4741b09969d6SVaclav Hapla   PetscFunctionReturn(0);
4742b09969d6SVaclav Hapla }
4743b09969d6SVaclav Hapla 
4744b09969d6SVaclav Hapla /*@
47453df08285SMatthew 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
47463df08285SMatthew G. Knepley 
47473df08285SMatthew G. Knepley   Collective on comm
4748b09969d6SVaclav Hapla 
4749b09969d6SVaclav Hapla   Input Parameters:
4750b09969d6SVaclav Hapla + comm - The communicator
4751b09969d6SVaclav Hapla . dim - The topological dimension of the mesh
47523df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0
47533df08285SMatthew G. Knepley . numVertices - The number of vertices owned by this process, or PETSC_DECIDE, only on process 0
47543df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0
4755b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
47563df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0
4757b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates
47583df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0
4759b09969d6SVaclav Hapla 
4760b09969d6SVaclav Hapla   Output Parameter:
47613df08285SMatthew G. Knepley . dm - The DM, which only has points on process 0
4762b09969d6SVaclav Hapla 
4763b09969d6SVaclav Hapla   Notes:
4764b09969d6SVaclav Hapla   This function is just a convenient sequence of DMCreate(), DMSetType(), DMSetDimension(), DMPlexBuildFromCellList(),
4765b09969d6SVaclav Hapla   DMPlexInterpolate(), DMPlexBuildCoordinatesFromCellList()
4766b09969d6SVaclav Hapla 
476725b6865aSVaclav Hapla   See DMPlexBuildFromCellList() for an example and details about the topology-related parameters.
476825b6865aSVaclav Hapla   See DMPlexBuildCoordinatesFromCellList() for details about the geometry-related parameters.
47693df08285SMatthew G. Knepley   See DMPlexCreateFromCellListParallelPetsc() for parallel input
477025b6865aSVaclav Hapla 
4771b09969d6SVaclav Hapla   Level: intermediate
4772b09969d6SVaclav Hapla 
4773db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
47749298eaa6SMatthew G Knepley @*/
4775d71ae5a4SJacob 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)
4776d71ae5a4SJacob Faibussowitsch {
47773df08285SMatthew G. Knepley   PetscMPIInt rank;
47789298eaa6SMatthew G Knepley 
47799298eaa6SMatthew G Knepley   PetscFunctionBegin;
478028b400f6SJacob Faibussowitsch   PetscCheck(dim, comm, PETSC_ERR_ARG_OUTOFRANGE, "This is not appropriate for 0-dimensional meshes. Consider either creating the DM using DMPlexCreateFromDAG(), by hand, or using DMSwarm.");
47819566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
47829566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
47839566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
47849566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
4785c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells));
47869566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL));
47879298eaa6SMatthew G Knepley   if (interpolate) {
47885fd9971aSMatthew G. Knepley     DM idm;
47899298eaa6SMatthew G Knepley 
47909566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
47919566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
47929298eaa6SMatthew G Knepley     *dm = idm;
47939298eaa6SMatthew G Knepley   }
4794c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords));
47959566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL));
47969298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
47979298eaa6SMatthew G Knepley }
47989298eaa6SMatthew G Knepley 
4799939f6067SMatthew G. Knepley /*@
4800939f6067SMatthew 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
4801939f6067SMatthew G. Knepley 
4802939f6067SMatthew G. Knepley   Input Parameters:
4803c73cfb54SMatthew G. Knepley + dm - The empty DM object, usually from DMCreate() and DMSetDimension()
4804939f6067SMatthew G. Knepley . depth - The depth of the DAG
4805367003a6SStefano Zampini . numPoints - Array of size depth + 1 containing the number of points at each depth
4806939f6067SMatthew G. Knepley . coneSize - The cone size of each point
4807939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
4808939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point
4809367003a6SStefano Zampini - vertexCoords - An array of numPoints[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via DMSetCoordinateDim()
4810939f6067SMatthew G. Knepley 
4811939f6067SMatthew G. Knepley   Output Parameter:
4812939f6067SMatthew G. Knepley . dm - The DM
4813939f6067SMatthew G. Knepley 
4814939f6067SMatthew G. Knepley   Note: Two triangles sharing a face would have input
4815939f6067SMatthew G. Knepley $  depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
4816939f6067SMatthew G. Knepley $  cones = [2 3 4  3 5 4], coneOrientations = [0 0 0  0 0 0]
4817939f6067SMatthew G. Knepley $ vertexCoords = [-1.0 0.0  0.0 -1.0  0.0 1.0  1.0 0.0]
4818939f6067SMatthew G. Knepley $
4819939f6067SMatthew G. Knepley which would result in the DMPlex
4820939f6067SMatthew G. Knepley $
4821939f6067SMatthew G. Knepley $        4
4822939f6067SMatthew G. Knepley $      / | \
4823939f6067SMatthew G. Knepley $     /  |  \
4824939f6067SMatthew G. Knepley $    /   |   \
4825939f6067SMatthew G. Knepley $   2  0 | 1  5
4826939f6067SMatthew G. Knepley $    \   |   /
4827939f6067SMatthew G. Knepley $     \  |  /
4828939f6067SMatthew G. Knepley $      \ | /
4829939f6067SMatthew G. Knepley $        3
4830939f6067SMatthew G. Knepley $
4831a4a685f2SJacob Faibussowitsch $ Notice that all points are numbered consecutively, unlike DMPlexCreateFromCellListPetsc()
4832939f6067SMatthew G. Knepley 
4833939f6067SMatthew G. Knepley   Level: advanced
4834939f6067SMatthew G. Knepley 
4835db781477SPatrick Sanan .seealso: `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
4836939f6067SMatthew G. Knepley @*/
4837d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
4838d71ae5a4SJacob Faibussowitsch {
48399298eaa6SMatthew G Knepley   Vec          coordinates;
48409298eaa6SMatthew G Knepley   PetscSection coordSection;
48419298eaa6SMatthew G Knepley   PetscScalar *coords;
4842811e8653SToby Isaac   PetscInt     coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off;
48439298eaa6SMatthew G Knepley 
48449298eaa6SMatthew G Knepley   PetscFunctionBegin;
48459566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
48469566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
484763a3b9bcSJacob Faibussowitsch   PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim);
48489298eaa6SMatthew G Knepley   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
48499566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, pStart, pEnd));
48509298eaa6SMatthew G Knepley   for (p = pStart; p < pEnd; ++p) {
48519566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart]));
4852ad540459SPierre Jolivet     if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart;
485397e052ccSToby Isaac   }
48541dca8a05SBarry Smith   PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]);
48559566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm)); /* Allocate space for cones */
48569298eaa6SMatthew G Knepley   for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) {
48579566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(dm, p, &cones[off]));
48589566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off]));
48599298eaa6SMatthew G Knepley   }
48609566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
48619566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
48629298eaa6SMatthew G Knepley   /* Build coordinates */
48639566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
48649566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
48659566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
48669566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0]));
48679298eaa6SMatthew G Knepley   for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) {
48689566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
48699566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
48709298eaa6SMatthew G Knepley   }
48719566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
48729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
48739566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
48749566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
48759566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
48769566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, dimEmbed));
48779566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
48789318fe57SMatthew G. Knepley   if (vertexCoords) {
48799566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
48809298eaa6SMatthew G Knepley     for (v = 0; v < numPoints[0]; ++v) {
48819298eaa6SMatthew G Knepley       PetscInt off;
48829298eaa6SMatthew G Knepley 
48839566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off));
4884ad540459SPierre Jolivet       for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d];
48859298eaa6SMatthew G Knepley     }
48869318fe57SMatthew G. Knepley   }
48879566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
48889566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
48899566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
48909298eaa6SMatthew G Knepley   PetscFunctionReturn(0);
48919298eaa6SMatthew G Knepley }
48928415267dSToby Isaac 
4893ca522641SMatthew G. Knepley /*@C
48948ca92349SMatthew G. Knepley   DMPlexCreateCellVertexFromFile - Create a DMPlex mesh from a simple cell-vertex file.
48958ca92349SMatthew G. Knepley 
48968ca92349SMatthew G. Knepley + comm        - The MPI communicator
48978ca92349SMatthew G. Knepley . filename    - Name of the .dat file
48988ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
48998ca92349SMatthew G. Knepley 
49008ca92349SMatthew G. Knepley   Output Parameter:
49018ca92349SMatthew G. Knepley . dm  - The DM object representing the mesh
49028ca92349SMatthew G. Knepley 
49038ca92349SMatthew G. Knepley   Note: The format is the simplest possible:
49048ca92349SMatthew G. Knepley $ Ne
49058ca92349SMatthew G. Knepley $ v0 v1 ... vk
49068ca92349SMatthew G. Knepley $ Nv
49078ca92349SMatthew G. Knepley $ x y z marker
49088ca92349SMatthew G. Knepley 
49098ca92349SMatthew G. Knepley   Level: beginner
49108ca92349SMatthew G. Knepley 
4911db781477SPatrick Sanan .seealso: `DMPlexCreateFromFile()`, `DMPlexCreateMedFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
49128ca92349SMatthew G. Knepley @*/
4913d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
4914d71ae5a4SJacob Faibussowitsch {
49158ca92349SMatthew G. Knepley   DMLabel      marker;
49168ca92349SMatthew G. Knepley   PetscViewer  viewer;
49178ca92349SMatthew G. Knepley   Vec          coordinates;
49188ca92349SMatthew G. Knepley   PetscSection coordSection;
49198ca92349SMatthew G. Knepley   PetscScalar *coords;
49208ca92349SMatthew G. Knepley   char         line[PETSC_MAX_PATH_LEN];
49218ca92349SMatthew G. Knepley   PetscInt     dim = 3, cdim = 3, coordSize, v, c, d;
49228ca92349SMatthew G. Knepley   PetscMPIInt  rank;
4923f8d5e320SMatthew G. Knepley   int          snum, Nv, Nc, Ncn, Nl;
49248ca92349SMatthew G. Knepley 
49258ca92349SMatthew G. Knepley   PetscFunctionBegin;
49269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
49279566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
49289566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
49299566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
49309566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
4931dd400576SPatrick Sanan   if (rank == 0) {
49329566063dSJacob Faibussowitsch     PetscCall(PetscViewerRead(viewer, line, 4, NULL, PETSC_STRING));
4933f8d5e320SMatthew G. Knepley     snum = sscanf(line, "%d %d %d %d", &Nc, &Nv, &Ncn, &Nl);
493408401ef6SPierre Jolivet     PetscCheck(snum == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
493525ce1634SJed Brown   } else {
4936f8d5e320SMatthew G. Knepley     Nc = Nv = Ncn = Nl = 0;
49378ca92349SMatthew G. Knepley   }
49389566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
49399566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
49409566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
49419566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
49429566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, cdim));
49438ca92349SMatthew G. Knepley   /* Read topology */
4944dd400576SPatrick Sanan   if (rank == 0) {
4945f8d5e320SMatthew G. Knepley     char     format[PETSC_MAX_PATH_LEN];
4946f8d5e320SMatthew G. Knepley     PetscInt cone[8];
49478ca92349SMatthew G. Knepley     int      vbuf[8], v;
49488ca92349SMatthew G. Knepley 
49499371c9d4SSatish Balay     for (c = 0; c < Ncn; ++c) {
49509371c9d4SSatish Balay       format[c * 3 + 0] = '%';
49519371c9d4SSatish Balay       format[c * 3 + 1] = 'd';
49529371c9d4SSatish Balay       format[c * 3 + 2] = ' ';
49539371c9d4SSatish Balay     }
4954f8d5e320SMatthew G. Knepley     format[Ncn * 3 - 1] = '\0';
49559566063dSJacob Faibussowitsch     for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn));
49569566063dSJacob Faibussowitsch     PetscCall(DMSetUp(*dm));
49578ca92349SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
49589566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING));
4959f8d5e320SMatthew G. Knepley       switch (Ncn) {
4960d71ae5a4SJacob Faibussowitsch       case 2:
4961d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1]);
4962d71ae5a4SJacob Faibussowitsch         break;
4963d71ae5a4SJacob Faibussowitsch       case 3:
4964d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]);
4965d71ae5a4SJacob Faibussowitsch         break;
4966d71ae5a4SJacob Faibussowitsch       case 4:
4967d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]);
4968d71ae5a4SJacob Faibussowitsch         break;
4969d71ae5a4SJacob Faibussowitsch       case 6:
4970d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]);
4971d71ae5a4SJacob Faibussowitsch         break;
4972d71ae5a4SJacob Faibussowitsch       case 8:
4973d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]);
4974d71ae5a4SJacob Faibussowitsch         break;
4975d71ae5a4SJacob Faibussowitsch       default:
4976d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn);
4977f8d5e320SMatthew G. Knepley       }
497808401ef6SPierre Jolivet       PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
4979f8d5e320SMatthew G. Knepley       for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc;
49808ca92349SMatthew G. Knepley       /* Hexahedra are inverted */
4981f8d5e320SMatthew G. Knepley       if (Ncn == 8) {
49828ca92349SMatthew G. Knepley         PetscInt tmp = cone[1];
49838ca92349SMatthew G. Knepley         cone[1]      = cone[3];
49848ca92349SMatthew G. Knepley         cone[3]      = tmp;
49858ca92349SMatthew G. Knepley       }
49869566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(*dm, c, cone));
49878ca92349SMatthew G. Knepley     }
49888ca92349SMatthew G. Knepley   }
49899566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
49909566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
49918ca92349SMatthew G. Knepley   /* Read coordinates */
49929566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
49939566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
49949566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
49959566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
49968ca92349SMatthew G. Knepley   for (v = Nc; v < Nc + Nv; ++v) {
49979566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
49989566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
49998ca92349SMatthew G. Knepley   }
50009566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
50019566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
50029566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
50039566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
50049566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
50059566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
50069566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
50079566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
5008dd400576SPatrick Sanan   if (rank == 0) {
5009f8d5e320SMatthew G. Knepley     char   format[PETSC_MAX_PATH_LEN];
50108ca92349SMatthew G. Knepley     double x[3];
5011f8d5e320SMatthew G. Knepley     int    l, val[3];
50128ca92349SMatthew G. Knepley 
5013f8d5e320SMatthew G. Knepley     if (Nl) {
50149371c9d4SSatish Balay       for (l = 0; l < Nl; ++l) {
50159371c9d4SSatish Balay         format[l * 3 + 0] = '%';
50169371c9d4SSatish Balay         format[l * 3 + 1] = 'd';
50179371c9d4SSatish Balay         format[l * 3 + 2] = ' ';
50189371c9d4SSatish Balay       }
5019f8d5e320SMatthew G. Knepley       format[Nl * 3 - 1] = '\0';
50209566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
50219566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &marker));
5022f8d5e320SMatthew G. Knepley     }
50238ca92349SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
50249566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING));
5025f8d5e320SMatthew G. Knepley       snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]);
502608401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
5027f8d5e320SMatthew G. Knepley       switch (Nl) {
5028d71ae5a4SJacob Faibussowitsch       case 0:
5029d71ae5a4SJacob Faibussowitsch         snum = 0;
5030d71ae5a4SJacob Faibussowitsch         break;
5031d71ae5a4SJacob Faibussowitsch       case 1:
5032d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0]);
5033d71ae5a4SJacob Faibussowitsch         break;
5034d71ae5a4SJacob Faibussowitsch       case 2:
5035d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1]);
5036d71ae5a4SJacob Faibussowitsch         break;
5037d71ae5a4SJacob Faibussowitsch       case 3:
5038d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1], &val[2]);
5039d71ae5a4SJacob Faibussowitsch         break;
5040d71ae5a4SJacob Faibussowitsch       default:
5041d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl);
5042f8d5e320SMatthew G. Knepley       }
504308401ef6SPierre Jolivet       PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
50448ca92349SMatthew G. Knepley       for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d];
50459566063dSJacob Faibussowitsch       for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l]));
50468ca92349SMatthew G. Knepley     }
50478ca92349SMatthew G. Knepley   }
50489566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
50499566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
50509566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
50519566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
50528ca92349SMatthew G. Knepley   if (interpolate) {
50538ca92349SMatthew G. Knepley     DM      idm;
50548ca92349SMatthew G. Knepley     DMLabel bdlabel;
50558ca92349SMatthew G. Knepley 
50569566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
50579566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
50588ca92349SMatthew G. Knepley     *dm = idm;
50598ca92349SMatthew G. Knepley 
5060f8d5e320SMatthew G. Knepley     if (!Nl) {
50619566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
50629566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &bdlabel));
50639566063dSJacob Faibussowitsch       PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel));
50649566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelComplete(*dm, bdlabel));
50658ca92349SMatthew G. Knepley     }
5066f8d5e320SMatthew G. Knepley   }
50678ca92349SMatthew G. Knepley   PetscFunctionReturn(0);
50688ca92349SMatthew G. Knepley }
50698ca92349SMatthew G. Knepley 
50708ca92349SMatthew G. Knepley /*@C
5071ca522641SMatthew G. Knepley   DMPlexCreateFromFile - This takes a filename and produces a DM
5072ca522641SMatthew G. Knepley 
5073ca522641SMatthew G. Knepley   Input Parameters:
5074ca522641SMatthew G. Knepley + comm - The communicator
5075ca522641SMatthew G. Knepley . filename - A file name
5076cd7e8a5eSksagiyam . plexname - The object name of the resulting DM, also used for intra-datafile lookup by some formats
5077ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
5078ca522641SMatthew G. Knepley 
5079ca522641SMatthew G. Knepley   Output Parameter:
5080ca522641SMatthew G. Knepley . dm - The DM
5081ca522641SMatthew G. Knepley 
508202ef0d99SVaclav Hapla   Options Database Keys:
508302ef0d99SVaclav Hapla . -dm_plex_create_from_hdf5_xdmf - use the PETSC_VIEWER_HDF5_XDMF format for reading HDF5
508402ef0d99SVaclav Hapla 
5085bca97951SVaclav Hapla   Use -dm_plex_create_ prefix to pass options to the internal PetscViewer, e.g.
5086bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective
5087bca97951SVaclav Hapla 
5088cd7e8a5eSksagiyam   Notes:
5089cd7e8a5eSksagiyam   Using PETSCVIEWERHDF5 type with PETSC_VIEWER_HDF5_PETSC format, one can save multiple DMPlex
5090cd7e8a5eSksagiyam   meshes in a single HDF5 file. This in turn requires one to name the DMPlex object with PetscObjectSetName()
5091cd7e8a5eSksagiyam   before saving it with DMView() and before loading it with DMLoad() for identification of the mesh object.
5092cd7e8a5eSksagiyam   The input parameter name is thus used to name the DMPlex object when DMPlexCreateFromFile() internally
5093cd7e8a5eSksagiyam   calls DMLoad(). Currently, name is ignored for other viewer types and/or formats.
5094cd7e8a5eSksagiyam 
5095ca522641SMatthew G. Knepley   Level: beginner
5096ca522641SMatthew G. Knepley 
5097db781477SPatrick Sanan .seealso: `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()`
5098ca522641SMatthew G. Knepley @*/
5099d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm)
5100d71ae5a4SJacob Faibussowitsch {
5101ef3a5affSJacob Faibussowitsch   const char  extGmsh[]      = ".msh";
5102ef3a5affSJacob Faibussowitsch   const char  extGmsh2[]     = ".msh2";
5103ef3a5affSJacob Faibussowitsch   const char  extGmsh4[]     = ".msh4";
5104ef3a5affSJacob Faibussowitsch   const char  extCGNS[]      = ".cgns";
5105ef3a5affSJacob Faibussowitsch   const char  extExodus[]    = ".exo";
5106ef3a5affSJacob Faibussowitsch   const char  extExodus_e[]  = ".e";
5107ef3a5affSJacob Faibussowitsch   const char  extGenesis[]   = ".gen";
5108ef3a5affSJacob Faibussowitsch   const char  extFluent[]    = ".cas";
5109ef3a5affSJacob Faibussowitsch   const char  extHDF5[]      = ".h5";
5110ef3a5affSJacob Faibussowitsch   const char  extMed[]       = ".med";
5111ef3a5affSJacob Faibussowitsch   const char  extPLY[]       = ".ply";
5112ef3a5affSJacob Faibussowitsch   const char  extEGADSLite[] = ".egadslite";
5113ef3a5affSJacob Faibussowitsch   const char  extEGADS[]     = ".egads";
5114ef3a5affSJacob Faibussowitsch   const char  extIGES[]      = ".igs";
5115ef3a5affSJacob Faibussowitsch   const char  extSTEP[]      = ".stp";
5116ef3a5affSJacob Faibussowitsch   const char  extCV[]        = ".dat";
5117ca522641SMatthew G. Knepley   size_t      len;
5118c1cad2e7SMatthew G. Knepley   PetscBool   isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isMed, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV;
5119ca522641SMatthew G. Knepley   PetscMPIInt rank;
5120ca522641SMatthew G. Knepley 
5121ca522641SMatthew G. Knepley   PetscFunctionBegin;
51225d80c0bfSVaclav Hapla   PetscValidCharPointer(filename, 2);
51230d862eaeSPierre Jolivet   if (plexname) PetscValidCharPointer(plexname, 3);
5124cd7e8a5eSksagiyam   PetscValidPointer(dm, 5);
51259566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
51269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0));
51279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
51289566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(filename, &len));
512928b400f6SJacob Faibussowitsch   PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path");
5130ef3a5affSJacob Faibussowitsch 
51319371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \
51329371c9d4SSatish Balay   do { \
5133274aaeaaSJacob Faibussowitsch     PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \
5134274aaeaaSJacob Faibussowitsch     /* don't count the null-terminator at the end */ \
5135274aaeaaSJacob Faibussowitsch     const size_t ext_len = sizeof(extension__) - 1; \
5136274aaeaaSJacob Faibussowitsch     if (len < ext_len) { \
5137ef3a5affSJacob Faibussowitsch       is_extension__ = PETSC_FALSE; \
5138ef3a5affSJacob Faibussowitsch     } else { \
5139274aaeaaSJacob Faibussowitsch       PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \
5140ef3a5affSJacob Faibussowitsch     } \
5141ef3a5affSJacob Faibussowitsch   } while (0)
5142ef3a5affSJacob Faibussowitsch 
5143ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh, isGmsh);
5144ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh2, isGmsh2);
5145ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh4, isGmsh4);
5146ef3a5affSJacob Faibussowitsch   CheckExtension(extCGNS, isCGNS);
5147ef3a5affSJacob Faibussowitsch   CheckExtension(extExodus, isExodus);
5148ef3a5affSJacob Faibussowitsch   if (!isExodus) CheckExtension(extExodus_e, isExodus);
5149ef3a5affSJacob Faibussowitsch   CheckExtension(extGenesis, isGenesis);
5150ef3a5affSJacob Faibussowitsch   CheckExtension(extFluent, isFluent);
5151ef3a5affSJacob Faibussowitsch   CheckExtension(extHDF5, isHDF5);
5152ef3a5affSJacob Faibussowitsch   CheckExtension(extMed, isMed);
5153ef3a5affSJacob Faibussowitsch   CheckExtension(extPLY, isPLY);
5154ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADSLite, isEGADSLite);
5155ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADS, isEGADS);
5156ef3a5affSJacob Faibussowitsch   CheckExtension(extIGES, isIGES);
5157ef3a5affSJacob Faibussowitsch   CheckExtension(extSTEP, isSTEP);
5158ef3a5affSJacob Faibussowitsch   CheckExtension(extCV, isCV);
5159ef3a5affSJacob Faibussowitsch 
5160ef3a5affSJacob Faibussowitsch #undef CheckExtension
5161ef3a5affSJacob Faibussowitsch 
5162de78e4feSLisandro Dalcin   if (isGmsh || isGmsh2 || isGmsh4) {
51639566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm));
5164ca522641SMatthew G. Knepley   } else if (isCGNS) {
51659566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm));
516690c68965SMatthew G. Knepley   } else if (isExodus || isGenesis) {
51679566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm));
51682f0bd6dcSMichael Lange   } else if (isFluent) {
51699566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm));
5170cc2f8f65SMatthew G. Knepley   } else if (isHDF5) {
51719c48423bSVaclav Hapla     PetscBool   load_hdf5_xdmf = PETSC_FALSE;
5172cc2f8f65SMatthew G. Knepley     PetscViewer viewer;
5173cc2f8f65SMatthew G. Knepley 
517443b242b4SVaclav 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 */
51759566063dSJacob Faibussowitsch     PetscCall(PetscStrncmp(&filename[PetscMax(0, len - 8)], ".xdmf", 5, &load_hdf5_xdmf));
51769566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &load_hdf5_xdmf, NULL));
51779566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(comm, &viewer));
51789566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5));
51799566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_"));
51809566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetFromOptions(viewer));
51819566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
51829566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(viewer, filename));
5183cd7e8a5eSksagiyam 
51849566063dSJacob Faibussowitsch     PetscCall(DMCreate(comm, dm));
51859566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname));
51869566063dSJacob Faibussowitsch     PetscCall(DMSetType(*dm, DMPLEX));
51879566063dSJacob Faibussowitsch     if (load_hdf5_xdmf) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF));
51889566063dSJacob Faibussowitsch     PetscCall(DMLoad(*dm, viewer));
51899566063dSJacob Faibussowitsch     if (load_hdf5_xdmf) PetscCall(PetscViewerPopFormat(viewer));
51909566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
51915fd9971aSMatthew G. Knepley 
51925fd9971aSMatthew G. Knepley     if (interpolate) {
51935fd9971aSMatthew G. Knepley       DM idm;
51945fd9971aSMatthew G. Knepley 
51959566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm));
51969566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
51975fd9971aSMatthew G. Knepley       *dm = idm;
51985fd9971aSMatthew G. Knepley     }
5199707dd687SMichael Lange   } else if (isMed) {
52009566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateMedFromFile(comm, filename, interpolate, dm));
5201f2801cd6SMatthew G. Knepley   } else if (isPLY) {
52029566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm));
5203c1cad2e7SMatthew G. Knepley   } else if (isEGADSLite || isEGADS || isIGES || isSTEP) {
52049566063dSJacob Faibussowitsch     if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm));
52059566063dSJacob Faibussowitsch     else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm));
52067bee2925SMatthew Knepley     if (!interpolate) {
52077bee2925SMatthew Knepley       DM udm;
52087bee2925SMatthew Knepley 
52099566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(*dm, &udm));
52109566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
52117bee2925SMatthew Knepley       *dm = udm;
52127bee2925SMatthew Knepley     }
52138ca92349SMatthew G. Knepley   } else if (isCV) {
52149566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm));
521598921bdaSJacob Faibussowitsch   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename);
52169566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(plexname, &len));
52179566063dSJacob Faibussowitsch   if (len) PetscCall(PetscObjectSetName((PetscObject)(*dm), plexname));
52189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0));
5219ca522641SMatthew G. Knepley   PetscFunctionReturn(0);
5220ca522641SMatthew G. Knepley }
5221