xref: /petsc/src/dm/impls/plex/plexcreate.c (revision 22d6dc081b2bdf689b9a42b21f546588ee2028de)
1552f7358SJed Brown #define PETSCDM_DLL
2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I   "petscdmplex.h"   I*/
3cc4c1da9SBarry Smith #include <petsc/private/hashseti.h>
40c312b8eSJed Brown #include <petscsf.h>
5cc4c1da9SBarry Smith #include <petscdmplextransform.h> /*I   "petscdmplextransform.h"   I*/
69f6c5813SMatthew G. Knepley #include <petscdmlabelephemeral.h>
7b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h>
8b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h>
9552f7358SJed Brown 
10d0812dedSMatthew G. Knepley #ifdef PETSC_HAVE_UNISTD_H
11d0812dedSMatthew G. Knepley   #include <unistd.h>
12d0812dedSMatthew G. Knepley #endif
13d0812dedSMatthew G. Knepley #include <errno.h>
14d0812dedSMatthew G. Knepley 
15708be2fdSJed Brown PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_CreateFromOptions, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList;
1658cd63d5SVaclav Hapla 
179318fe57SMatthew G. Knepley /* External function declarations here */
189318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm);
199318fe57SMatthew G. Knepley 
20e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */
21d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout)
22d71ae5a4SJacob Faibussowitsch {
234fb89dddSMatthew G. Knepley   const PetscReal     *maxCell, *Lstart, *L;
2412a88998SMatthew G. Knepley   VecType              vecType;
2512a88998SMatthew G. Knepley   MatType              matType;
265962854dSMatthew G. Knepley   PetscBool            dist, useCeed;
27adc21957SMatthew G. Knepley   DMReorderDefaultFlag reorder;
28e600fa54SMatthew G. Knepley 
29e600fa54SMatthew G. Knepley   PetscFunctionBegin;
3012a88998SMatthew G. Knepley   PetscCall(DMGetVecType(dmin, &vecType));
3112a88998SMatthew G. Knepley   PetscCall(DMSetVecType(dmout, vecType));
3212a88998SMatthew G. Knepley   PetscCall(DMGetMatType(dmin, &matType));
3312a88998SMatthew G. Knepley   PetscCall(DMSetMatType(dmout, matType));
34e600fa54SMatthew G. Knepley   if (copyPeriodicity) {
354fb89dddSMatthew G. Knepley     PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L));
364fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L));
373d0e8ed9SDavid Salac     PetscCall(DMLocalizeCoordinates(dmout));
38e600fa54SMatthew G. Knepley   }
399566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dmin, &dist));
409566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeSetDefault(dmout, dist));
416bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dmin, &reorder));
426bc1bd01Sksagiyam   PetscCall(DMPlexReorderSetDefault(dmout, reorder));
435962854dSMatthew G. Knepley   PetscCall(DMPlexGetUseCeed(dmin, &useCeed));
445962854dSMatthew G. Knepley   PetscCall(DMPlexSetUseCeed(dmout, useCeed));
45e600fa54SMatthew G. Knepley   ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation;
465962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printSetValues  = ((DM_Plex *)dmin->data)->printSetValues;
475962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printFEM        = ((DM_Plex *)dmin->data)->printFEM;
485962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printFVM        = ((DM_Plex *)dmin->data)->printFVM;
495962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printL2         = ((DM_Plex *)dmin->data)->printL2;
505962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printLocate     = ((DM_Plex *)dmin->data)->printLocate;
51a77a5016SMatthew G. Knepley   ((DM_Plex *)dmout->data)->printProject    = ((DM_Plex *)dmin->data)->printProject;
525962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printTol        = ((DM_Plex *)dmin->data)->printTol;
531baa6e33SBarry Smith   if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0));
543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55e600fa54SMatthew G. Knepley }
56e600fa54SMatthew G. Knepley 
579318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm
589318fe57SMatthew G. Knepley    - Share the DM_Plex structure
599318fe57SMatthew G. Knepley    - Share the coordinates
609318fe57SMatthew G. Knepley    - Share the SF
619318fe57SMatthew G. Knepley */
62d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm)
63d71ae5a4SJacob Faibussowitsch {
649318fe57SMatthew G. Knepley   PetscSF          sf;
659318fe57SMatthew G. Knepley   DM               dmNew = *ndm, coordDM, coarseDM;
669318fe57SMatthew G. Knepley   Vec              coords;
674fb89dddSMatthew G. Knepley   const PetscReal *maxCell, *Lstart, *L;
689318fe57SMatthew G. Knepley   PetscInt         dim, cdim;
699318fe57SMatthew G. Knepley 
709318fe57SMatthew G. Knepley   PetscFunctionBegin;
719318fe57SMatthew G. Knepley   if (dm == dmNew) {
729566063dSJacob Faibussowitsch     PetscCall(DMDestroy(ndm));
733ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
749318fe57SMatthew G. Knepley   }
759318fe57SMatthew G. Knepley   dm->setupcalled = dmNew->setupcalled;
76d0812dedSMatthew G. Knepley   if (!dm->hdr.name) {
77d0812dedSMatthew G. Knepley     const char *name;
78d0812dedSMatthew G. Knepley 
79d0812dedSMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)*ndm, &name));
80d0812dedSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, name));
81d0812dedSMatthew G. Knepley   }
829566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dmNew, &dim));
839566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
849566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmNew, &cdim));
859566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
869566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmNew, &sf));
879566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sf));
889566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmNew, &coordDM));
899566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmNew, &coords));
909566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dm, coordDM));
919566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coords));
926858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM));
936858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords));
946858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dm, coordDM));
956858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dm, coords));
969318fe57SMatthew G. Knepley   /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */
976858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&dm->coordinates[0].field));
986858538eSMatthew G. Knepley   dm->coordinates[0].field            = dmNew->coordinates[0].field;
9961a622f3SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc;
1004fb89dddSMatthew G. Knepley   PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L));
1014fb89dddSMatthew G. Knepley   PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
1026925d1c4SMatthew G. Knepley   PetscCall(DMPlexGetGlobalToNaturalSF(dmNew, &sf));
1036925d1c4SMatthew G. Knepley   PetscCall(DMPlexSetGlobalToNaturalSF(dm, sf));
1049566063dSJacob Faibussowitsch   PetscCall(DMDestroy_Plex(dm));
1059566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
1069318fe57SMatthew G. Knepley   dm->data = dmNew->data;
1079318fe57SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->refct++;
1081fca310dSJames Wright   {
1091fca310dSJames Wright     PetscInt       num_face_sfs;
1101fca310dSJames Wright     const PetscSF *sfs;
1111fca310dSJames Wright     PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &sfs));
1121fca310dSJames Wright     PetscCall(DMPlexSetIsoperiodicFaceSF(dm, num_face_sfs, (PetscSF *)sfs)); // for the compose function effect on dm
1131fca310dSJames Wright   }
1149566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(dm));
1159566063dSJacob Faibussowitsch   PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL));
1169566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmNew, &coarseDM));
1179566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dm, coarseDM));
1189566063dSJacob Faibussowitsch   PetscCall(DMDestroy(ndm));
1193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1209318fe57SMatthew G. Knepley }
1219318fe57SMatthew G. Knepley 
1229318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew
1239318fe57SMatthew G. Knepley    - Swap the DM_Plex structure
1249318fe57SMatthew G. Knepley    - Swap the coordinates
1259318fe57SMatthew G. Knepley    - Swap the point PetscSF
1269318fe57SMatthew G. Knepley */
127d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB)
128d71ae5a4SJacob Faibussowitsch {
1299318fe57SMatthew G. Knepley   DM          coordDMA, coordDMB;
1309318fe57SMatthew G. Knepley   Vec         coordsA, coordsB;
1319318fe57SMatthew G. Knepley   PetscSF     sfA, sfB;
1329318fe57SMatthew G. Knepley   DMField     fieldTmp;
1339318fe57SMatthew G. Knepley   void       *tmp;
1349318fe57SMatthew G. Knepley   DMLabelLink listTmp;
1359318fe57SMatthew G. Knepley   DMLabel     depthTmp;
1369318fe57SMatthew G. Knepley   PetscInt    tmpI;
1379318fe57SMatthew G. Knepley 
1389318fe57SMatthew G. Knepley   PetscFunctionBegin;
1393ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
1409566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmA, &sfA));
1419566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmB, &sfB));
1429566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sfA));
1439566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmA, sfB));
1449566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmB, sfA));
1459566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)sfA));
1469318fe57SMatthew G. Knepley 
1479566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmA, &coordDMA));
1489566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmB, &coordDMB));
1499566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordDMA));
1509566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmA, coordDMB));
1519566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmB, coordDMA));
1529566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
1539318fe57SMatthew G. Knepley 
1549566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordsA));
1559566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmB, &coordsB));
1569566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordsA));
1579566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmA, coordsB));
1589566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordsA));
1599566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordsA));
1609318fe57SMatthew G. Knepley 
1616858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA));
1626858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB));
1636858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordDMA));
1646858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmA, coordDMB));
1656858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmB, coordDMA));
1666858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
1676858538eSMatthew G. Knepley 
1686858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA));
1696858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB));
1706858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordsA));
1716858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB));
1726858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA));
1736858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordsA));
1746858538eSMatthew G. Knepley 
1756858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[0].field;
1766858538eSMatthew G. Knepley   dmA->coordinates[0].field = dmB->coordinates[0].field;
1776858538eSMatthew G. Knepley   dmB->coordinates[0].field = fieldTmp;
1786858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[1].field;
1796858538eSMatthew G. Knepley   dmA->coordinates[1].field = dmB->coordinates[1].field;
1806858538eSMatthew G. Knepley   dmB->coordinates[1].field = fieldTmp;
1819318fe57SMatthew G. Knepley   tmp                       = dmA->data;
1829318fe57SMatthew G. Knepley   dmA->data                 = dmB->data;
1839318fe57SMatthew G. Knepley   dmB->data                 = tmp;
1849318fe57SMatthew G. Knepley   listTmp                   = dmA->labels;
1859318fe57SMatthew G. Knepley   dmA->labels               = dmB->labels;
1869318fe57SMatthew G. Knepley   dmB->labels               = listTmp;
1879318fe57SMatthew G. Knepley   depthTmp                  = dmA->depthLabel;
1889318fe57SMatthew G. Knepley   dmA->depthLabel           = dmB->depthLabel;
1899318fe57SMatthew G. Knepley   dmB->depthLabel           = depthTmp;
1909318fe57SMatthew G. Knepley   depthTmp                  = dmA->celltypeLabel;
1919318fe57SMatthew G. Knepley   dmA->celltypeLabel        = dmB->celltypeLabel;
1929318fe57SMatthew G. Knepley   dmB->celltypeLabel        = depthTmp;
1939318fe57SMatthew G. Knepley   tmpI                      = dmA->levelup;
1949318fe57SMatthew G. Knepley   dmA->levelup              = dmB->levelup;
1959318fe57SMatthew G. Knepley   dmB->levelup              = tmpI;
1963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1979318fe57SMatthew G. Knepley }
1989318fe57SMatthew G. Knepley 
1993431e603SJed Brown PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm)
200d71ae5a4SJacob Faibussowitsch {
2019318fe57SMatthew G. Knepley   DM idm;
2029318fe57SMatthew G. Knepley 
2039318fe57SMatthew G. Knepley   PetscFunctionBegin;
2049566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolate(dm, &idm));
2059566063dSJacob Faibussowitsch   PetscCall(DMPlexCopyCoordinates(dm, idm));
20669d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &idm));
2073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2089318fe57SMatthew G. Knepley }
2099318fe57SMatthew G. Knepley 
2109318fe57SMatthew G. Knepley /*@C
2119318fe57SMatthew G. Knepley   DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates
2129318fe57SMatthew G. Knepley 
21320f4b53cSBarry Smith   Collective
2149318fe57SMatthew G. Knepley 
2159318fe57SMatthew G. Knepley   Input Parameters:
21660225df5SJacob Faibussowitsch + dm        - The `DMPLEX`
21720f4b53cSBarry Smith . degree    - The degree of the finite element or `PETSC_DECIDE`
218e44f6aebSMatthew G. Knepley . project   - Flag to project current coordinates into the space
2199318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface
2209318fe57SMatthew G. Knepley 
2219318fe57SMatthew G. Knepley   Level: advanced
2229318fe57SMatthew G. Knepley 
2231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPointFunc`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()`
2249318fe57SMatthew G. Knepley @*/
225e44f6aebSMatthew G. Knepley PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscBool project, PetscPointFunc coordFunc)
226d71ae5a4SJacob Faibussowitsch {
2279318fe57SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
228e44f6aebSMatthew G. Knepley   PetscFE  fe   = NULL;
2299318fe57SMatthew G. Knepley   DM       cdm;
2301df12153SMatthew G. Knepley   PetscInt dim, dE, qorder, height;
2319318fe57SMatthew G. Knepley 
232e44f6aebSMatthew G. Knepley   PetscFunctionBegin;
2339566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
2349566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
2359318fe57SMatthew G. Knepley   qorder = degree;
236e44f6aebSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
237d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)cdm);
238dc431b0cSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0));
239d0609cedSBarry Smith   PetscOptionsEnd();
2401df12153SMatthew G. Knepley   PetscCall(DMPlexGetVTKCellHeight(dm, &height));
241e44f6aebSMatthew G. Knepley   if (degree >= 0) {
242e44f6aebSMatthew G. Knepley     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
243e44f6aebSMatthew G. Knepley     PetscInt       cStart, cEnd, gct;
244dc431b0cSMatthew G. Knepley 
2451df12153SMatthew G. Knepley     PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd));
246dc431b0cSMatthew G. Knepley     if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct));
247e44f6aebSMatthew G. Knepley     gct = (PetscInt)ct;
248462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &gct, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm)));
249e44f6aebSMatthew G. Knepley     ct = (DMPolytopeType)gct;
250e44f6aebSMatthew G. Knepley     // Work around current bug in PetscDualSpaceSetUp_Lagrange()
251e44f6aebSMatthew G. Knepley     //   Can be seen in plex_tutorials-ex10_1
252e44f6aebSMatthew G. Knepley     if (ct != DM_POLYTOPE_SEG_PRISM_TENSOR && ct != DM_POLYTOPE_TRI_PRISM_TENSOR && ct != DM_POLYTOPE_QUAD_PRISM_TENSOR) PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe));
2534f9ab2b4SJed Brown   }
254e44f6aebSMatthew G. Knepley   PetscCall(DMSetCoordinateDisc(dm, fe, project));
2559566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
2569318fe57SMatthew G. Knepley   mesh->coordFunc = coordFunc;
2573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2589318fe57SMatthew G. Knepley }
2599318fe57SMatthew G. Knepley 
2601df5d5c5SMatthew G. Knepley /*@
2611df5d5c5SMatthew G. Knepley   DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement.
2621df5d5c5SMatthew G. Knepley 
263d083f849SBarry Smith   Collective
2641df5d5c5SMatthew G. Knepley 
2651df5d5c5SMatthew G. Knepley   Input Parameters:
266a1cb98faSBarry Smith + comm            - The communicator for the `DM` object
2671df5d5c5SMatthew G. Knepley . dim             - The spatial dimension
2681df5d5c5SMatthew G. Knepley . simplex         - Flag for simplicial cells, otherwise they are tensor product cells
2691df5d5c5SMatthew G. Knepley . interpolate     - Flag to create intermediate mesh pieces (edges, faces)
2701df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell
2711df5d5c5SMatthew G. Knepley 
2721df5d5c5SMatthew G. Knepley   Output Parameter:
27360225df5SJacob Faibussowitsch . newdm - The `DM` object
2741df5d5c5SMatthew G. Knepley 
2751df5d5c5SMatthew G. Knepley   Level: beginner
2761df5d5c5SMatthew G. Knepley 
2771cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()`
2781df5d5c5SMatthew G. Knepley @*/
279d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm)
280d71ae5a4SJacob Faibussowitsch {
2811df5d5c5SMatthew G. Knepley   DM          dm;
2821df5d5c5SMatthew G. Knepley   PetscMPIInt rank;
2831df5d5c5SMatthew G. Knepley 
2841df5d5c5SMatthew G. Knepley   PetscFunctionBegin;
2859566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, &dm));
2869566063dSJacob Faibussowitsch   PetscCall(DMSetType(dm, DMPLEX));
2879566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
28846139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
2899566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
290ce78fa2fSMatthew G. Knepley   switch (dim) {
291ce78fa2fSMatthew G. Knepley   case 2:
2929566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular"));
2939566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral"));
294ce78fa2fSMatthew G. Knepley     break;
295ce78fa2fSMatthew G. Knepley   case 3:
2969566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral"));
2979566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral"));
298ce78fa2fSMatthew G. Knepley     break;
299d71ae5a4SJacob Faibussowitsch   default:
300d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
301ce78fa2fSMatthew G. Knepley   }
3021df5d5c5SMatthew G. Knepley   if (rank) {
3031df5d5c5SMatthew G. Knepley     PetscInt numPoints[2] = {0, 0};
3049566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL));
3051df5d5c5SMatthew G. Knepley   } else {
3061df5d5c5SMatthew G. Knepley     switch (dim) {
3071df5d5c5SMatthew G. Knepley     case 2:
3081df5d5c5SMatthew G. Knepley       if (simplex) {
3091df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {4, 2};
3101df5d5c5SMatthew G. Knepley         PetscInt    coneSize[6]         = {3, 3, 0, 0, 0, 0};
3111df5d5c5SMatthew G. Knepley         PetscInt    cones[6]            = {2, 3, 4, 5, 4, 3};
3121df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
3131df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[8]     = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5};
3141df5d5c5SMatthew G. Knepley 
3159566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
3161df5d5c5SMatthew G. Knepley       } else {
3171df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {6, 2};
3181df5d5c5SMatthew G. Knepley         PetscInt    coneSize[8]         = {4, 4, 0, 0, 0, 0, 0, 0};
3191df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {2, 3, 4, 5, 3, 6, 7, 4};
3201df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
3211df5d5c5SMatthew 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};
3221df5d5c5SMatthew G. Knepley 
3239566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
3241df5d5c5SMatthew G. Knepley       }
3251df5d5c5SMatthew G. Knepley       break;
3261df5d5c5SMatthew G. Knepley     case 3:
3271df5d5c5SMatthew G. Knepley       if (simplex) {
3281df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {5, 2};
3291df5d5c5SMatthew G. Knepley         PetscInt    coneSize[7]         = {4, 4, 0, 0, 0, 0, 0};
3301df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {4, 3, 5, 2, 5, 3, 4, 6};
3311df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
3321df5d5c5SMatthew 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};
3331df5d5c5SMatthew G. Knepley 
3349566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
3351df5d5c5SMatthew G. Knepley       } else {
3361df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]         = {12, 2};
3371df5d5c5SMatthew G. Knepley         PetscInt    coneSize[14]         = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3381df5d5c5SMatthew G. Knepley         PetscInt    cones[16]            = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8};
3391df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
3409371c9d4SSatish 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};
3411df5d5c5SMatthew G. Knepley 
3429566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
3431df5d5c5SMatthew G. Knepley       }
3441df5d5c5SMatthew G. Knepley       break;
345d71ae5a4SJacob Faibussowitsch     default:
346d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
3471df5d5c5SMatthew G. Knepley     }
3481df5d5c5SMatthew G. Knepley   }
34946139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
3501df5d5c5SMatthew G. Knepley   *newdm = dm;
3511df5d5c5SMatthew G. Knepley   if (refinementLimit > 0.0) {
3521df5d5c5SMatthew G. Knepley     DM          rdm;
3531df5d5c5SMatthew G. Knepley     const char *name;
3541df5d5c5SMatthew G. Knepley 
3559566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE));
3569566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit));
3579566063dSJacob Faibussowitsch     PetscCall(DMRefine(*newdm, comm, &rdm));
3589566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)*newdm, &name));
3599566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)rdm, name));
3609566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
3611df5d5c5SMatthew G. Knepley     *newdm = rdm;
3621df5d5c5SMatthew G. Knepley   }
3631df5d5c5SMatthew G. Knepley   if (interpolate) {
3645fd9971aSMatthew G. Knepley     DM idm;
3651df5d5c5SMatthew G. Knepley 
3669566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*newdm, &idm));
3679566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
3681df5d5c5SMatthew G. Knepley     *newdm = idm;
3691df5d5c5SMatthew G. Knepley   }
3703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3711df5d5c5SMatthew G. Knepley }
3721df5d5c5SMatthew G. Knepley 
373d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
374d71ae5a4SJacob Faibussowitsch {
3759318fe57SMatthew G. Knepley   const PetscInt numVertices    = 2;
3769318fe57SMatthew G. Knepley   PetscInt       markerRight    = 1;
3779318fe57SMatthew G. Knepley   PetscInt       markerLeft     = 1;
3789318fe57SMatthew G. Knepley   PetscBool      markerSeparate = PETSC_FALSE;
3799318fe57SMatthew G. Knepley   Vec            coordinates;
3809318fe57SMatthew G. Knepley   PetscSection   coordSection;
3819318fe57SMatthew G. Knepley   PetscScalar   *coords;
3829318fe57SMatthew G. Knepley   PetscInt       coordSize;
3839318fe57SMatthew G. Knepley   PetscMPIInt    rank;
3849318fe57SMatthew G. Knepley   PetscInt       cdim = 1, v;
385552f7358SJed Brown 
3869318fe57SMatthew G. Knepley   PetscFunctionBegin;
3879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
3889318fe57SMatthew G. Knepley   if (markerSeparate) {
3899318fe57SMatthew G. Knepley     markerRight = 2;
3909318fe57SMatthew G. Knepley     markerLeft  = 1;
3919318fe57SMatthew G. Knepley   }
3929566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
393c5853193SPierre Jolivet   if (rank == 0) {
3949566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numVertices));
3959566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3969566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft));
3979566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight));
3989318fe57SMatthew G. Knepley   }
3999566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
4009566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
4019318fe57SMatthew G. Knepley   /* Build coordinates */
4029566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
4039566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
4049566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
4059566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, 0, numVertices));
4069566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
4079318fe57SMatthew G. Knepley   for (v = 0; v < numVertices; ++v) {
4089566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
4099566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
4109318fe57SMatthew G. Knepley   }
4119566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
4129566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
4139566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
4149566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
4159566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
4169566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
4179566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
4189566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
4199318fe57SMatthew G. Knepley   coords[0] = lower[0];
4209318fe57SMatthew G. Knepley   coords[1] = upper[0];
4219566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
4229566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
4239566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
4243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4259318fe57SMatthew G. Knepley }
42626492d91SMatthew G. Knepley 
427d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
428d71ae5a4SJacob Faibussowitsch {
4291df21d24SMatthew G. Knepley   const PetscInt numVertices    = (edges[0] + 1) * (edges[1] + 1);
4301df21d24SMatthew G. Knepley   const PetscInt numEdges       = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1];
431552f7358SJed Brown   PetscInt       markerTop      = 1;
432552f7358SJed Brown   PetscInt       markerBottom   = 1;
433552f7358SJed Brown   PetscInt       markerRight    = 1;
434552f7358SJed Brown   PetscInt       markerLeft     = 1;
435552f7358SJed Brown   PetscBool      markerSeparate = PETSC_FALSE;
436552f7358SJed Brown   Vec            coordinates;
437552f7358SJed Brown   PetscSection   coordSection;
438552f7358SJed Brown   PetscScalar   *coords;
439552f7358SJed Brown   PetscInt       coordSize;
440552f7358SJed Brown   PetscMPIInt    rank;
441552f7358SJed Brown   PetscInt       v, vx, vy;
442552f7358SJed Brown 
443552f7358SJed Brown   PetscFunctionBegin;
4449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
445552f7358SJed Brown   if (markerSeparate) {
4461df21d24SMatthew G. Knepley     markerTop    = 3;
4471df21d24SMatthew G. Knepley     markerBottom = 1;
4481df21d24SMatthew G. Knepley     markerRight  = 2;
4491df21d24SMatthew G. Knepley     markerLeft   = 4;
450552f7358SJed Brown   }
4519566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
452dd400576SPatrick Sanan   if (rank == 0) {
453552f7358SJed Brown     PetscInt e, ex, ey;
454552f7358SJed Brown 
4559566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices));
45648a46eb9SPierre Jolivet     for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
4579566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
458552f7358SJed Brown     for (vx = 0; vx <= edges[0]; vx++) {
459552f7358SJed Brown       for (ey = 0; ey < edges[1]; ey++) {
460552f7358SJed Brown         PetscInt edge   = vx * edges[1] + ey + edges[0] * (edges[1] + 1);
461552f7358SJed Brown         PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges;
462da80777bSKarl Rupp         PetscInt cone[2];
463552f7358SJed Brown 
4649371c9d4SSatish Balay         cone[0] = vertex;
4659371c9d4SSatish Balay         cone[1] = vertex + edges[0] + 1;
4669566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
467552f7358SJed Brown         if (vx == edges[0]) {
4689566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
4699566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
470552f7358SJed Brown           if (ey == edges[1] - 1) {
4719566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
4729566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight));
473552f7358SJed Brown           }
474552f7358SJed Brown         } else if (vx == 0) {
4759566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
4769566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
477552f7358SJed Brown           if (ey == edges[1] - 1) {
4789566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
4799566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft));
480552f7358SJed Brown           }
481552f7358SJed Brown         }
482552f7358SJed Brown       }
483552f7358SJed Brown     }
484552f7358SJed Brown     for (vy = 0; vy <= edges[1]; vy++) {
485552f7358SJed Brown       for (ex = 0; ex < edges[0]; ex++) {
486552f7358SJed Brown         PetscInt edge   = vy * edges[0] + ex;
487552f7358SJed Brown         PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges;
488da80777bSKarl Rupp         PetscInt cone[2];
489552f7358SJed Brown 
4909371c9d4SSatish Balay         cone[0] = vertex;
4919371c9d4SSatish Balay         cone[1] = vertex + 1;
4929566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
493552f7358SJed Brown         if (vy == edges[1]) {
4949566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
4959566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
496552f7358SJed Brown           if (ex == edges[0] - 1) {
4979566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
4989566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop));
499552f7358SJed Brown           }
500552f7358SJed Brown         } else if (vy == 0) {
5019566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
5029566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
503552f7358SJed Brown           if (ex == edges[0] - 1) {
5049566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
5059566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom));
506552f7358SJed Brown           }
507552f7358SJed Brown         }
508552f7358SJed Brown       }
509552f7358SJed Brown     }
510552f7358SJed Brown   }
5119566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
5129566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
513552f7358SJed Brown   /* Build coordinates */
5149566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 2));
5159566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
5169566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
5179566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices));
5189566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2));
519552f7358SJed Brown   for (v = numEdges; v < numEdges + numVertices; ++v) {
5209566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 2));
5219566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2));
522552f7358SJed Brown   }
5239566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
5249566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
5259566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
5269566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
5279566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
5289566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 2));
5299566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
5309566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
531552f7358SJed Brown   for (vy = 0; vy <= edges[1]; ++vy) {
532552f7358SJed Brown     for (vx = 0; vx <= edges[0]; ++vx) {
533552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx;
534552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy;
535552f7358SJed Brown     }
536552f7358SJed Brown   }
5379566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
5389566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
5399566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
5403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
541552f7358SJed Brown }
542552f7358SJed Brown 
543d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[])
544d71ae5a4SJacob Faibussowitsch {
5459e8abbc3SMichael Lange   PetscInt     vertices[3], numVertices;
5467b59f5a9SMichael Lange   PetscInt     numFaces       = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2];
547c2df9bbfSMatthew G. Knepley   PetscInt     markerTop      = 1;
548c2df9bbfSMatthew G. Knepley   PetscInt     markerBottom   = 1;
549c2df9bbfSMatthew G. Knepley   PetscInt     markerFront    = 1;
550c2df9bbfSMatthew G. Knepley   PetscInt     markerBack     = 1;
551c2df9bbfSMatthew G. Knepley   PetscInt     markerRight    = 1;
552c2df9bbfSMatthew G. Knepley   PetscInt     markerLeft     = 1;
553c2df9bbfSMatthew G. Knepley   PetscBool    markerSeparate = PETSC_FALSE;
554552f7358SJed Brown   Vec          coordinates;
555552f7358SJed Brown   PetscSection coordSection;
556552f7358SJed Brown   PetscScalar *coords;
557552f7358SJed Brown   PetscInt     coordSize;
558552f7358SJed Brown   PetscMPIInt  rank;
559552f7358SJed Brown   PetscInt     v, vx, vy, vz;
5607b59f5a9SMichael Lange   PetscInt     voffset, iface = 0, cone[4];
561552f7358SJed Brown 
562552f7358SJed Brown   PetscFunctionBegin;
5631dca8a05SBarry 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");
5649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
565c2df9bbfSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
566c2df9bbfSMatthew G. Knepley   if (markerSeparate) {
567c2df9bbfSMatthew G. Knepley     markerBottom = 1;
568c2df9bbfSMatthew G. Knepley     markerTop    = 2;
569c2df9bbfSMatthew G. Knepley     markerFront  = 3;
570c2df9bbfSMatthew G. Knepley     markerBack   = 4;
571c2df9bbfSMatthew G. Knepley     markerRight  = 5;
572c2df9bbfSMatthew G. Knepley     markerLeft   = 6;
573c2df9bbfSMatthew G. Knepley   }
5749371c9d4SSatish Balay   vertices[0] = faces[0] + 1;
5759371c9d4SSatish Balay   vertices[1] = faces[1] + 1;
5769371c9d4SSatish Balay   vertices[2] = faces[2] + 1;
5779e8abbc3SMichael Lange   numVertices = vertices[0] * vertices[1] * vertices[2];
578dd400576SPatrick Sanan   if (rank == 0) {
579552f7358SJed Brown     PetscInt f;
580552f7358SJed Brown 
5819566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices));
58248a46eb9SPierre Jolivet     for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
5839566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
5847b59f5a9SMichael Lange 
5857b59f5a9SMichael Lange     /* Side 0 (Top) */
5867b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
5877b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
5887b59f5a9SMichael Lange         voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx;
5899371c9d4SSatish Balay         cone[0] = voffset;
5909371c9d4SSatish Balay         cone[1] = voffset + 1;
5919371c9d4SSatish Balay         cone[2] = voffset + vertices[0] + 1;
5929371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
5939566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
594c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop));
595c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop));
596c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop));
597c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop));
598c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop));
5997b59f5a9SMichael Lange         iface++;
600552f7358SJed Brown       }
601552f7358SJed Brown     }
6027b59f5a9SMichael Lange 
6037b59f5a9SMichael Lange     /* Side 1 (Bottom) */
6047b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
6057b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
6067b59f5a9SMichael Lange         voffset = numFaces + vy * (faces[0] + 1) + vx;
6079371c9d4SSatish Balay         cone[0] = voffset + 1;
6089371c9d4SSatish Balay         cone[1] = voffset;
6099371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
6109371c9d4SSatish Balay         cone[3] = voffset + vertices[0] + 1;
6119566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
612c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom));
613c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom));
614c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom));
615c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom));
616c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom));
6177b59f5a9SMichael Lange         iface++;
618552f7358SJed Brown       }
619552f7358SJed Brown     }
6207b59f5a9SMichael Lange 
6217b59f5a9SMichael Lange     /* Side 2 (Front) */
6227b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6237b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
6247b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vx;
6259371c9d4SSatish Balay         cone[0] = voffset;
6269371c9d4SSatish Balay         cone[1] = voffset + 1;
6279371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + 1;
6289371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1];
6299566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
630c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront));
631c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront));
632c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront));
633c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront));
634c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront));
6357b59f5a9SMichael Lange         iface++;
636552f7358SJed Brown       }
6377b59f5a9SMichael Lange     }
6387b59f5a9SMichael Lange 
6397b59f5a9SMichael Lange     /* Side 3 (Back) */
6407b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6417b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
6427b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx;
6439371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
6449371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1] + 1;
6459371c9d4SSatish Balay         cone[2] = voffset + 1;
6469371c9d4SSatish Balay         cone[3] = voffset;
6479566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
648c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack));
649c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack));
650c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack));
651c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack));
652c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack));
6537b59f5a9SMichael Lange         iface++;
6547b59f5a9SMichael Lange       }
6557b59f5a9SMichael Lange     }
6567b59f5a9SMichael Lange 
6577b59f5a9SMichael Lange     /* Side 4 (Left) */
6587b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6597b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
6607b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0];
6619371c9d4SSatish Balay         cone[0] = voffset;
6629371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1];
6639371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + vertices[0];
6649371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
6659566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
666c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft));
667c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft));
668c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft));
669c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft));
670c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft));
6717b59f5a9SMichael Lange         iface++;
6727b59f5a9SMichael Lange       }
6737b59f5a9SMichael Lange     }
6747b59f5a9SMichael Lange 
6757b59f5a9SMichael Lange     /* Side 5 (Right) */
6767b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
6777b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
678aab5bcd8SJed Brown         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0];
6799371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
6809371c9d4SSatish Balay         cone[1] = voffset;
6819371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
6829371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1] + vertices[0];
6839566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
684c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight));
685c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight));
686c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight));
687c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight));
688c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight));
6897b59f5a9SMichael Lange         iface++;
6907b59f5a9SMichael Lange       }
691552f7358SJed Brown     }
692552f7358SJed Brown   }
6939566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
6949566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
695552f7358SJed Brown   /* Build coordinates */
6969566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 3));
6979566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
6989566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
6999566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices));
7009566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3));
701552f7358SJed Brown   for (v = numFaces; v < numFaces + numVertices; ++v) {
7029566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 3));
7039566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3));
704552f7358SJed Brown   }
7059566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
7069566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
7079566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
7089566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
7099566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
7109566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 3));
7119566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
7129566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
713552f7358SJed Brown   for (vz = 0; vz <= faces[2]; ++vz) {
714552f7358SJed Brown     for (vy = 0; vy <= faces[1]; ++vy) {
715552f7358SJed Brown       for (vx = 0; vx <= faces[0]; ++vx) {
716552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx;
717552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy;
718552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz;
719552f7358SJed Brown       }
720552f7358SJed Brown     }
721552f7358SJed Brown   }
7229566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
7239566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
7249566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
7253ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
726552f7358SJed Brown }
727552f7358SJed Brown 
728d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate)
729d71ae5a4SJacob Faibussowitsch {
7309318fe57SMatthew G. Knepley   PetscFunctionBegin;
7319318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
73246139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
7339566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim - 1));
7349566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim));
7359318fe57SMatthew G. Knepley   switch (dim) {
736d71ae5a4SJacob Faibussowitsch   case 1:
737d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces));
738d71ae5a4SJacob Faibussowitsch     break;
739d71ae5a4SJacob Faibussowitsch   case 2:
740d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces));
741d71ae5a4SJacob Faibussowitsch     break;
742d71ae5a4SJacob Faibussowitsch   case 3:
743d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces));
744d71ae5a4SJacob Faibussowitsch     break;
745d71ae5a4SJacob Faibussowitsch   default:
746d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim);
7479318fe57SMatthew G. Knepley   }
74846139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
7499566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
7503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7519318fe57SMatthew G. Knepley }
7529318fe57SMatthew G. Knepley 
7539318fe57SMatthew G. Knepley /*@C
7549318fe57SMatthew G. Knepley   DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra).
7559318fe57SMatthew G. Knepley 
7569318fe57SMatthew G. Knepley   Collective
7579318fe57SMatthew G. Knepley 
7589318fe57SMatthew G. Knepley   Input Parameters:
759a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
76020f4b53cSBarry Smith . dim         - The spatial dimension of the box, so the resulting mesh is has dimension `dim`-1
76120f4b53cSBarry Smith . faces       - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
76220f4b53cSBarry Smith . lower       - The lower left corner, or `NULL` for (0, 0, 0)
76320f4b53cSBarry Smith . upper       - The upper right corner, or `NULL` for (1, 1, 1)
7649318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
7659318fe57SMatthew G. Knepley 
7669318fe57SMatthew G. Knepley   Output Parameter:
767a1cb98faSBarry Smith . dm - The `DM` object
7689318fe57SMatthew G. Knepley 
7699318fe57SMatthew G. Knepley   Level: beginner
7709318fe57SMatthew G. Knepley 
7711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()`
7729318fe57SMatthew G. Knepley @*/
773d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm)
774d71ae5a4SJacob Faibussowitsch {
7759318fe57SMatthew G. Knepley   PetscInt  fac[3] = {1, 1, 1};
7769318fe57SMatthew G. Knepley   PetscReal low[3] = {0, 0, 0};
7779318fe57SMatthew G. Knepley   PetscReal upp[3] = {1, 1, 1};
7789318fe57SMatthew G. Knepley 
7799318fe57SMatthew G. Knepley   PetscFunctionBegin;
7809566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
7819566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
7829566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate));
7833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7849318fe57SMatthew G. Knepley }
7859318fe57SMatthew G. Knepley 
786d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd)
787d71ae5a4SJacob Faibussowitsch {
788fdbf62faSLisandro Dalcin   PetscInt     i, fStart, fEnd, numCells = 0, numVerts = 0;
789fdbf62faSLisandro Dalcin   PetscInt     numPoints[2], *coneSize, *cones, *coneOrientations;
790fdbf62faSLisandro Dalcin   PetscScalar *vertexCoords;
791fdbf62faSLisandro Dalcin   PetscReal    L, maxCell;
792fdbf62faSLisandro Dalcin   PetscBool    markerSeparate = PETSC_FALSE;
793fdbf62faSLisandro Dalcin   PetscInt     markerLeft = 1, faceMarkerLeft = 1;
794fdbf62faSLisandro Dalcin   PetscInt     markerRight = 1, faceMarkerRight = 2;
795fdbf62faSLisandro Dalcin   PetscBool    wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE;
796fdbf62faSLisandro Dalcin   PetscMPIInt  rank;
797fdbf62faSLisandro Dalcin 
798fdbf62faSLisandro Dalcin   PetscFunctionBegin;
7994f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
800fdbf62faSLisandro Dalcin 
8019566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, 1));
8029566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
8039566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
804fdbf62faSLisandro Dalcin 
8059566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
806dd400576SPatrick Sanan   if (rank == 0) numCells = segments;
807dd400576SPatrick Sanan   if (rank == 0) numVerts = segments + (wrap ? 0 : 1);
808fdbf62faSLisandro Dalcin 
8099371c9d4SSatish Balay   numPoints[0] = numVerts;
8109371c9d4SSatish Balay   numPoints[1] = numCells;
8119566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords));
8129566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts));
813ad540459SPierre Jolivet   for (i = 0; i < numCells; ++i) coneSize[i] = 2;
814ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0;
8159371c9d4SSatish Balay   for (i = 0; i < numCells; ++i) {
8169371c9d4SSatish Balay     cones[2 * i]     = numCells + i % numVerts;
8179371c9d4SSatish Balay     cones[2 * i + 1] = numCells + (i + 1) % numVerts;
8189371c9d4SSatish Balay   }
819ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells);
8209566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
8219566063dSJacob Faibussowitsch   PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords));
822fdbf62faSLisandro Dalcin 
8239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
8249371c9d4SSatish Balay   if (markerSeparate) {
8259371c9d4SSatish Balay     markerLeft  = faceMarkerLeft;
8269371c9d4SSatish Balay     markerRight = faceMarkerRight;
8279371c9d4SSatish Balay   }
828dd400576SPatrick Sanan   if (!wrap && rank == 0) {
8299566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
8309566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft));
8319566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight));
8329566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft));
8339566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight));
834fdbf62faSLisandro Dalcin   }
835fdbf62faSLisandro Dalcin   if (wrap) {
836fdbf62faSLisandro Dalcin     L       = upper - lower;
837fdbf62faSLisandro Dalcin     maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments));
8384fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L));
839fdbf62faSLisandro Dalcin   }
8409566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
8413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
842fdbf62faSLisandro Dalcin }
843fdbf62faSLisandro Dalcin 
8444054ae39SJames Wright // Creates "Face Sets" label based on the standard box labeling conventions
8454054ae39SJames Wright static PetscErrorCode DMPlexSetBoxLabel_Internal(DM dm)
8464054ae39SJames Wright {
8476ff49feeSJames Wright   DM              cdm;
8486ff49feeSJames Wright   PetscSection    csection;
8496ff49feeSJames Wright   Vec             coordinates;
8504054ae39SJames Wright   DMLabel         label;
8516ff49feeSJames Wright   IS              faces_is;
8524054ae39SJames Wright   PetscInt        dim, num_face;
8534054ae39SJames Wright   const PetscInt *faces;
8544054ae39SJames Wright   PetscInt        faceMarkerBottom, faceMarkerTop, faceMarkerFront, faceMarkerBack, faceMarkerRight, faceMarkerLeft;
8554054ae39SJames Wright 
8564054ae39SJames Wright   PetscFunctionBeginUser;
8574054ae39SJames Wright   PetscCall(DMGetDimension(dm, &dim));
858d7c1f440SPierre Jolivet   PetscCheck((dim == 2) || (dim == 3), PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DMPlex box labeling only supports 2D and 3D meshes, received DM of dimension %" PetscInt_FMT, dim);
8594054ae39SJames Wright   // Get Face Sets label
8604054ae39SJames Wright   PetscCall(DMGetLabel(dm, "Face Sets", &label));
8614054ae39SJames Wright   if (label) {
8624054ae39SJames Wright     PetscCall(DMLabelReset(label));
8634054ae39SJames Wright   } else {
8644054ae39SJames Wright     PetscCall(DMCreateLabel(dm, "Face Sets"));
8654054ae39SJames Wright     PetscCall(DMGetLabel(dm, "Face Sets", &label));
8664054ae39SJames Wright   }
8674054ae39SJames Wright   PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label));
8686ff49feeSJames Wright   PetscCall(DMGetStratumIS(dm, "Face Sets", 1, &faces_is));
8696ff49feeSJames Wright   if (!faces_is) PetscFunctionReturn(PETSC_SUCCESS); // No faces on rank
8704054ae39SJames Wright 
8714054ae39SJames Wright   switch (dim) {
8724054ae39SJames Wright   case 2:
8734054ae39SJames Wright     faceMarkerTop    = 3;
8744054ae39SJames Wright     faceMarkerBottom = 1;
8754054ae39SJames Wright     faceMarkerRight  = 2;
8764054ae39SJames Wright     faceMarkerLeft   = 4;
8774054ae39SJames Wright     break;
8784054ae39SJames Wright   case 3:
8794054ae39SJames Wright     faceMarkerBottom = 1;
8804054ae39SJames Wright     faceMarkerTop    = 2;
8814054ae39SJames Wright     faceMarkerFront  = 3;
8824054ae39SJames Wright     faceMarkerBack   = 4;
8834054ae39SJames Wright     faceMarkerRight  = 5;
8844054ae39SJames Wright     faceMarkerLeft   = 6;
8854054ae39SJames Wright     break;
8864054ae39SJames Wright   default:
8874054ae39SJames Wright     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
8884054ae39SJames Wright   }
8894054ae39SJames Wright 
8906ff49feeSJames Wright   PetscCall(ISGetLocalSize(faces_is, &num_face));
8916ff49feeSJames Wright   PetscCall(ISGetIndices(faces_is, &faces));
8926ff49feeSJames Wright   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
8936ff49feeSJames Wright   PetscCall(DMGetCoordinateDM(dm, &cdm));
8946ff49feeSJames Wright   PetscCall(DMGetLocalSection(cdm, &csection));
8954054ae39SJames Wright   for (PetscInt f = 0; f < num_face; ++f) {
8966ff49feeSJames Wright     PetscScalar *coords = NULL;
8976ff49feeSJames Wright     PetscInt     face = faces[f], flip = 1, label_value = -1, coords_size;
8984054ae39SJames Wright 
8994054ae39SJames Wright     { // Determine if orientation of face is flipped
9004054ae39SJames Wright       PetscInt        num_cells_support, num_faces, start = -1;
9014054ae39SJames Wright       const PetscInt *orients, *cell_faces, *cells;
9024054ae39SJames Wright 
9034054ae39SJames Wright       PetscCall(DMPlexGetSupport(dm, face, &cells));
9044054ae39SJames Wright       PetscCall(DMPlexGetSupportSize(dm, face, &num_cells_support));
9054054ae39SJames Wright       PetscCheck(num_cells_support == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Expected one cell in support of exterior face, but got %" PetscInt_FMT " cells", num_cells_support);
9064054ae39SJames Wright       PetscCall(DMPlexGetCone(dm, cells[0], &cell_faces));
9074054ae39SJames Wright       PetscCall(DMPlexGetConeSize(dm, cells[0], &num_faces));
9084054ae39SJames Wright       for (PetscInt i = 0; i < num_faces; i++) {
9094054ae39SJames Wright         if (cell_faces[i] == face) start = i;
9104054ae39SJames Wright       }
9114054ae39SJames Wright       PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Could not find face %" PetscInt_FMT " in cone of its support", face);
9124054ae39SJames Wright       PetscCall(DMPlexGetConeOrientation(dm, cells[0], &orients));
9134054ae39SJames Wright       if (orients[start] < 0) flip = -1;
9144054ae39SJames Wright     }
9154054ae39SJames Wright 
9166ff49feeSJames Wright     // Cannot use DMPlexComputeCellGeometryFVM() for high-order geometry, so must calculate normal vectors manually
9176ff49feeSJames Wright     // Use the vertices (depth 0) of coordinate DM to calculate normal vector
9186ff49feeSJames Wright     PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords));
9194054ae39SJames Wright     switch (dim) {
9204054ae39SJames Wright     case 2: {
9216ff49feeSJames Wright       PetscScalar vec[2];
9226ff49feeSJames Wright 
9236ff49feeSJames Wright       for (PetscInt d = 0; d < dim; ++d) vec[d] = flip * (PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]));
9246ff49feeSJames Wright       PetscScalar normal[] = {vec[1], -vec[0]};
9256ff49feeSJames Wright       if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) {
9266ff49feeSJames Wright         label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft;
9274054ae39SJames Wright       } else {
9286ff49feeSJames Wright         label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerTop : faceMarkerBottom;
9294054ae39SJames Wright       }
9304054ae39SJames Wright     } break;
9314054ae39SJames Wright     case 3: {
9326ff49feeSJames Wright       PetscScalar vec1[3], vec2[3], normal[3];
9336ff49feeSJames Wright 
9346ff49feeSJames Wright       for (PetscInt d = 0; d < dim; ++d) {
9356ff49feeSJames Wright         vec1[d] = PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]);
9366ff49feeSJames Wright         vec2[d] = PetscRealPart(coords[2 * dim + d]) - PetscRealPart(coords[1 * dim + d]);
9376ff49feeSJames Wright       }
9386ff49feeSJames Wright 
9396ff49feeSJames Wright       // Calculate normal vector via cross-product
9406ff49feeSJames Wright       normal[0] = flip * ((vec1[1] * vec2[2]) - (vec1[2] * vec2[1]));
9416ff49feeSJames Wright       normal[1] = flip * ((vec1[2] * vec2[0]) - (vec1[0] * vec2[2]));
9426ff49feeSJames Wright       normal[2] = flip * ((vec1[0] * vec2[1]) - (vec1[1] * vec2[0]));
9436ff49feeSJames Wright 
9446ff49feeSJames Wright       if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) {
9456ff49feeSJames Wright         if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[2])) {
9466ff49feeSJames Wright           label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft;
9474054ae39SJames Wright         } else {
9486ff49feeSJames Wright           label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom;
9494054ae39SJames Wright         }
9504054ae39SJames Wright       } else {
9516ff49feeSJames Wright         if (PetscAbsScalar(normal[1]) > PetscAbsScalar(normal[2])) {
9526ff49feeSJames Wright           label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerBack : faceMarkerFront;
9534054ae39SJames Wright         } else {
9546ff49feeSJames Wright           label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom;
9554054ae39SJames Wright         }
9564054ae39SJames Wright       }
9574054ae39SJames Wright     } break;
9584054ae39SJames Wright     }
9594054ae39SJames Wright 
9604054ae39SJames Wright     PetscInt previous_label_value; // always 1 due to DMPlexMarkBoundaryFaces call above
9614054ae39SJames Wright     PetscCall(DMGetLabelValue(dm, "Face Sets", face, &previous_label_value));
9624054ae39SJames Wright     PetscCall(DMClearLabelValue(dm, "Face Sets", face, previous_label_value));
9634054ae39SJames Wright     PetscCall(DMSetLabelValue(dm, "Face Sets", face, label_value));
9646ff49feeSJames Wright     PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords));
9654054ae39SJames Wright   }
9666ff49feeSJames Wright   PetscCall(ISRestoreIndices(faces_is, &faces));
9676ff49feeSJames Wright   PetscCall(ISDestroy(&faces_is));
9684054ae39SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
9694054ae39SJames Wright }
9704054ae39SJames Wright 
971d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
972d71ae5a4SJacob Faibussowitsch {
9739318fe57SMatthew G. Knepley   DM      boundary, vol;
974c22d3578SMatthew G. Knepley   DMLabel bdlabel;
975d6218766SMatthew G. Knepley 
976d6218766SMatthew G. Knepley   PetscFunctionBegin;
9774f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
978c22d3578SMatthew 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");
9799566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary));
9809566063dSJacob Faibussowitsch   PetscCall(DMSetType(boundary, DMPLEX));
9819566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE));
9829566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol));
983c22d3578SMatthew G. Knepley   PetscCall(DMGetLabel(vol, "marker", &bdlabel));
984c22d3578SMatthew G. Knepley   if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel));
9855de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol));
98669d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
9874054ae39SJames Wright   if (interpolate) {
9884054ae39SJames Wright     PetscCall(DMPlexInterpolateInPlace_Internal(dm));
9894054ae39SJames Wright     PetscCall(DMPlexSetBoxLabel_Internal(dm));
9904054ae39SJames Wright   }
9919566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&boundary));
9923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
993d6218766SMatthew G. Knepley }
994d6218766SMatthew G. Knepley 
995d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ)
996d71ae5a4SJacob Faibussowitsch {
997ed0e4b50SMatthew G. Knepley   DMLabel     cutLabel  = NULL;
998f4eb4c5dSMatthew G. Knepley   PetscInt    markerTop = 1, faceMarkerTop = 1;
999f4eb4c5dSMatthew G. Knepley   PetscInt    markerBottom = 1, faceMarkerBottom = 1;
1000f4eb4c5dSMatthew G. Knepley   PetscInt    markerFront = 1, faceMarkerFront = 1;
1001f4eb4c5dSMatthew G. Knepley   PetscInt    markerBack = 1, faceMarkerBack = 1;
1002f4eb4c5dSMatthew G. Knepley   PetscInt    markerRight = 1, faceMarkerRight = 1;
1003f4eb4c5dSMatthew G. Knepley   PetscInt    markerLeft = 1, faceMarkerLeft = 1;
10043dfda0b1SToby Isaac   PetscInt    dim;
1005d8211ee3SMatthew G. Knepley   PetscBool   markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE;
10063dfda0b1SToby Isaac   PetscMPIInt rank;
10073dfda0b1SToby Isaac 
10083dfda0b1SToby Isaac   PetscFunctionBegin;
10099566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
10109566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
10119566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
10129566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
10139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
10149371c9d4SSatish 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) {
10159371c9d4SSatish Balay     if (cutMarker) {
10169371c9d4SSatish Balay       PetscCall(DMCreateLabel(dm, "periodic_cut"));
10179371c9d4SSatish Balay       PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
10189371c9d4SSatish Balay     }
1019d8211ee3SMatthew G. Knepley   }
10203dfda0b1SToby Isaac   switch (dim) {
10213dfda0b1SToby Isaac   case 2:
1022f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 3;
1023f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
1024f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 2;
1025f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 4;
10263dfda0b1SToby Isaac     break;
10273dfda0b1SToby Isaac   case 3:
1028f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
1029f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 2;
1030f4eb4c5dSMatthew G. Knepley     faceMarkerFront  = 3;
1031f4eb4c5dSMatthew G. Knepley     faceMarkerBack   = 4;
1032f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 5;
1033f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 6;
10343dfda0b1SToby Isaac     break;
1035d71ae5a4SJacob Faibussowitsch   default:
1036d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
10373dfda0b1SToby Isaac   }
10389566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
1039f4eb4c5dSMatthew G. Knepley   if (markerSeparate) {
1040f4eb4c5dSMatthew G. Knepley     markerBottom = faceMarkerBottom;
1041f4eb4c5dSMatthew G. Knepley     markerTop    = faceMarkerTop;
1042f4eb4c5dSMatthew G. Knepley     markerFront  = faceMarkerFront;
1043f4eb4c5dSMatthew G. Knepley     markerBack   = faceMarkerBack;
1044f4eb4c5dSMatthew G. Knepley     markerRight  = faceMarkerRight;
1045f4eb4c5dSMatthew G. Knepley     markerLeft   = faceMarkerLeft;
10463dfda0b1SToby Isaac   }
10473dfda0b1SToby Isaac   {
1048dd400576SPatrick Sanan     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
1049dd400576SPatrick Sanan     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
1050dd400576SPatrick Sanan     const PetscInt numZEdges    = rank == 0 ? edges[2] : 0;
1051dd400576SPatrick Sanan     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0;
1052dd400576SPatrick Sanan     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0;
1053dd400576SPatrick Sanan     const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0;
10543dfda0b1SToby Isaac     const PetscInt numCells     = numXEdges * numYEdges * numZEdges;
10553dfda0b1SToby Isaac     const PetscInt numXFaces    = numYEdges * numZEdges;
10563dfda0b1SToby Isaac     const PetscInt numYFaces    = numXEdges * numZEdges;
10573dfda0b1SToby Isaac     const PetscInt numZFaces    = numXEdges * numYEdges;
10583dfda0b1SToby Isaac     const PetscInt numTotXFaces = numXVertices * numXFaces;
10593dfda0b1SToby Isaac     const PetscInt numTotYFaces = numYVertices * numYFaces;
10603dfda0b1SToby Isaac     const PetscInt numTotZFaces = numZVertices * numZFaces;
10613dfda0b1SToby Isaac     const PetscInt numFaces     = numTotXFaces + numTotYFaces + numTotZFaces;
10623dfda0b1SToby Isaac     const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices;
10633dfda0b1SToby Isaac     const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices;
10643dfda0b1SToby Isaac     const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices;
10653dfda0b1SToby Isaac     const PetscInt numVertices  = numXVertices * numYVertices * numZVertices;
10663dfda0b1SToby Isaac     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numTotZEdges;
10673dfda0b1SToby Isaac     const PetscInt firstVertex  = (dim == 2) ? numFaces : numCells;
10683dfda0b1SToby Isaac     const PetscInt firstXFace   = (dim == 2) ? 0 : numCells + numVertices;
10693dfda0b1SToby Isaac     const PetscInt firstYFace   = firstXFace + numTotXFaces;
10703dfda0b1SToby Isaac     const PetscInt firstZFace   = firstYFace + numTotYFaces;
10713dfda0b1SToby Isaac     const PetscInt firstXEdge   = numCells + numFaces + numVertices;
10723dfda0b1SToby Isaac     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
10733dfda0b1SToby Isaac     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
10743dfda0b1SToby Isaac     Vec            coordinates;
10753dfda0b1SToby Isaac     PetscSection   coordSection;
10763dfda0b1SToby Isaac     PetscScalar   *coords;
10773dfda0b1SToby Isaac     PetscInt       coordSize;
10783dfda0b1SToby Isaac     PetscInt       v, vx, vy, vz;
10793dfda0b1SToby Isaac     PetscInt       c, f, fx, fy, fz, e, ex, ey, ez;
10803dfda0b1SToby Isaac 
10819566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices));
108248a46eb9SPierre Jolivet     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
108348a46eb9SPierre Jolivet     for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
108448a46eb9SPierre Jolivet     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
10859566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
10863dfda0b1SToby Isaac     /* Build cells */
10873dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
10883dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
10893dfda0b1SToby Isaac         for (fx = 0; fx < numXEdges; ++fx) {
10903dfda0b1SToby Isaac           PetscInt cell  = (fz * numYEdges + fy) * numXEdges + fx;
10913dfda0b1SToby Isaac           PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
10923dfda0b1SToby Isaac           PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices);
10933dfda0b1SToby Isaac           PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
10943dfda0b1SToby Isaac           PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices);
10953dfda0b1SToby Isaac           PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
10963dfda0b1SToby Isaac           PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices);
10973dfda0b1SToby Isaac           /* B,  T,  F,  K,  R,  L */
1098b5a892a1SMatthew G. Knepley           PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */
109942206facSLisandro Dalcin           PetscInt cone[6];
11003dfda0b1SToby Isaac 
11013dfda0b1SToby Isaac           /* no boundary twisting in 3D */
11029371c9d4SSatish Balay           cone[0] = faceB;
11039371c9d4SSatish Balay           cone[1] = faceT;
11049371c9d4SSatish Balay           cone[2] = faceF;
11059371c9d4SSatish Balay           cone[3] = faceK;
11069371c9d4SSatish Balay           cone[4] = faceR;
11079371c9d4SSatish Balay           cone[5] = faceL;
11089566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, cell, cone));
11099566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, cell, ornt));
11109566063dSJacob Faibussowitsch           if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
11119566063dSJacob Faibussowitsch           if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
11129566063dSJacob Faibussowitsch           if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
11133dfda0b1SToby Isaac         }
11143dfda0b1SToby Isaac       }
11153dfda0b1SToby Isaac     }
11163dfda0b1SToby Isaac     /* Build x faces */
11173dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
11183dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
11193dfda0b1SToby Isaac         for (fx = 0; fx < numXVertices; ++fx) {
11203dfda0b1SToby Isaac           PetscInt face    = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
11213dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
11223dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz;
11233dfda0b1SToby Isaac           PetscInt edgeB   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
11243dfda0b1SToby Isaac           PetscInt edgeT   = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy;
1125b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
11263dfda0b1SToby Isaac           PetscInt cone[4];
11273dfda0b1SToby Isaac 
11283dfda0b1SToby Isaac           if (dim == 3) {
11293dfda0b1SToby Isaac             /* markers */
11303dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
11313dfda0b1SToby Isaac               if (fx == numXVertices - 1) {
11329566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight));
11339566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerRight));
11349371c9d4SSatish Balay               } else if (fx == 0) {
11359566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft));
11369566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft));
11373dfda0b1SToby Isaac               }
11383dfda0b1SToby Isaac             }
11393dfda0b1SToby Isaac           }
11409371c9d4SSatish Balay           cone[0] = edgeB;
11419371c9d4SSatish Balay           cone[1] = edgeR;
11429371c9d4SSatish Balay           cone[2] = edgeT;
11439371c9d4SSatish Balay           cone[3] = edgeL;
11449566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
11459566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
11463dfda0b1SToby Isaac         }
11473dfda0b1SToby Isaac       }
11483dfda0b1SToby Isaac     }
11493dfda0b1SToby Isaac     /* Build y faces */
11503dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
115142206facSLisandro Dalcin       for (fx = 0; fx < numXEdges; ++fx) {
11523dfda0b1SToby Isaac         for (fy = 0; fy < numYVertices; ++fy) {
11533dfda0b1SToby Isaac           PetscInt face    = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
11543dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
11553dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz;
11563dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
11573dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx;
1158b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
11593dfda0b1SToby Isaac           PetscInt cone[4];
11603dfda0b1SToby Isaac 
11613dfda0b1SToby Isaac           if (dim == 3) {
11623dfda0b1SToby Isaac             /* markers */
11633dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
11643dfda0b1SToby Isaac               if (fy == numYVertices - 1) {
11659566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack));
11669566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBack));
11679371c9d4SSatish Balay               } else if (fy == 0) {
11689566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront));
11699566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerFront));
11703dfda0b1SToby Isaac               }
11713dfda0b1SToby Isaac             }
11723dfda0b1SToby Isaac           }
11739371c9d4SSatish Balay           cone[0] = edgeB;
11749371c9d4SSatish Balay           cone[1] = edgeR;
11759371c9d4SSatish Balay           cone[2] = edgeT;
11769371c9d4SSatish Balay           cone[3] = edgeL;
11779566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
11789566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
11793dfda0b1SToby Isaac         }
11803dfda0b1SToby Isaac       }
11813dfda0b1SToby Isaac     }
11823dfda0b1SToby Isaac     /* Build z faces */
11833dfda0b1SToby Isaac     for (fy = 0; fy < numYEdges; ++fy) {
11843dfda0b1SToby Isaac       for (fx = 0; fx < numXEdges; ++fx) {
11853dfda0b1SToby Isaac         for (fz = 0; fz < numZVertices; fz++) {
11863dfda0b1SToby Isaac           PetscInt face    = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
11873dfda0b1SToby Isaac           PetscInt edgeL   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
11883dfda0b1SToby Isaac           PetscInt edgeR   = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy;
11893dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
11903dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx;
1191b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
11923dfda0b1SToby Isaac           PetscInt cone[4];
11933dfda0b1SToby Isaac 
11943dfda0b1SToby Isaac           if (dim == 2) {
11959371c9d4SSatish Balay             if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) {
11969371c9d4SSatish Balay               edgeR += numYEdges - 1 - 2 * fy;
11979371c9d4SSatish Balay               ornt[1] = -1;
11989371c9d4SSatish Balay             }
11999371c9d4SSatish Balay             if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) {
12009371c9d4SSatish Balay               edgeT += numXEdges - 1 - 2 * fx;
12019371c9d4SSatish Balay               ornt[2] = 0;
12029371c9d4SSatish Balay             }
12039566063dSJacob Faibussowitsch             if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
12049566063dSJacob Faibussowitsch             if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
1205d1c88043SMatthew G. Knepley           } else {
12063dfda0b1SToby Isaac             /* markers */
12073dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
12083dfda0b1SToby Isaac               if (fz == numZVertices - 1) {
12099566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop));
12109566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerTop));
12119371c9d4SSatish Balay               } else if (fz == 0) {
12129566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom));
12139566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom));
12143dfda0b1SToby Isaac               }
12153dfda0b1SToby Isaac             }
12163dfda0b1SToby Isaac           }
12179371c9d4SSatish Balay           cone[0] = edgeB;
12189371c9d4SSatish Balay           cone[1] = edgeR;
12199371c9d4SSatish Balay           cone[2] = edgeT;
12209371c9d4SSatish Balay           cone[3] = edgeL;
12219566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
12229566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
12233dfda0b1SToby Isaac         }
12243dfda0b1SToby Isaac       }
12253dfda0b1SToby Isaac     }
12263dfda0b1SToby Isaac     /* Build Z edges*/
12273dfda0b1SToby Isaac     for (vy = 0; vy < numYVertices; vy++) {
12283dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
12293dfda0b1SToby Isaac         for (ez = 0; ez < numZEdges; ez++) {
12303dfda0b1SToby Isaac           const PetscInt edge    = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez;
12313dfda0b1SToby Isaac           const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx;
12323dfda0b1SToby Isaac           const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx;
12333dfda0b1SToby Isaac           PetscInt       cone[2];
12343dfda0b1SToby Isaac 
12359371c9d4SSatish Balay           cone[0] = vertexB;
12369371c9d4SSatish Balay           cone[1] = vertexT;
1237c2df9bbfSMatthew G. Knepley           PetscCall(DMPlexSetCone(dm, edge, cone));
12383dfda0b1SToby Isaac           if (dim == 3) {
12393dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
12403dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
12419566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1242c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1243c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1244c2df9bbfSMatthew G. Knepley               } else if (vx == 0) {
12459566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1246c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1247c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
12483dfda0b1SToby Isaac               }
12493dfda0b1SToby Isaac             }
12503dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
12513dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
12529566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1253c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1254c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1255c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
12569566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1257c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1258c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
12593dfda0b1SToby Isaac               }
12603dfda0b1SToby Isaac             }
12613dfda0b1SToby Isaac           }
12623dfda0b1SToby Isaac         }
12633dfda0b1SToby Isaac       }
12643dfda0b1SToby Isaac     }
12653dfda0b1SToby Isaac     /* Build Y edges*/
12663dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
12673dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
12683dfda0b1SToby Isaac         for (ey = 0; ey < numYEdges; ey++) {
12693dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx;
12703dfda0b1SToby Isaac           const PetscInt edge    = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey;
12713dfda0b1SToby Isaac           const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx;
12723dfda0b1SToby Isaac           const PetscInt vertexK = firstVertex + nextv;
12733dfda0b1SToby Isaac           PetscInt       cone[2];
12743dfda0b1SToby Isaac 
12759371c9d4SSatish Balay           cone[0] = vertexF;
12769371c9d4SSatish Balay           cone[1] = vertexK;
12779566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
12783dfda0b1SToby Isaac           if (dim == 2) {
12793dfda0b1SToby Isaac             if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
12803dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
12819566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
12829566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
12839566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1284c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1285d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
12869566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
12879566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
12889566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1289c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
12903dfda0b1SToby Isaac               }
1291d8211ee3SMatthew G. Knepley             } else {
12924c67ea77SStefano Zampini               if (vx == 0 && cutLabel) {
12939566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
12949566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1295c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
12963dfda0b1SToby Isaac               }
1297d8211ee3SMatthew G. Knepley             }
1298d8211ee3SMatthew G. Knepley           } else {
12993dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
13003dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
13019566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1302c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1303c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1304d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
13059566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1306c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1307c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
13083dfda0b1SToby Isaac               }
13093dfda0b1SToby Isaac             }
13103dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
13113dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
13129566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1313c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1314c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1315d8211ee3SMatthew G. Knepley               } else if (vz == 0) {
13169566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1317c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1318c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
13193dfda0b1SToby Isaac               }
13203dfda0b1SToby Isaac             }
13213dfda0b1SToby Isaac           }
13223dfda0b1SToby Isaac         }
13233dfda0b1SToby Isaac       }
13243dfda0b1SToby Isaac     }
13253dfda0b1SToby Isaac     /* Build X edges*/
13263dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
13273dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; vy++) {
13283dfda0b1SToby Isaac         for (ex = 0; ex < numXEdges; ex++) {
13293dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices;
13303dfda0b1SToby Isaac           const PetscInt edge    = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex;
13313dfda0b1SToby Isaac           const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex;
13323dfda0b1SToby Isaac           const PetscInt vertexR = firstVertex + nextv;
13333dfda0b1SToby Isaac           PetscInt       cone[2];
13343dfda0b1SToby Isaac 
13359371c9d4SSatish Balay           cone[0] = vertexL;
13369371c9d4SSatish Balay           cone[1] = vertexR;
13379566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
13383dfda0b1SToby Isaac           if (dim == 2) {
13393dfda0b1SToby Isaac             if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
13403dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
13419566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
13429566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
13439566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1344c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1345d8211ee3SMatthew G. Knepley               } else if (vy == 0) {
13469566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
13479566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
13489566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1349c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
13503dfda0b1SToby Isaac               }
1351d8211ee3SMatthew G. Knepley             } else {
13524c67ea77SStefano Zampini               if (vy == 0 && cutLabel) {
13539566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
13549566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1355c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
13563dfda0b1SToby Isaac               }
1357d8211ee3SMatthew G. Knepley             }
1358d8211ee3SMatthew G. Knepley           } else {
13593dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
13603dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
13619566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1362c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1363c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1364c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
13659566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1366c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1367c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
13683dfda0b1SToby Isaac               }
13693dfda0b1SToby Isaac             }
13703dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
13713dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
13729566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1373c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1374c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1375c2df9bbfSMatthew G. Knepley               } else if (vz == 0) {
13769566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1377c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1378c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
13793dfda0b1SToby Isaac               }
13803dfda0b1SToby Isaac             }
13813dfda0b1SToby Isaac           }
13823dfda0b1SToby Isaac         }
13833dfda0b1SToby Isaac       }
13843dfda0b1SToby Isaac     }
13859566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
13869566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
13873dfda0b1SToby Isaac     /* Build coordinates */
13889566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
13899566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
13909566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
13919566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
13923dfda0b1SToby Isaac     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
13939566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
13949566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
13953dfda0b1SToby Isaac     }
13969566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
13979566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
13989566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
13999566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
14009566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
14019566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
14029566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
14039566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
14043dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; ++vz) {
14053dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; ++vy) {
14063dfda0b1SToby Isaac         for (vx = 0; vx < numXVertices; ++vx) {
14073dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
14083dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
1409ad540459SPierre Jolivet           if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz;
14103dfda0b1SToby Isaac         }
14113dfda0b1SToby Isaac       }
14123dfda0b1SToby Isaac     }
14139566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
14149566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
14159566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
14163dfda0b1SToby Isaac   }
14173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14183dfda0b1SToby Isaac }
14193dfda0b1SToby Isaac 
1420d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1421d71ae5a4SJacob Faibussowitsch {
14229318fe57SMatthew G. Knepley   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
14239318fe57SMatthew G. Knepley   PetscInt       fac[3] = {0, 0, 0}, d;
1424552f7358SJed Brown 
1425552f7358SJed Brown   PetscFunctionBegin;
14264f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
14279318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
14289566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
14299371c9d4SSatish Balay   for (d = 0; d < dim; ++d) {
14309371c9d4SSatish Balay     fac[d] = faces[d];
14319371c9d4SSatish Balay     bdt[d] = periodicity[d];
14329371c9d4SSatish Balay   }
14339566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2]));
14349371c9d4SSatish 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))) {
14356858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
14366858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1437552f7358SJed Brown 
14389318fe57SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
14396858538eSMatthew G. Knepley       if (periodicity[d] != DM_BOUNDARY_NONE) {
14409318fe57SMatthew G. Knepley         L[d]       = upper[d] - lower[d];
14419318fe57SMatthew G. Knepley         maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d]));
1442768d5fceSMatthew G. Knepley       }
14436858538eSMatthew G. Knepley     }
14444fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1445768d5fceSMatthew G. Knepley   }
14469566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
14473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
14489318fe57SMatthew G. Knepley }
14499318fe57SMatthew G. Knepley 
14505dca41c3SJed Brown static PetscErrorCode DMPlexCreateBoxMesh_Internal(DM dm, DMPlexShape shape, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
1451d71ae5a4SJacob Faibussowitsch {
14529318fe57SMatthew G. Knepley   PetscFunctionBegin;
145346139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
14545dca41c3SJed Brown   if (shape == DM_SHAPE_ZBOX) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
14556725e60dSJed Brown   else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0]));
14569566063dSJacob Faibussowitsch   else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
14579566063dSJacob Faibussowitsch   else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity));
14589318fe57SMatthew G. Knepley   if (!interpolate && dim > 1 && !simplex) {
1459768d5fceSMatthew G. Knepley     DM udm;
1460768d5fceSMatthew G. Knepley 
14619566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(dm, &udm));
14629566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, udm));
146369d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &udm));
1464768d5fceSMatthew G. Knepley   }
146546139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
14663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1467c8c68bd8SToby Isaac }
1468c8c68bd8SToby Isaac 
14695d83a8b1SBarry Smith /*@
1470768d5fceSMatthew G. Knepley   DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra).
1471768d5fceSMatthew G. Knepley 
1472d083f849SBarry Smith   Collective
1473768d5fceSMatthew G. Knepley 
1474768d5fceSMatthew G. Knepley   Input Parameters:
1475a1cb98faSBarry Smith + comm               - The communicator for the `DM` object
1476768d5fceSMatthew G. Knepley . dim                - The spatial dimension
1477a1cb98faSBarry Smith . simplex            - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells
147820f4b53cSBarry Smith . faces              - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
147920f4b53cSBarry Smith . lower              - The lower left corner, or `NULL` for (0, 0, 0)
148020f4b53cSBarry Smith . upper              - The upper right corner, or `NULL` for (1, 1, 1)
148120f4b53cSBarry Smith . periodicity        - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE`
148242108689Sksagiyam . interpolate        - Flag to create intermediate mesh pieces (edges, faces)
148342108689Sksagiyam . localizationHeight - Flag to localize edges and faces in addition to cells; only significant for periodic meshes
148442108689Sksagiyam - sparseLocalize     - Flag to localize coordinates only for cells near the periodic boundary; only significant for periodic meshes
1485768d5fceSMatthew G. Knepley 
1486768d5fceSMatthew G. Knepley   Output Parameter:
1487a1cb98faSBarry Smith . dm - The `DM` object
1488768d5fceSMatthew G. Knepley 
1489768d5fceSMatthew G. Knepley   Level: beginner
1490768d5fceSMatthew G. Knepley 
1491a1cb98faSBarry Smith   Note:
1492a1cb98faSBarry Smith   To customize this mesh using options, use
1493a1cb98faSBarry Smith .vb
1494a1cb98faSBarry Smith   DMCreate(comm, &dm);
1495a1cb98faSBarry Smith   DMSetType(dm, DMPLEX);
1496a1cb98faSBarry Smith   DMSetFromOptions(dm);
1497a1cb98faSBarry Smith .ve
1498a1cb98faSBarry Smith   and use the options in `DMSetFromOptions()`.
1499a1cb98faSBarry Smith 
1500a4e35b19SJacob Faibussowitsch   Here is the numbering returned for 2 faces in each direction for tensor cells\:
1501a1cb98faSBarry Smith .vb
1502a1cb98faSBarry Smith  10---17---11---18----12
1503a1cb98faSBarry Smith   |         |         |
1504a1cb98faSBarry Smith   |         |         |
1505a1cb98faSBarry Smith  20    2   22    3    24
1506a1cb98faSBarry Smith   |         |         |
1507a1cb98faSBarry Smith   |         |         |
1508a1cb98faSBarry Smith   7---15----8---16----9
1509a1cb98faSBarry Smith   |         |         |
1510a1cb98faSBarry Smith   |         |         |
1511a1cb98faSBarry Smith  19    0   21    1   23
1512a1cb98faSBarry Smith   |         |         |
1513a1cb98faSBarry Smith   |         |         |
1514a1cb98faSBarry Smith   4---13----5---14----6
1515a1cb98faSBarry Smith .ve
1516a1cb98faSBarry Smith   and for simplicial cells
1517a1cb98faSBarry Smith .vb
1518a1cb98faSBarry Smith  14----8---15----9----16
1519a1cb98faSBarry Smith   |\     5  |\      7 |
1520a1cb98faSBarry Smith   | \       | \       |
1521a1cb98faSBarry Smith  13   2    14    3    15
1522a1cb98faSBarry Smith   | 4   \   | 6   \   |
1523a1cb98faSBarry Smith   |       \ |       \ |
1524a1cb98faSBarry Smith  11----6---12----7----13
1525a1cb98faSBarry Smith   |\        |\        |
1526a1cb98faSBarry Smith   | \    1  | \     3 |
1527a1cb98faSBarry Smith  10   0    11    1    12
1528a1cb98faSBarry Smith   | 0   \   | 2   \   |
1529a1cb98faSBarry Smith   |       \ |       \ |
1530a1cb98faSBarry Smith   8----4----9----5----10
1531a1cb98faSBarry Smith .ve
1532a1cb98faSBarry Smith 
15331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
1534768d5fceSMatthew G. Knepley @*/
153542108689Sksagiyam PetscErrorCode DMPlexCreateBoxMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate, PetscInt localizationHeight, PetscBool sparseLocalize, DM *dm)
1536d71ae5a4SJacob Faibussowitsch {
15379318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
1538fdbf62faSLisandro Dalcin   PetscReal      low[3] = {0, 0, 0};
1539fdbf62faSLisandro Dalcin   PetscReal      upp[3] = {1, 1, 1};
1540fdbf62faSLisandro Dalcin   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
1541552f7358SJed Brown 
1542768d5fceSMatthew G. Knepley   PetscFunctionBegin;
15439566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
15449566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
15455dca41c3SJed Brown   PetscCall(DMPlexCreateBoxMesh_Internal(*dm, DM_SHAPE_BOX, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate));
154642108689Sksagiyam   if (periodicity) {
154742108689Sksagiyam     DM cdm;
154842108689Sksagiyam 
154942108689Sksagiyam     PetscCall(DMGetCoordinateDM(*dm, &cdm));
155042108689Sksagiyam     PetscCall(DMPlexSetMaxProjectionHeight(cdm, localizationHeight));
155142108689Sksagiyam     PetscCall(DMSetSparseLocalize(*dm, sparseLocalize));
155242108689Sksagiyam     PetscCall(DMLocalizeCoordinates(*dm));
155342108689Sksagiyam   }
15543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
15559318fe57SMatthew G. Knepley }
1556fdbf62faSLisandro Dalcin 
1557d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1558d71ae5a4SJacob Faibussowitsch {
15599318fe57SMatthew G. Knepley   DM       bdm, vol;
15609318fe57SMatthew G. Knepley   PetscInt i;
15619318fe57SMatthew G. Knepley 
15629318fe57SMatthew G. Knepley   PetscFunctionBegin;
15631fcf445aSMatthew G. Knepley   // TODO Now we can support periodicity
156408401ef6SPierre Jolivet   for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported");
15659566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm));
15669566063dSJacob Faibussowitsch   PetscCall(DMSetType(bdm, DMPLEX));
15679566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(bdm, 2));
156846139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, bdm, 0, 0, 0));
15699566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE));
15701fcf445aSMatthew G. Knepley   PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, NULL, NULL, &vol));
157146139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, bdm, 0, 0, 0));
15729566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&bdm));
157369d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
15749318fe57SMatthew G. Knepley   if (lower[2] != 0.0) {
15759318fe57SMatthew G. Knepley     Vec          v;
15769318fe57SMatthew G. Knepley     PetscScalar *x;
15779318fe57SMatthew G. Knepley     PetscInt     cDim, n;
15789318fe57SMatthew G. Knepley 
15799566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &v));
15809566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(v, &cDim));
15819566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(v, &n));
15829566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v, &x));
15839318fe57SMatthew G. Knepley     x += cDim;
15849318fe57SMatthew G. Knepley     for (i = 0; i < n; i += cDim) x[i] += lower[2];
15859566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v, &x));
15869566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, v));
15879318fe57SMatthew G. Knepley   }
15883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1589552f7358SJed Brown }
1590552f7358SJed Brown 
159100dabe28SStefano Zampini /*@
159239f4f5dbSPierre Jolivet   DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tessellating the (x,y) plane and extruding in the third direction using wedge cells.
159300dabe28SStefano Zampini 
1594d083f849SBarry Smith   Collective
159500dabe28SStefano Zampini 
159600dabe28SStefano Zampini   Input Parameters:
1597a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
159820f4b53cSBarry Smith . faces       - Number of faces per dimension, or `NULL` for (1, 1, 1)
159920f4b53cSBarry Smith . lower       - The lower left corner, or `NULL` for (0, 0, 0)
160020f4b53cSBarry Smith . upper       - The upper right corner, or `NULL` for (1, 1, 1)
160120f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE`
1602a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first
160300dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces)
160400dabe28SStefano Zampini 
160500dabe28SStefano Zampini   Output Parameter:
1606a1cb98faSBarry Smith . dm - The `DM` object
160700dabe28SStefano Zampini 
160800dabe28SStefano Zampini   Level: beginner
160900dabe28SStefano Zampini 
16101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
161100dabe28SStefano Zampini @*/
1612d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm)
1613d71ae5a4SJacob Faibussowitsch {
16149318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
161500dabe28SStefano Zampini   PetscReal      low[3] = {0, 0, 0};
161600dabe28SStefano Zampini   PetscReal      upp[3] = {1, 1, 1};
161700dabe28SStefano Zampini   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
161800dabe28SStefano Zampini 
161900dabe28SStefano Zampini   PetscFunctionBegin;
16209566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
16219566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
16229566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt));
1623d410b0cfSMatthew G. Knepley   if (!interpolate) {
1624d410b0cfSMatthew G. Knepley     DM udm;
162500dabe28SStefano Zampini 
16269566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(*dm, &udm));
162769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(*dm, &udm));
162800dabe28SStefano Zampini   }
16297ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
16303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
163100dabe28SStefano Zampini }
163200dabe28SStefano Zampini 
1633cfb853baSMatthew G. Knepley /*
1634cfb853baSMatthew G. Knepley   DMPlexTensorPointLexicographic_Private - Returns all tuples of size 'len' with nonnegative integers that are all less than or equal to 'max' for that dimension.
1635cfb853baSMatthew G. Knepley 
1636cfb853baSMatthew G. Knepley   Input Parameters:
1637cfb853baSMatthew G. Knepley + len - The length of the tuple
1638cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max)
1639cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition
1640cfb853baSMatthew G. Knepley 
1641cfb853baSMatthew G. Knepley   Output Parameter:
164220f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max`
1643cfb853baSMatthew G. Knepley 
1644cfb853baSMatthew G. Knepley   Level: developer
1645cfb853baSMatthew G. Knepley 
164620f4b53cSBarry Smith   Note:
164720f4b53cSBarry Smith   Ordering is lexicographic with lowest index as least significant in ordering.
164820f4b53cSBarry Smith   e.g. for len == 2 and max == 2, this will return, in order, {0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0,2}, {1,2}, {2,2}.
164920f4b53cSBarry Smith 
1650cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal()
1651cfb853baSMatthew G. Knepley */
1652cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[])
1653cfb853baSMatthew G. Knepley {
1654cfb853baSMatthew G. Knepley   PetscInt i;
1655cfb853baSMatthew G. Knepley 
1656cfb853baSMatthew G. Knepley   PetscFunctionBegin;
1657cfb853baSMatthew G. Knepley   for (i = 0; i < len; ++i) {
1658cfb853baSMatthew G. Knepley     if (tup[i] < max[i] - 1) {
1659cfb853baSMatthew G. Knepley       break;
1660cfb853baSMatthew G. Knepley     } else {
1661cfb853baSMatthew G. Knepley       tup[i] = 0;
1662cfb853baSMatthew G. Knepley     }
1663cfb853baSMatthew G. Knepley   }
1664cfb853baSMatthew G. Knepley   if (i == len) tup[i - 1] = max[i - 1];
1665cfb853baSMatthew G. Knepley   else ++tup[i];
16663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1667cfb853baSMatthew G. Knepley }
1668cfb853baSMatthew G. Knepley 
1669cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[])
1670cfb853baSMatthew G. Knepley {
1671cfb853baSMatthew G. Knepley   PetscInt i, idx = tup[len - 1];
1672cfb853baSMatthew G. Knepley 
1673cfb853baSMatthew G. Knepley   for (i = len - 2; i >= 0; --i) {
1674cfb853baSMatthew G. Knepley     idx *= max[i];
1675cfb853baSMatthew G. Knepley     idx += tup[i];
1676cfb853baSMatthew G. Knepley   }
1677cfb853baSMatthew G. Knepley   return idx;
1678cfb853baSMatthew G. Knepley }
1679cfb853baSMatthew G. Knepley 
1680cfb853baSMatthew G. Knepley static PetscErrorCode DestroyExtent_Private(void *extent)
1681cfb853baSMatthew G. Knepley {
1682cfb853baSMatthew G. Knepley   return PetscFree(extent);
1683cfb853baSMatthew G. Knepley }
1684cfb853baSMatthew G. Knepley 
1685cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], const DMBoundaryType bd[])
1686cfb853baSMatthew G. Knepley {
1687cfb853baSMatthew G. Knepley   Vec          coordinates;
1688cfb853baSMatthew G. Knepley   PetscSection coordSection;
1689cfb853baSMatthew G. Knepley   DMLabel      cutLabel    = NULL;
1690cfb853baSMatthew G. Knepley   PetscBool    cutMarker   = PETSC_FALSE;
1691cfb853baSMatthew G. Knepley   PetscBool    periodic    = PETSC_FALSE;
1692cfb853baSMatthew G. Knepley   PetscInt     numCells    = 1, c;
1693cfb853baSMatthew G. Knepley   PetscInt     numVertices = 1, v;
1694cfb853baSMatthew G. Knepley   PetscScalar *coords;
1695cfb853baSMatthew G. Knepley   PetscInt    *vertices, *vert, *vtmp, *supp, cone[2];
1696cfb853baSMatthew G. Knepley   PetscInt     d, e, cell = 0, coordSize;
1697cfb853baSMatthew G. Knepley   PetscMPIInt  rank;
1698cfb853baSMatthew G. Knepley 
1699cfb853baSMatthew G. Knepley   PetscFunctionBegin;
1700cfb853baSMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1701cfb853baSMatthew G. Knepley   PetscCall(DMSetDimension(dm, dim));
1702cfb853baSMatthew G. Knepley   PetscCall(PetscCalloc4(dim, &vertices, dim, &vert, dim, &vtmp, 2 * dim, &supp));
1703cfb853baSMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "marker"));
1704cfb853baSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
1705cfb853baSMatthew G. Knepley   for (d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE;
1706cfb853baSMatthew G. Knepley   if (periodic && cutMarker) {
1707cfb853baSMatthew G. Knepley     PetscCall(DMCreateLabel(dm, "periodic_cut"));
1708cfb853baSMatthew G. Knepley     PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
1709cfb853baSMatthew G. Knepley   }
1710cfb853baSMatthew G. Knepley   for (d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Hypercubic mesh must be periodic now");
1711cfb853baSMatthew G. Knepley   for (d = 0; d < dim; ++d) {
1712cfb853baSMatthew G. Knepley     vertices[d] = edges[d];
1713cfb853baSMatthew G. Knepley     numVertices *= vertices[d];
1714cfb853baSMatthew G. Knepley   }
1715cfb853baSMatthew G. Knepley   numCells = numVertices * dim;
1716cfb853baSMatthew G. Knepley   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
1717cfb853baSMatthew G. Knepley   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2));
1718cfb853baSMatthew G. Knepley   for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim));
1719cfb853baSMatthew G. Knepley   /* TODO Loop over boundary and reset support sizes */
1720cfb853baSMatthew G. Knepley   PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */
1721cfb853baSMatthew G. Knepley   /* Build cell cones and vertex supports */
1722cfb853baSMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "celltype"));
1723cfb853baSMatthew G. Knepley   while (vert[dim - 1] < vertices[dim - 1]) {
1724cfb853baSMatthew G. Knepley     const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells;
1725cfb853baSMatthew G. Knepley     PetscInt       s      = 0;
1726cfb853baSMatthew G. Knepley 
17273ba16761SJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "Vertex %" PetscInt_FMT ":", vertex));
17283ba16761SJacob Faibussowitsch     for (d = 0; d < dim; ++d) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, vert[d]));
17293ba16761SJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
1730cfb853baSMatthew G. Knepley     PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT));
1731cfb853baSMatthew G. Knepley     for (d = 0; d < dim; ++d) {
1732cfb853baSMatthew G. Knepley       for (e = 0; e < dim; ++e) vtmp[e] = vert[e];
1733cfb853baSMatthew G. Knepley       vtmp[d] = (vert[d] + 1) % vertices[d];
1734cfb853baSMatthew G. Knepley       cone[0] = vertex;
1735cfb853baSMatthew G. Knepley       cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells;
17363ba16761SJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Vertex %" PetscInt_FMT ":", cone[1]));
17373ba16761SJacob Faibussowitsch       for (e = 0; e < dim; ++e) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, vtmp[e]));
17383ba16761SJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
1739cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetCone(dm, cell, cone));
1740cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT));
17413ba16761SJacob Faibussowitsch       PetscCall(PetscPrintf(PETSC_COMM_SELF, "  Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1]));
1742cfb853baSMatthew G. Knepley       ++cell;
1743cfb853baSMatthew G. Knepley     }
1744cfb853baSMatthew G. Knepley     for (d = 0; d < dim; ++d) {
1745cfb853baSMatthew G. Knepley       for (e = 0; e < dim; ++e) vtmp[e] = vert[e];
1746cfb853baSMatthew G. Knepley       vtmp[d]   = (vert[d] + vertices[d] - 1) % vertices[d];
1747cfb853baSMatthew G. Knepley       supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d;
1748cfb853baSMatthew G. Knepley       supp[s++] = (vertex - numCells) * dim + d;
1749cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetSupport(dm, vertex, supp));
1750cfb853baSMatthew G. Knepley     }
1751cfb853baSMatthew G. Knepley     PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert));
1752cfb853baSMatthew G. Knepley   }
1753cfb853baSMatthew G. Knepley   PetscCall(DMPlexStratify(dm));
1754cfb853baSMatthew G. Knepley   /* Build coordinates */
1755cfb853baSMatthew G. Knepley   PetscCall(DMGetCoordinateSection(dm, &coordSection));
1756cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetNumFields(coordSection, 1));
1757cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
1758cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
1759cfb853baSMatthew G. Knepley   for (v = numCells; v < numCells + numVertices; ++v) {
1760cfb853baSMatthew G. Knepley     PetscCall(PetscSectionSetDof(coordSection, v, dim));
1761cfb853baSMatthew G. Knepley     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
1762cfb853baSMatthew G. Knepley   }
1763cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetUp(coordSection));
1764cfb853baSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
1765cfb853baSMatthew G. Knepley   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
1766cfb853baSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
1767cfb853baSMatthew G. Knepley   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
1768cfb853baSMatthew G. Knepley   PetscCall(VecSetBlockSize(coordinates, dim));
1769cfb853baSMatthew G. Knepley   PetscCall(VecSetType(coordinates, VECSTANDARD));
1770cfb853baSMatthew G. Knepley   PetscCall(VecGetArray(coordinates, &coords));
1771cfb853baSMatthew G. Knepley   for (d = 0; d < dim; ++d) vert[d] = 0;
1772cfb853baSMatthew G. Knepley   while (vert[dim - 1] < vertices[dim - 1]) {
1773cfb853baSMatthew G. Knepley     const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert);
1774cfb853baSMatthew G. Knepley 
1775cfb853baSMatthew G. Knepley     for (d = 0; d < dim; ++d) coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / vertices[d]) * vert[d];
17763ba16761SJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "Vertex %" PetscInt_FMT ":", vertex));
17773ba16761SJacob Faibussowitsch     for (d = 0; d < dim; ++d) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %" PetscInt_FMT, vert[d]));
17783ba16761SJacob Faibussowitsch     for (d = 0; d < dim; ++d) PetscCall(PetscPrintf(PETSC_COMM_SELF, " %g", (double)PetscRealPart(coords[vertex * dim + d])));
17793ba16761SJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n"));
1780cfb853baSMatthew G. Knepley     PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert));
1781cfb853baSMatthew G. Knepley   }
1782cfb853baSMatthew G. Knepley   PetscCall(VecRestoreArray(coordinates, &coords));
1783cfb853baSMatthew G. Knepley   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
1784cfb853baSMatthew G. Knepley   PetscCall(VecDestroy(&coordinates));
1785cfb853baSMatthew G. Knepley   PetscCall(PetscFree4(vertices, vert, vtmp, supp));
1786cfb853baSMatthew G. Knepley   //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper));
1787cfb853baSMatthew G. Knepley   // Attach the extent
1788cfb853baSMatthew G. Knepley   {
1789cfb853baSMatthew G. Knepley     PetscContainer c;
1790cfb853baSMatthew G. Knepley     PetscInt      *extent;
1791cfb853baSMatthew G. Knepley 
1792cfb853baSMatthew G. Knepley     PetscCall(PetscMalloc1(dim, &extent));
1793cfb853baSMatthew G. Knepley     for (PetscInt d = 0; d < dim; ++d) extent[d] = edges[d];
1794cfb853baSMatthew G. Knepley     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c));
1795cfb853baSMatthew G. Knepley     PetscCall(PetscContainerSetUserDestroy(c, DestroyExtent_Private));
1796cfb853baSMatthew G. Knepley     PetscCall(PetscContainerSetPointer(c, extent));
1797cfb853baSMatthew G. Knepley     PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c));
1798cfb853baSMatthew G. Knepley     PetscCall(PetscContainerDestroy(&c));
1799cfb853baSMatthew G. Knepley   }
18003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1801cfb853baSMatthew G. Knepley }
1802cfb853baSMatthew G. Knepley 
1803cfb853baSMatthew G. Knepley /*@C
1804aaa8cc7dSPierre Jolivet   DMPlexCreateHypercubicMesh - Creates a periodic mesh on the tensor product of unit intervals using only vertices and edges.
1805cfb853baSMatthew G. Knepley 
1806cfb853baSMatthew G. Knepley   Collective
1807cfb853baSMatthew G. Knepley 
1808cfb853baSMatthew G. Knepley   Input Parameters:
1809cfb853baSMatthew G. Knepley + comm  - The communicator for the DM object
1810cfb853baSMatthew G. Knepley . dim   - The spatial dimension
181120f4b53cSBarry Smith . edges - Number of edges per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
181220f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0)
181320f4b53cSBarry Smith - upper - The upper right corner, or `NULL` for (1, 1, 1)
1814cfb853baSMatthew G. Knepley 
1815cfb853baSMatthew G. Knepley   Output Parameter:
1816cfb853baSMatthew G. Knepley . dm - The DM object
1817cfb853baSMatthew G. Knepley 
181820f4b53cSBarry Smith   Level: beginner
181920f4b53cSBarry Smith 
182020f4b53cSBarry Smith   Note:
182120f4b53cSBarry Smith   If you want to customize this mesh using options, you just need to
182220f4b53cSBarry Smith .vb
182320f4b53cSBarry Smith   DMCreate(comm, &dm);
182420f4b53cSBarry Smith   DMSetType(dm, DMPLEX);
182520f4b53cSBarry Smith   DMSetFromOptions(dm);
182620f4b53cSBarry Smith .ve
182720f4b53cSBarry Smith   and use the options on the `DMSetFromOptions()` page.
1828cfb853baSMatthew G. Knepley 
1829cfb853baSMatthew G. Knepley   The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively,
183020f4b53cSBarry Smith .vb
183120f4b53cSBarry Smith  18--0-19--2-20--4-18
183220f4b53cSBarry Smith   |     |     |     |
183320f4b53cSBarry Smith  13    15    17    13
183420f4b53cSBarry Smith   |     |     |     |
183520f4b53cSBarry Smith  24-12-25-14-26-16-24
183620f4b53cSBarry Smith   |     |     |     |
183720f4b53cSBarry Smith   7     9    11     7
183820f4b53cSBarry Smith   |     |     |     |
183920f4b53cSBarry Smith  21--6-22--8-23-10-21
184020f4b53cSBarry Smith   |     |     |     |
184120f4b53cSBarry Smith   1     3     5     1
184220f4b53cSBarry Smith   |     |     |     |
184320f4b53cSBarry Smith  18--0-19--2-20--4-18
184420f4b53cSBarry Smith .ve
1845cfb853baSMatthew G. Knepley 
184676fbde31SPierre Jolivet .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
1847cfb853baSMatthew G. Knepley @*/
1848cfb853baSMatthew G. Knepley PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], DM *dm)
1849cfb853baSMatthew G. Knepley {
1850cfb853baSMatthew G. Knepley   PetscInt       *edg;
1851cfb853baSMatthew G. Knepley   PetscReal      *low, *upp;
1852cfb853baSMatthew G. Knepley   DMBoundaryType *bdt;
1853cfb853baSMatthew G. Knepley   PetscInt        d;
1854cfb853baSMatthew G. Knepley 
1855cfb853baSMatthew G. Knepley   PetscFunctionBegin;
1856cfb853baSMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
1857cfb853baSMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
1858cfb853baSMatthew G. Knepley   PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt));
1859cfb853baSMatthew G. Knepley   for (d = 0; d < dim; ++d) {
1860cfb853baSMatthew G. Knepley     edg[d] = edges ? edges[d] : 1;
1861cfb853baSMatthew G. Knepley     low[d] = lower ? lower[d] : 0.;
1862cfb853baSMatthew G. Knepley     upp[d] = upper ? upper[d] : 1.;
1863cfb853baSMatthew G. Knepley     bdt[d] = DM_BOUNDARY_PERIODIC;
1864cfb853baSMatthew G. Knepley   }
1865cfb853baSMatthew G. Knepley   PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, bdt));
1866cfb853baSMatthew G. Knepley   PetscCall(PetscFree4(edg, low, upp, bdt));
18673ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1868cfb853baSMatthew G. Knepley }
1869cfb853baSMatthew G. Knepley 
1870cc4c1da9SBarry Smith /*@
1871a1cb98faSBarry Smith   DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database.
1872a9074c1eSMatthew G. Knepley 
187320f4b53cSBarry Smith   Logically Collective
1874a9074c1eSMatthew G. Knepley 
1875a9074c1eSMatthew G. Knepley   Input Parameters:
187620f4b53cSBarry Smith + dm     - the `DM` context
1877a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names
1878a9074c1eSMatthew G. Knepley 
1879a1cb98faSBarry Smith   Level: advanced
1880a1cb98faSBarry Smith 
1881a1cb98faSBarry Smith   Note:
1882a9074c1eSMatthew G. Knepley   A hyphen (-) must NOT be given at the beginning of the prefix name.
1883a9074c1eSMatthew G. Knepley   The first character of all runtime options is AUTOMATICALLY the hyphen.
1884a9074c1eSMatthew G. Knepley 
18851cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()`
1886a9074c1eSMatthew G. Knepley @*/
1887d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[])
1888d71ae5a4SJacob Faibussowitsch {
1889a9074c1eSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
1890a9074c1eSMatthew G. Knepley 
1891a9074c1eSMatthew G. Knepley   PetscFunctionBegin;
1892a9074c1eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
18939566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
18949566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix));
18953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1896a9074c1eSMatthew G. Knepley }
1897a9074c1eSMatthew G. Knepley 
18989318fe57SMatthew G. Knepley /* Remap geometry to cylinder
189961a622f3SMatthew G. Knepley    TODO: This only works for a single refinement, then it is broken
190061a622f3SMatthew G. Knepley 
19019318fe57SMatthew G. Knepley      Interior square: Linear interpolation is correct
19029318fe57SMatthew G. Knepley      The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing
19039318fe57SMatthew G. Knepley      such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance
19040510c589SMatthew G. Knepley 
19059318fe57SMatthew G. Knepley        phi     = arctan(y/x)
19069318fe57SMatthew G. Knepley        d_close = sqrt(1/8 + 1/4 sin^2(phi))
19079318fe57SMatthew G. Knepley        d_far   = sqrt(1/2 + sin^2(phi))
19080510c589SMatthew G. Knepley 
19099318fe57SMatthew G. Knepley      so we remap them using
19100510c589SMatthew G. Knepley 
19119318fe57SMatthew G. Knepley        x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close)
19129318fe57SMatthew G. Knepley        y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close)
19130510c589SMatthew G. Knepley 
19149318fe57SMatthew G. Knepley      If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y.
19159318fe57SMatthew G. Knepley */
1916d71ae5a4SJacob 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[])
1917d71ae5a4SJacob Faibussowitsch {
19189318fe57SMatthew G. Knepley   const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
19199318fe57SMatthew G. Knepley   const PetscReal ds2 = 0.5 * dis;
192022cc497dSMatthew G. Knepley 
19219318fe57SMatthew G. Knepley   if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) {
19229318fe57SMatthew G. Knepley     f0[0] = u[0];
19239318fe57SMatthew G. Knepley     f0[1] = u[1];
19249318fe57SMatthew G. Knepley   } else {
19259318fe57SMatthew G. Knepley     PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc;
19260510c589SMatthew G. Knepley 
19279318fe57SMatthew G. Knepley     x    = PetscRealPart(u[0]);
19289318fe57SMatthew G. Knepley     y    = PetscRealPart(u[1]);
19299318fe57SMatthew G. Knepley     phi  = PetscAtan2Real(y, x);
19309318fe57SMatthew G. Knepley     sinp = PetscSinReal(phi);
19319318fe57SMatthew G. Knepley     cosp = PetscCosReal(phi);
19329318fe57SMatthew G. Knepley     if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) {
19339318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / sinp);
19349318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / sinp);
19359318fe57SMatthew G. Knepley       xc = ds2 * x / PetscAbsReal(y);
19369318fe57SMatthew G. Knepley       yc = ds2 * PetscSignReal(y);
19379318fe57SMatthew G. Knepley     } else {
19389318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / cosp);
19399318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / cosp);
19409318fe57SMatthew G. Knepley       xc = ds2 * PetscSignReal(x);
19419318fe57SMatthew G. Knepley       yc = ds2 * y / PetscAbsReal(x);
19429318fe57SMatthew G. Knepley     }
19439318fe57SMatthew G. Knepley     f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc);
19449318fe57SMatthew G. Knepley     f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc);
19459318fe57SMatthew G. Knepley   }
19469318fe57SMatthew G. Knepley   f0[2] = u[2];
19479318fe57SMatthew G. Knepley }
19480510c589SMatthew G. Knepley 
194949704ca5SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ, PetscInt Nr)
1950d71ae5a4SJacob Faibussowitsch {
19510510c589SMatthew G. Knepley   const PetscInt dim = 3;
19529318fe57SMatthew G. Knepley   PetscInt       numCells, numVertices;
1953d8c47e87SMatthew G. Knepley   PetscMPIInt    rank;
19540510c589SMatthew G. Knepley 
19550510c589SMatthew G. Knepley   PetscFunctionBegin;
195646139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
19579566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
19589566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
19590510c589SMatthew G. Knepley   /* Create topology */
19600510c589SMatthew G. Knepley   {
19610510c589SMatthew G. Knepley     PetscInt cone[8], c;
19620510c589SMatthew G. Knepley 
1963dd400576SPatrick Sanan     numCells    = rank == 0 ? 5 : 0;
1964dd400576SPatrick Sanan     numVertices = rank == 0 ? 16 : 0;
1965006a8963SMatthew G. Knepley     if (periodicZ == DM_BOUNDARY_PERIODIC) {
1966ae8bcbbbSMatthew G. Knepley       numCells *= 3;
1967dd400576SPatrick Sanan       numVertices = rank == 0 ? 24 : 0;
1968006a8963SMatthew G. Knepley     }
19699566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
19709566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8));
19719566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
1972dd400576SPatrick Sanan     if (rank == 0) {
1973006a8963SMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
19749371c9d4SSatish Balay         cone[0] = 15;
19759371c9d4SSatish Balay         cone[1] = 18;
19769371c9d4SSatish Balay         cone[2] = 17;
19779371c9d4SSatish Balay         cone[3] = 16;
19789371c9d4SSatish Balay         cone[4] = 31;
19799371c9d4SSatish Balay         cone[5] = 32;
19809371c9d4SSatish Balay         cone[6] = 33;
19819371c9d4SSatish Balay         cone[7] = 34;
19829566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
19839371c9d4SSatish Balay         cone[0] = 16;
19849371c9d4SSatish Balay         cone[1] = 17;
19859371c9d4SSatish Balay         cone[2] = 24;
19869371c9d4SSatish Balay         cone[3] = 23;
19879371c9d4SSatish Balay         cone[4] = 32;
19889371c9d4SSatish Balay         cone[5] = 36;
19899371c9d4SSatish Balay         cone[6] = 37;
19909371c9d4SSatish Balay         cone[7] = 33; /* 22 25 26 21 */
19919566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
19929371c9d4SSatish Balay         cone[0] = 18;
19939371c9d4SSatish Balay         cone[1] = 27;
19949371c9d4SSatish Balay         cone[2] = 24;
19959371c9d4SSatish Balay         cone[3] = 17;
19969371c9d4SSatish Balay         cone[4] = 34;
19979371c9d4SSatish Balay         cone[5] = 33;
19989371c9d4SSatish Balay         cone[6] = 37;
19999371c9d4SSatish Balay         cone[7] = 38;
20009566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
20019371c9d4SSatish Balay         cone[0] = 29;
20029371c9d4SSatish Balay         cone[1] = 27;
20039371c9d4SSatish Balay         cone[2] = 18;
20049371c9d4SSatish Balay         cone[3] = 15;
20059371c9d4SSatish Balay         cone[4] = 35;
20069371c9d4SSatish Balay         cone[5] = 31;
20079371c9d4SSatish Balay         cone[6] = 34;
20089371c9d4SSatish Balay         cone[7] = 38;
20099566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
20109371c9d4SSatish Balay         cone[0] = 29;
20119371c9d4SSatish Balay         cone[1] = 15;
20129371c9d4SSatish Balay         cone[2] = 16;
20139371c9d4SSatish Balay         cone[3] = 23;
20149371c9d4SSatish Balay         cone[4] = 35;
20159371c9d4SSatish Balay         cone[5] = 36;
20169371c9d4SSatish Balay         cone[6] = 32;
20179371c9d4SSatish Balay         cone[7] = 31;
20189566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
2019006a8963SMatthew G. Knepley 
20209371c9d4SSatish Balay         cone[0] = 31;
20219371c9d4SSatish Balay         cone[1] = 34;
20229371c9d4SSatish Balay         cone[2] = 33;
20239371c9d4SSatish Balay         cone[3] = 32;
20249371c9d4SSatish Balay         cone[4] = 19;
20259371c9d4SSatish Balay         cone[5] = 22;
20269371c9d4SSatish Balay         cone[6] = 21;
20279371c9d4SSatish Balay         cone[7] = 20;
20289566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
20299371c9d4SSatish Balay         cone[0] = 32;
20309371c9d4SSatish Balay         cone[1] = 33;
20319371c9d4SSatish Balay         cone[2] = 37;
20329371c9d4SSatish Balay         cone[3] = 36;
20339371c9d4SSatish Balay         cone[4] = 22;
20349371c9d4SSatish Balay         cone[5] = 25;
20359371c9d4SSatish Balay         cone[6] = 26;
20369371c9d4SSatish Balay         cone[7] = 21;
20379566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 6, cone));
20389371c9d4SSatish Balay         cone[0] = 34;
20399371c9d4SSatish Balay         cone[1] = 38;
20409371c9d4SSatish Balay         cone[2] = 37;
20419371c9d4SSatish Balay         cone[3] = 33;
20429371c9d4SSatish Balay         cone[4] = 20;
20439371c9d4SSatish Balay         cone[5] = 21;
20449371c9d4SSatish Balay         cone[6] = 26;
20459371c9d4SSatish Balay         cone[7] = 28;
20469566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 7, cone));
20479371c9d4SSatish Balay         cone[0] = 35;
20489371c9d4SSatish Balay         cone[1] = 38;
20499371c9d4SSatish Balay         cone[2] = 34;
20509371c9d4SSatish Balay         cone[3] = 31;
20519371c9d4SSatish Balay         cone[4] = 30;
20529371c9d4SSatish Balay         cone[5] = 19;
20539371c9d4SSatish Balay         cone[6] = 20;
20549371c9d4SSatish Balay         cone[7] = 28;
20559566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 8, cone));
20569371c9d4SSatish Balay         cone[0] = 35;
20579371c9d4SSatish Balay         cone[1] = 31;
20589371c9d4SSatish Balay         cone[2] = 32;
20599371c9d4SSatish Balay         cone[3] = 36;
20609371c9d4SSatish Balay         cone[4] = 30;
20619371c9d4SSatish Balay         cone[5] = 25;
20629371c9d4SSatish Balay         cone[6] = 22;
20639371c9d4SSatish Balay         cone[7] = 19;
20649566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 9, cone));
2065ae8bcbbbSMatthew G. Knepley 
20669371c9d4SSatish Balay         cone[0] = 19;
20679371c9d4SSatish Balay         cone[1] = 20;
20689371c9d4SSatish Balay         cone[2] = 21;
20699371c9d4SSatish Balay         cone[3] = 22;
20709371c9d4SSatish Balay         cone[4] = 15;
20719371c9d4SSatish Balay         cone[5] = 16;
20729371c9d4SSatish Balay         cone[6] = 17;
20739371c9d4SSatish Balay         cone[7] = 18;
20749566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 10, cone));
20759371c9d4SSatish Balay         cone[0] = 22;
20769371c9d4SSatish Balay         cone[1] = 21;
20779371c9d4SSatish Balay         cone[2] = 26;
20789371c9d4SSatish Balay         cone[3] = 25;
20799371c9d4SSatish Balay         cone[4] = 16;
20809371c9d4SSatish Balay         cone[5] = 23;
20819371c9d4SSatish Balay         cone[6] = 24;
20829371c9d4SSatish Balay         cone[7] = 17;
20839566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 11, cone));
20849371c9d4SSatish Balay         cone[0] = 20;
20859371c9d4SSatish Balay         cone[1] = 28;
20869371c9d4SSatish Balay         cone[2] = 26;
20879371c9d4SSatish Balay         cone[3] = 21;
20889371c9d4SSatish Balay         cone[4] = 18;
20899371c9d4SSatish Balay         cone[5] = 17;
20909371c9d4SSatish Balay         cone[6] = 24;
20919371c9d4SSatish Balay         cone[7] = 27;
20929566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 12, cone));
20939371c9d4SSatish Balay         cone[0] = 30;
20949371c9d4SSatish Balay         cone[1] = 28;
20959371c9d4SSatish Balay         cone[2] = 20;
20969371c9d4SSatish Balay         cone[3] = 19;
20979371c9d4SSatish Balay         cone[4] = 29;
20989371c9d4SSatish Balay         cone[5] = 15;
20999371c9d4SSatish Balay         cone[6] = 18;
21009371c9d4SSatish Balay         cone[7] = 27;
21019566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 13, cone));
21029371c9d4SSatish Balay         cone[0] = 30;
21039371c9d4SSatish Balay         cone[1] = 19;
21049371c9d4SSatish Balay         cone[2] = 22;
21059371c9d4SSatish Balay         cone[3] = 25;
21069371c9d4SSatish Balay         cone[4] = 29;
21079371c9d4SSatish Balay         cone[5] = 23;
21089371c9d4SSatish Balay         cone[6] = 16;
21099371c9d4SSatish Balay         cone[7] = 15;
21109566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
2111006a8963SMatthew G. Knepley       } else {
21129371c9d4SSatish Balay         cone[0] = 5;
21139371c9d4SSatish Balay         cone[1] = 8;
21149371c9d4SSatish Balay         cone[2] = 7;
21159371c9d4SSatish Balay         cone[3] = 6;
21169371c9d4SSatish Balay         cone[4] = 9;
21179371c9d4SSatish Balay         cone[5] = 12;
21189371c9d4SSatish Balay         cone[6] = 11;
21199371c9d4SSatish Balay         cone[7] = 10;
21209566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
21219371c9d4SSatish Balay         cone[0] = 6;
21229371c9d4SSatish Balay         cone[1] = 7;
21239371c9d4SSatish Balay         cone[2] = 14;
21249371c9d4SSatish Balay         cone[3] = 13;
21259371c9d4SSatish Balay         cone[4] = 12;
21269371c9d4SSatish Balay         cone[5] = 15;
21279371c9d4SSatish Balay         cone[6] = 16;
21289371c9d4SSatish Balay         cone[7] = 11;
21299566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
21309371c9d4SSatish Balay         cone[0] = 8;
21319371c9d4SSatish Balay         cone[1] = 17;
21329371c9d4SSatish Balay         cone[2] = 14;
21339371c9d4SSatish Balay         cone[3] = 7;
21349371c9d4SSatish Balay         cone[4] = 10;
21359371c9d4SSatish Balay         cone[5] = 11;
21369371c9d4SSatish Balay         cone[6] = 16;
21379371c9d4SSatish Balay         cone[7] = 18;
21389566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
21399371c9d4SSatish Balay         cone[0] = 19;
21409371c9d4SSatish Balay         cone[1] = 17;
21419371c9d4SSatish Balay         cone[2] = 8;
21429371c9d4SSatish Balay         cone[3] = 5;
21439371c9d4SSatish Balay         cone[4] = 20;
21449371c9d4SSatish Balay         cone[5] = 9;
21459371c9d4SSatish Balay         cone[6] = 10;
21469371c9d4SSatish Balay         cone[7] = 18;
21479566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
21489371c9d4SSatish Balay         cone[0] = 19;
21499371c9d4SSatish Balay         cone[1] = 5;
21509371c9d4SSatish Balay         cone[2] = 6;
21519371c9d4SSatish Balay         cone[3] = 13;
21529371c9d4SSatish Balay         cone[4] = 20;
21539371c9d4SSatish Balay         cone[5] = 15;
21549371c9d4SSatish Balay         cone[6] = 12;
21559371c9d4SSatish Balay         cone[7] = 9;
21569566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
2157006a8963SMatthew G. Knepley       }
2158d8c47e87SMatthew G. Knepley     }
21599566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
21609566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
21610510c589SMatthew G. Knepley   }
2162dbc1dc17SMatthew G. Knepley   /* Create cube geometry */
21630510c589SMatthew G. Knepley   {
21640510c589SMatthew G. Knepley     Vec             coordinates;
21650510c589SMatthew G. Knepley     PetscSection    coordSection;
21660510c589SMatthew G. Knepley     PetscScalar    *coords;
21670510c589SMatthew G. Knepley     PetscInt        coordSize, v;
21680510c589SMatthew G. Knepley     const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
21690510c589SMatthew G. Knepley     const PetscReal ds2 = dis / 2.0;
21700510c589SMatthew G. Knepley 
21710510c589SMatthew G. Knepley     /* Build coordinates */
21729566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
21739566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
21749566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
21759566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
21760510c589SMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
21779566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
21789566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
21790510c589SMatthew G. Knepley     }
21809566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
21819566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
21829566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
21839566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
21849566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
21859566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
21869566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
21879566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
2188dd400576SPatrick Sanan     if (rank == 0) {
21899371c9d4SSatish Balay       coords[0 * dim + 0]  = -ds2;
21909371c9d4SSatish Balay       coords[0 * dim + 1]  = -ds2;
21919371c9d4SSatish Balay       coords[0 * dim + 2]  = 0.0;
21929371c9d4SSatish Balay       coords[1 * dim + 0]  = ds2;
21939371c9d4SSatish Balay       coords[1 * dim + 1]  = -ds2;
21949371c9d4SSatish Balay       coords[1 * dim + 2]  = 0.0;
21959371c9d4SSatish Balay       coords[2 * dim + 0]  = ds2;
21969371c9d4SSatish Balay       coords[2 * dim + 1]  = ds2;
21979371c9d4SSatish Balay       coords[2 * dim + 2]  = 0.0;
21989371c9d4SSatish Balay       coords[3 * dim + 0]  = -ds2;
21999371c9d4SSatish Balay       coords[3 * dim + 1]  = ds2;
22009371c9d4SSatish Balay       coords[3 * dim + 2]  = 0.0;
22019371c9d4SSatish Balay       coords[4 * dim + 0]  = -ds2;
22029371c9d4SSatish Balay       coords[4 * dim + 1]  = -ds2;
22039371c9d4SSatish Balay       coords[4 * dim + 2]  = 1.0;
22049371c9d4SSatish Balay       coords[5 * dim + 0]  = -ds2;
22059371c9d4SSatish Balay       coords[5 * dim + 1]  = ds2;
22069371c9d4SSatish Balay       coords[5 * dim + 2]  = 1.0;
22079371c9d4SSatish Balay       coords[6 * dim + 0]  = ds2;
22089371c9d4SSatish Balay       coords[6 * dim + 1]  = ds2;
22099371c9d4SSatish Balay       coords[6 * dim + 2]  = 1.0;
22109371c9d4SSatish Balay       coords[7 * dim + 0]  = ds2;
22119371c9d4SSatish Balay       coords[7 * dim + 1]  = -ds2;
22129371c9d4SSatish Balay       coords[7 * dim + 2]  = 1.0;
22139371c9d4SSatish Balay       coords[8 * dim + 0]  = dis;
22149371c9d4SSatish Balay       coords[8 * dim + 1]  = -dis;
22159371c9d4SSatish Balay       coords[8 * dim + 2]  = 0.0;
22169371c9d4SSatish Balay       coords[9 * dim + 0]  = dis;
22179371c9d4SSatish Balay       coords[9 * dim + 1]  = dis;
22189371c9d4SSatish Balay       coords[9 * dim + 2]  = 0.0;
22199371c9d4SSatish Balay       coords[10 * dim + 0] = dis;
22209371c9d4SSatish Balay       coords[10 * dim + 1] = -dis;
22219371c9d4SSatish Balay       coords[10 * dim + 2] = 1.0;
22229371c9d4SSatish Balay       coords[11 * dim + 0] = dis;
22239371c9d4SSatish Balay       coords[11 * dim + 1] = dis;
22249371c9d4SSatish Balay       coords[11 * dim + 2] = 1.0;
22259371c9d4SSatish Balay       coords[12 * dim + 0] = -dis;
22269371c9d4SSatish Balay       coords[12 * dim + 1] = dis;
22279371c9d4SSatish Balay       coords[12 * dim + 2] = 0.0;
22289371c9d4SSatish Balay       coords[13 * dim + 0] = -dis;
22299371c9d4SSatish Balay       coords[13 * dim + 1] = dis;
22309371c9d4SSatish Balay       coords[13 * dim + 2] = 1.0;
22319371c9d4SSatish Balay       coords[14 * dim + 0] = -dis;
22329371c9d4SSatish Balay       coords[14 * dim + 1] = -dis;
22339371c9d4SSatish Balay       coords[14 * dim + 2] = 0.0;
22349371c9d4SSatish Balay       coords[15 * dim + 0] = -dis;
22359371c9d4SSatish Balay       coords[15 * dim + 1] = -dis;
22369371c9d4SSatish Balay       coords[15 * dim + 2] = 1.0;
2237ae8bcbbbSMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
22389371c9d4SSatish Balay         /* 15 31 19 */ coords[16 * dim + 0] = -ds2;
22399371c9d4SSatish Balay         coords[16 * dim + 1]                = -ds2;
22409371c9d4SSatish Balay         coords[16 * dim + 2]                = 0.5;
22419371c9d4SSatish Balay         /* 16 32 22 */ coords[17 * dim + 0] = ds2;
22429371c9d4SSatish Balay         coords[17 * dim + 1]                = -ds2;
22439371c9d4SSatish Balay         coords[17 * dim + 2]                = 0.5;
22449371c9d4SSatish Balay         /* 17 33 21 */ coords[18 * dim + 0] = ds2;
22459371c9d4SSatish Balay         coords[18 * dim + 1]                = ds2;
22469371c9d4SSatish Balay         coords[18 * dim + 2]                = 0.5;
22479371c9d4SSatish Balay         /* 18 34 20 */ coords[19 * dim + 0] = -ds2;
22489371c9d4SSatish Balay         coords[19 * dim + 1]                = ds2;
22499371c9d4SSatish Balay         coords[19 * dim + 2]                = 0.5;
22509371c9d4SSatish Balay         /* 29 35 30 */ coords[20 * dim + 0] = -dis;
22519371c9d4SSatish Balay         coords[20 * dim + 1]                = -dis;
22529371c9d4SSatish Balay         coords[20 * dim + 2]                = 0.5;
22539371c9d4SSatish Balay         /* 23 36 25 */ coords[21 * dim + 0] = dis;
22549371c9d4SSatish Balay         coords[21 * dim + 1]                = -dis;
22559371c9d4SSatish Balay         coords[21 * dim + 2]                = 0.5;
22569371c9d4SSatish Balay         /* 24 37 26 */ coords[22 * dim + 0] = dis;
22579371c9d4SSatish Balay         coords[22 * dim + 1]                = dis;
22589371c9d4SSatish Balay         coords[22 * dim + 2]                = 0.5;
22599371c9d4SSatish Balay         /* 27 38 28 */ coords[23 * dim + 0] = -dis;
22609371c9d4SSatish Balay         coords[23 * dim + 1]                = dis;
22619371c9d4SSatish Balay         coords[23 * dim + 2]                = 0.5;
2262ae8bcbbbSMatthew G. Knepley       }
2263d8c47e87SMatthew G. Knepley     }
22649566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
22659566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
22669566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
22670510c589SMatthew G. Knepley   }
2268006a8963SMatthew G. Knepley   /* Create periodicity */
2269006a8963SMatthew G. Knepley   if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) {
22706858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
22716858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
2272006a8963SMatthew G. Knepley     PetscReal lower[3]   = {0.0, 0.0, 0.0};
2273ae8bcbbbSMatthew G. Knepley     PetscReal upper[3]   = {1.0, 1.0, 1.5};
22746858538eSMatthew G. Knepley     PetscInt  numZCells  = 3;
2275006a8963SMatthew G. Knepley 
22766858538eSMatthew G. Knepley     L[2]       = upper[2] - lower[2];
22776858538eSMatthew G. Knepley     maxCell[2] = 1.1 * (L[2] / numZCells);
22784fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
2279006a8963SMatthew G. Knepley   }
2280dbc1dc17SMatthew G. Knepley   {
22819318fe57SMatthew G. Knepley     DM          cdm;
22829318fe57SMatthew G. Knepley     PetscDS     cds;
22839318fe57SMatthew G. Knepley     PetscScalar c[2] = {1.0, 1.0};
2284dbc1dc17SMatthew G. Knepley 
228549704ca5SMatthew G. Knepley     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL));
22869566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
22879566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
22889566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 2, c));
2289dbc1dc17SMatthew G. Knepley   }
229046139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
229146139095SJed Brown 
22929318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
22939566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(dm));
229449704ca5SMatthew G. Knepley 
229549704ca5SMatthew G. Knepley   char        oldprefix[PETSC_MAX_PATH_LEN];
229649704ca5SMatthew G. Knepley   const char *prefix;
229749704ca5SMatthew G. Knepley 
229849704ca5SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
229949704ca5SMatthew G. Knepley   PetscCall(PetscStrncpy(oldprefix, prefix, PETSC_MAX_PATH_LEN));
230049704ca5SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, "petsc_cyl_ref_"));
230149704ca5SMatthew G. Knepley   for (PetscInt r = 0; r < PetscMax(0, Nr); ++r) {
230249704ca5SMatthew G. Knepley     DM rdm;
230349704ca5SMatthew G. Knepley 
230449704ca5SMatthew G. Knepley     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
230549704ca5SMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &rdm));
230649704ca5SMatthew G. Knepley   }
230749704ca5SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldprefix));
230849704ca5SMatthew G. Knepley   PetscCall(DMPlexRemapGeometry(dm, 0.0, snapToCylinder));
230949704ca5SMatthew G. Knepley 
231049704ca5SMatthew G. Knepley   DMLabel         bdlabel, edgelabel;
231149704ca5SMatthew G. Knepley   IS              faceIS;
231249704ca5SMatthew G. Knepley   const PetscInt *faces;
231349704ca5SMatthew G. Knepley   PetscInt        Nf;
231449704ca5SMatthew G. Knepley 
231549704ca5SMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "marker"));
231649704ca5SMatthew G. Knepley   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
231749704ca5SMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "generatrix"));
231849704ca5SMatthew G. Knepley   PetscCall(DMGetLabel(dm, "generatrix", &edgelabel));
231949704ca5SMatthew G. Knepley   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
232049704ca5SMatthew G. Knepley   // Remove faces on top and bottom
232149704ca5SMatthew G. Knepley   PetscCall(DMLabelGetStratumIS(bdlabel, 1, &faceIS));
2322ba1b3593SJeremy L Thompson   if (faceIS) {
232349704ca5SMatthew G. Knepley     PetscCall(ISGetLocalSize(faceIS, &Nf));
232449704ca5SMatthew G. Knepley     PetscCall(ISGetIndices(faceIS, &faces));
232549704ca5SMatthew G. Knepley     for (PetscInt f = 0; f < Nf; ++f) {
232649704ca5SMatthew G. Knepley       PetscReal vol, normal[3];
232749704ca5SMatthew G. Knepley 
232849704ca5SMatthew G. Knepley       PetscCall(DMPlexComputeCellGeometryFVM(dm, faces[f], &vol, NULL, normal));
232949704ca5SMatthew G. Knepley       if (PetscAbsReal(normal[2]) < PETSC_SMALL) PetscCall(DMLabelSetValue(edgelabel, faces[f], 1));
233049704ca5SMatthew G. Knepley     }
233149704ca5SMatthew G. Knepley     PetscCall(ISRestoreIndices(faceIS, &faces));
233249704ca5SMatthew G. Knepley     PetscCall(ISDestroy(&faceIS));
2333ba1b3593SJeremy L Thompson   }
233449704ca5SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(dm, bdlabel));
233549704ca5SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(dm, edgelabel));
23363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23370510c589SMatthew G. Knepley }
23380510c589SMatthew G. Knepley 
233924119c2aSMatthew G. Knepley /*@
23409318fe57SMatthew G. Knepley   DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra.
234124119c2aSMatthew G. Knepley 
2342d083f849SBarry Smith   Collective
234324119c2aSMatthew G. Knepley 
234424119c2aSMatthew G. Knepley   Input Parameters:
2345a1cb98faSBarry Smith + comm      - The communicator for the `DM` object
234649704ca5SMatthew G. Knepley . periodicZ - The boundary type for the Z direction
234749704ca5SMatthew G. Knepley - Nr        - The number of refinements to carry out
234824119c2aSMatthew G. Knepley 
234924119c2aSMatthew G. Knepley   Output Parameter:
235020f4b53cSBarry Smith . dm - The `DM` object
235124119c2aSMatthew G. Knepley 
235224119c2aSMatthew G. Knepley   Level: beginner
235324119c2aSMatthew G. Knepley 
2354a1cb98faSBarry Smith   Note:
2355a4e35b19SJacob Faibussowitsch   Here is the output numbering looking from the bottom of the cylinder\:
2356a1cb98faSBarry Smith .vb
2357a1cb98faSBarry Smith        17-----14
2358a1cb98faSBarry Smith         |     |
2359a1cb98faSBarry Smith         |  2  |
2360a1cb98faSBarry Smith         |     |
2361a1cb98faSBarry Smith  17-----8-----7-----14
2362a1cb98faSBarry Smith   |     |     |     |
2363a1cb98faSBarry Smith   |  3  |  0  |  1  |
2364a1cb98faSBarry Smith   |     |     |     |
2365a1cb98faSBarry Smith  19-----5-----6-----13
2366a1cb98faSBarry Smith         |     |
2367a1cb98faSBarry Smith         |  4  |
2368a1cb98faSBarry Smith         |     |
2369a1cb98faSBarry Smith        19-----13
2370a1cb98faSBarry Smith 
2371a1cb98faSBarry Smith  and up through the top
2372a1cb98faSBarry Smith 
2373a1cb98faSBarry Smith        18-----16
2374a1cb98faSBarry Smith         |     |
2375a1cb98faSBarry Smith         |  2  |
2376a1cb98faSBarry Smith         |     |
2377a1cb98faSBarry Smith  18----10----11-----16
2378a1cb98faSBarry Smith   |     |     |     |
2379a1cb98faSBarry Smith   |  3  |  0  |  1  |
2380a1cb98faSBarry Smith   |     |     |     |
2381a1cb98faSBarry Smith  20-----9----12-----15
2382a1cb98faSBarry Smith         |     |
2383a1cb98faSBarry Smith         |  4  |
2384a1cb98faSBarry Smith         |     |
2385a1cb98faSBarry Smith        20-----15
2386a1cb98faSBarry Smith .ve
2387a1cb98faSBarry Smith 
23881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
238924119c2aSMatthew G. Knepley @*/
239049704ca5SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, PetscInt Nr, DM *dm)
2391d71ae5a4SJacob Faibussowitsch {
23929318fe57SMatthew G. Knepley   PetscFunctionBegin;
239349704ca5SMatthew G. Knepley   PetscAssertPointer(dm, 4);
23949566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
23959566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
239649704ca5SMatthew G. Knepley   PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ, Nr));
23973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
23989318fe57SMatthew G. Knepley }
23999318fe57SMatthew G. Knepley 
2400d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate)
2401d71ae5a4SJacob Faibussowitsch {
240224119c2aSMatthew G. Knepley   const PetscInt dim = 3;
2403412e9a14SMatthew G. Knepley   PetscInt       numCells, numVertices, v;
24049fe9f049SMatthew G. Knepley   PetscMPIInt    rank;
240524119c2aSMatthew G. Knepley 
240624119c2aSMatthew G. Knepley   PetscFunctionBegin;
240763a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n);
240846139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
24099566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
24109566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
2411412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
24129566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
241324119c2aSMatthew G. Knepley   /* Create topology */
241424119c2aSMatthew G. Knepley   {
241524119c2aSMatthew G. Knepley     PetscInt cone[6], c;
241624119c2aSMatthew G. Knepley 
2417dd400576SPatrick Sanan     numCells    = rank == 0 ? n : 0;
2418dd400576SPatrick Sanan     numVertices = rank == 0 ? 2 * (n + 1) : 0;
24199566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
24209566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
24219566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
242224119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
24239371c9d4SSatish Balay       cone[0] = c + n * 1;
24249371c9d4SSatish Balay       cone[1] = (c + 1) % n + n * 1;
24259371c9d4SSatish Balay       cone[2] = 0 + 3 * n;
24269371c9d4SSatish Balay       cone[3] = c + n * 2;
24279371c9d4SSatish Balay       cone[4] = (c + 1) % n + n * 2;
24289371c9d4SSatish Balay       cone[5] = 1 + 3 * n;
24299566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(dm, c, cone));
24309566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR));
243124119c2aSMatthew G. Knepley     }
24329566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
24339566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
243424119c2aSMatthew G. Knepley   }
243548a46eb9SPierre Jolivet   for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT));
243624119c2aSMatthew G. Knepley   /* Create cylinder geometry */
243724119c2aSMatthew G. Knepley   {
243824119c2aSMatthew G. Knepley     Vec          coordinates;
243924119c2aSMatthew G. Knepley     PetscSection coordSection;
244024119c2aSMatthew G. Knepley     PetscScalar *coords;
2441412e9a14SMatthew G. Knepley     PetscInt     coordSize, c;
244224119c2aSMatthew G. Knepley 
244324119c2aSMatthew G. Knepley     /* Build coordinates */
24449566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
24459566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
24469566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
24479566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
244824119c2aSMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
24499566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
24509566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
245124119c2aSMatthew G. Knepley     }
24529566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
24539566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
24549566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
24559566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
24569566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
24579566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
24589566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
24599566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
246024119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
24619371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
24629371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
24639371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 2] = 1.0;
24649371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
24659371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
24669371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 2] = 0.0;
246724119c2aSMatthew G. Knepley     }
2468dd400576SPatrick Sanan     if (rank == 0) {
24699371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 0] = 0.0;
24709371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 1] = 0.0;
24719371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 2] = 1.0;
24729371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 0] = 0.0;
24739371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 1] = 0.0;
24749371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 2] = 0.0;
24759fe9f049SMatthew G. Knepley     }
24769566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
24779566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
24789566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
247924119c2aSMatthew G. Knepley   }
248046139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
24819318fe57SMatthew G. Knepley   /* Interpolate */
24829566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
24833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
24849318fe57SMatthew G. Knepley }
24859318fe57SMatthew G. Knepley 
24869318fe57SMatthew G. Knepley /*@
24879318fe57SMatthew G. Knepley   DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges.
24889318fe57SMatthew G. Knepley 
24899318fe57SMatthew G. Knepley   Collective
24909318fe57SMatthew G. Knepley 
24919318fe57SMatthew G. Knepley   Input Parameters:
2492a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
24939318fe57SMatthew G. Knepley . n           - The number of wedges around the origin
24949318fe57SMatthew G. Knepley - interpolate - Create edges and faces
24959318fe57SMatthew G. Knepley 
24969318fe57SMatthew G. Knepley   Output Parameter:
2497a1cb98faSBarry Smith . dm - The `DM` object
24989318fe57SMatthew G. Knepley 
24999318fe57SMatthew G. Knepley   Level: beginner
25009318fe57SMatthew G. Knepley 
25011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
25029318fe57SMatthew G. Knepley @*/
2503d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm)
2504d71ae5a4SJacob Faibussowitsch {
25059318fe57SMatthew G. Knepley   PetscFunctionBegin;
25064f572ea9SToby Isaac   PetscAssertPointer(dm, 4);
25079566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
25089566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
25099566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate));
25103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
251124119c2aSMatthew G. Knepley }
251224119c2aSMatthew G. Knepley 
2513d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2514d71ae5a4SJacob Faibussowitsch {
251565a81367SMatthew G. Knepley   PetscReal prod = 0.0;
251665a81367SMatthew G. Knepley   PetscInt  i;
251765a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]);
251865a81367SMatthew G. Knepley   return PetscSqrtReal(prod);
251965a81367SMatthew G. Knepley }
2520dd2b43ebSStefano Zampini 
2521d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2522d71ae5a4SJacob Faibussowitsch {
252365a81367SMatthew G. Knepley   PetscReal prod = 0.0;
252465a81367SMatthew G. Knepley   PetscInt  i;
252565a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += x[i] * y[i];
252665a81367SMatthew G. Knepley   return prod;
252765a81367SMatthew G. Knepley }
252865a81367SMatthew G. Knepley 
252951a74b61SMatthew G. Knepley /* The first constant is the sphere radius */
2530d71ae5a4SJacob 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[])
2531d71ae5a4SJacob Faibussowitsch {
253251a74b61SMatthew G. Knepley   PetscReal r     = PetscRealPart(constants[0]);
253351a74b61SMatthew G. Knepley   PetscReal norm2 = 0.0, fac;
253451a74b61SMatthew G. Knepley   PetscInt  n     = uOff[1] - uOff[0], d;
253551a74b61SMatthew G. Knepley 
253651a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d]));
253751a74b61SMatthew G. Knepley   fac = r / PetscSqrtReal(norm2);
253851a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) f0[d] = u[d] * fac;
253951a74b61SMatthew G. Knepley }
254051a74b61SMatthew G. Knepley 
2541d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R)
2542d71ae5a4SJacob Faibussowitsch {
254365a81367SMatthew G. Knepley   const PetscInt embedDim = dim + 1;
254465a81367SMatthew G. Knepley   PetscSection   coordSection;
254565a81367SMatthew G. Knepley   Vec            coordinates;
254665a81367SMatthew G. Knepley   PetscScalar   *coords;
254765a81367SMatthew G. Knepley   PetscReal     *coordsIn;
254807c565c5SJose E. Roman   PetscInt       numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, e;
254965a81367SMatthew G. Knepley   PetscMPIInt    rank;
255065a81367SMatthew G. Knepley 
255165a81367SMatthew G. Knepley   PetscFunctionBegin;
25529318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, simplex, 3);
255346139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
25549566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
25559566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim + 1));
25569566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
255765a81367SMatthew G. Knepley   switch (dim) {
25585c344501SMatthew G. Knepley   case 1:
25595c344501SMatthew G. Knepley     numCells = 16;
25605c344501SMatthew G. Knepley     numVerts = numCells;
25615c344501SMatthew G. Knepley 
25625c344501SMatthew G. Knepley     // Build Topology
25635c344501SMatthew G. Knepley     PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
25645c344501SMatthew G. Knepley     for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
25655c344501SMatthew G. Knepley     PetscCall(DMSetUp(dm));
25665c344501SMatthew G. Knepley     for (PetscInt c = 0; c < numCells; ++c) {
25675c344501SMatthew G. Knepley       PetscInt cone[2];
25685c344501SMatthew G. Knepley 
25695c344501SMatthew G. Knepley       cone[0] = c + numCells;
25705c344501SMatthew G. Knepley       cone[1] = (c + 1) % numVerts + numCells;
25715c344501SMatthew G. Knepley       PetscCall(DMPlexSetCone(dm, c, cone));
25725c344501SMatthew G. Knepley     }
25735c344501SMatthew G. Knepley     PetscCall(DMPlexSymmetrize(dm));
25745c344501SMatthew G. Knepley     PetscCall(DMPlexStratify(dm));
25755c344501SMatthew G. Knepley     PetscCall(PetscMalloc1(numVerts * embedDim, &coordsIn));
25765c344501SMatthew G. Knepley     for (PetscInt v = 0; v < numVerts; ++v) {
25775c344501SMatthew G. Knepley       const PetscReal rad = 2. * PETSC_PI * v / numVerts;
25785c344501SMatthew G. Knepley 
25795c344501SMatthew G. Knepley       coordsIn[v * embedDim + 0] = PetscCosReal(rad);
25805c344501SMatthew G. Knepley       coordsIn[v * embedDim + 1] = PetscSinReal(rad);
25815c344501SMatthew G. Knepley     }
25825c344501SMatthew G. Knepley     break;
258365a81367SMatthew G. Knepley   case 2:
258465a81367SMatthew G. Knepley     if (simplex) {
258551a74b61SMatthew G. Knepley       const PetscReal radius    = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI);
258651a74b61SMatthew G. Knepley       const PetscReal edgeLen   = 2.0 / (1.0 + PETSC_PHI) * (R / radius);
258765a81367SMatthew G. Knepley       const PetscInt  degree    = 5;
258851a74b61SMatthew G. Knepley       PetscReal       vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)};
258965a81367SMatthew G. Knepley       PetscInt        s[3]      = {1, 1, 1};
259065a81367SMatthew G. Knepley       PetscInt        cone[3];
259107c565c5SJose E. Roman       PetscInt       *graph;
259265a81367SMatthew G. Knepley 
25939371c9d4SSatish Balay       vertex[0] *= R / radius;
25949371c9d4SSatish Balay       vertex[1] *= R / radius;
25959371c9d4SSatish Balay       vertex[2] *= R / radius;
2596dd400576SPatrick Sanan       numCells    = rank == 0 ? 20 : 0;
2597dd400576SPatrick Sanan       numVerts    = rank == 0 ? 12 : 0;
259865a81367SMatthew G. Knepley       firstVertex = numCells;
259951a74b61SMatthew G. Knepley       /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of
260065a81367SMatthew G. Knepley 
260165a81367SMatthew G. Knepley            (0, \pm 1/\phi+1, \pm \phi/\phi+1)
260265a81367SMatthew G. Knepley 
260365a81367SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
260451a74b61SMatthew G. Knepley          length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393.
260565a81367SMatthew G. Knepley       */
260665a81367SMatthew G. Knepley       /* Construct vertices */
26079566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2608dd400576SPatrick Sanan       if (rank == 0) {
260907c565c5SJose E. Roman         for (PetscInt p = 0, i = 0; p < embedDim; ++p) {
261065a81367SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
261165a81367SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
261265a81367SMatthew G. Knepley               for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim];
261365a81367SMatthew G. Knepley               ++i;
261465a81367SMatthew G. Knepley             }
261565a81367SMatthew G. Knepley           }
261665a81367SMatthew G. Knepley         }
261745da822fSValeria Barra       }
261865a81367SMatthew G. Knepley       /* Construct graph */
26199566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
262007c565c5SJose E. Roman       for (PetscInt i = 0; i < numVerts; ++i) {
262107c565c5SJose E. Roman         PetscInt k = 0;
262207c565c5SJose E. Roman         for (PetscInt j = 0; j < numVerts; ++j) {
26239371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
26249371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
26259371c9d4SSatish Balay             ++k;
26269371c9d4SSatish Balay           }
262765a81367SMatthew G. Knepley         }
262863a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
262965a81367SMatthew G. Knepley       }
263065a81367SMatthew G. Knepley       /* Build Topology */
26319566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
263207c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
26339566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
263465a81367SMatthew G. Knepley       /* Cells */
263507c565c5SJose E. Roman       for (PetscInt i = 0, c = 0; i < numVerts; ++i) {
263607c565c5SJose E. Roman         for (PetscInt j = 0; j < i; ++j) {
263707c565c5SJose E. Roman           for (PetscInt k = 0; k < j; ++k) {
263865a81367SMatthew G. Knepley             if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) {
26399371c9d4SSatish Balay               cone[0] = firstVertex + i;
26409371c9d4SSatish Balay               cone[1] = firstVertex + j;
26419371c9d4SSatish Balay               cone[2] = firstVertex + k;
264265a81367SMatthew G. Knepley               /* Check orientation */
264365a81367SMatthew G. Knepley               {
26449371c9d4SSatish Balay                 const PetscInt epsilon[3][3][3] = {
26459371c9d4SSatish Balay                   {{0, 0, 0},  {0, 0, 1},  {0, -1, 0}},
26469371c9d4SSatish Balay                   {{0, 0, -1}, {0, 0, 0},  {1, 0, 0} },
26479371c9d4SSatish Balay                   {{0, 1, 0},  {-1, 0, 0}, {0, 0, 0} }
26489371c9d4SSatish Balay                 };
264965a81367SMatthew G. Knepley                 PetscReal normal[3];
265065a81367SMatthew G. Knepley                 PetscInt  e, f;
265165a81367SMatthew G. Knepley 
265265a81367SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) {
265365a81367SMatthew G. Knepley                   normal[d] = 0.0;
265465a81367SMatthew G. Knepley                   for (e = 0; e < embedDim; ++e) {
2655ad540459SPierre 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]);
265665a81367SMatthew G. Knepley                   }
265765a81367SMatthew G. Knepley                 }
26589371c9d4SSatish Balay                 if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
26599371c9d4SSatish Balay                   PetscInt tmp = cone[1];
26609371c9d4SSatish Balay                   cone[1]      = cone[2];
26619371c9d4SSatish Balay                   cone[2]      = tmp;
266265a81367SMatthew G. Knepley                 }
266365a81367SMatthew G. Knepley               }
26649566063dSJacob Faibussowitsch               PetscCall(DMPlexSetCone(dm, c++, cone));
266565a81367SMatthew G. Knepley             }
266665a81367SMatthew G. Knepley           }
266765a81367SMatthew G. Knepley         }
266865a81367SMatthew G. Knepley       }
26699566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
26709566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
26719566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
267265a81367SMatthew G. Knepley     } else {
26732829fed8SMatthew G. Knepley       /*
26742829fed8SMatthew G. Knepley         12-21--13
26752829fed8SMatthew G. Knepley          |     |
26762829fed8SMatthew G. Knepley         25  4  24
26772829fed8SMatthew G. Knepley          |     |
26782829fed8SMatthew G. Knepley   12-25--9-16--8-24--13
26792829fed8SMatthew G. Knepley    |     |     |     |
26802829fed8SMatthew G. Knepley   23  5 17  0 15  3  22
26812829fed8SMatthew G. Knepley    |     |     |     |
26822829fed8SMatthew G. Knepley   10-20--6-14--7-19--11
26832829fed8SMatthew G. Knepley          |     |
26842829fed8SMatthew G. Knepley         20  1  19
26852829fed8SMatthew G. Knepley          |     |
26862829fed8SMatthew G. Knepley         10-18--11
26872829fed8SMatthew G. Knepley          |     |
26882829fed8SMatthew G. Knepley         23  2  22
26892829fed8SMatthew G. Knepley          |     |
26902829fed8SMatthew G. Knepley         12-21--13
26912829fed8SMatthew G. Knepley        */
26922829fed8SMatthew G. Knepley       PetscInt cone[4], ornt[4];
26932829fed8SMatthew G. Knepley 
2694dd400576SPatrick Sanan       numCells    = rank == 0 ? 6 : 0;
2695dd400576SPatrick Sanan       numEdges    = rank == 0 ? 12 : 0;
2696dd400576SPatrick Sanan       numVerts    = rank == 0 ? 8 : 0;
269765a81367SMatthew G. Knepley       firstVertex = numCells;
269865a81367SMatthew G. Knepley       firstEdge   = numCells + numVerts;
26992829fed8SMatthew G. Knepley       /* Build Topology */
27009566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts));
270107c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4));
270248a46eb9SPierre Jolivet       for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
27039566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2704dd400576SPatrick Sanan       if (rank == 0) {
27052829fed8SMatthew G. Knepley         /* Cell 0 */
27069371c9d4SSatish Balay         cone[0] = 14;
27079371c9d4SSatish Balay         cone[1] = 15;
27089371c9d4SSatish Balay         cone[2] = 16;
27099371c9d4SSatish Balay         cone[3] = 17;
27109566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
27119371c9d4SSatish Balay         ornt[0] = 0;
27129371c9d4SSatish Balay         ornt[1] = 0;
27139371c9d4SSatish Balay         ornt[2] = 0;
27149371c9d4SSatish Balay         ornt[3] = 0;
27159566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 0, ornt));
27162829fed8SMatthew G. Knepley         /* Cell 1 */
27179371c9d4SSatish Balay         cone[0] = 18;
27189371c9d4SSatish Balay         cone[1] = 19;
27199371c9d4SSatish Balay         cone[2] = 14;
27209371c9d4SSatish Balay         cone[3] = 20;
27219566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
27229371c9d4SSatish Balay         ornt[0] = 0;
27239371c9d4SSatish Balay         ornt[1] = 0;
27249371c9d4SSatish Balay         ornt[2] = -1;
27259371c9d4SSatish Balay         ornt[3] = 0;
27269566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 1, ornt));
27272829fed8SMatthew G. Knepley         /* Cell 2 */
27289371c9d4SSatish Balay         cone[0] = 21;
27299371c9d4SSatish Balay         cone[1] = 22;
27309371c9d4SSatish Balay         cone[2] = 18;
27319371c9d4SSatish Balay         cone[3] = 23;
27329566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
27339371c9d4SSatish Balay         ornt[0] = 0;
27349371c9d4SSatish Balay         ornt[1] = 0;
27359371c9d4SSatish Balay         ornt[2] = -1;
27369371c9d4SSatish Balay         ornt[3] = 0;
27379566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 2, ornt));
27382829fed8SMatthew G. Knepley         /* Cell 3 */
27399371c9d4SSatish Balay         cone[0] = 19;
27409371c9d4SSatish Balay         cone[1] = 22;
27419371c9d4SSatish Balay         cone[2] = 24;
27429371c9d4SSatish Balay         cone[3] = 15;
27439566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
27449371c9d4SSatish Balay         ornt[0] = -1;
27459371c9d4SSatish Balay         ornt[1] = -1;
27469371c9d4SSatish Balay         ornt[2] = 0;
27479371c9d4SSatish Balay         ornt[3] = -1;
27489566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 3, ornt));
27492829fed8SMatthew G. Knepley         /* Cell 4 */
27509371c9d4SSatish Balay         cone[0] = 16;
27519371c9d4SSatish Balay         cone[1] = 24;
27529371c9d4SSatish Balay         cone[2] = 21;
27539371c9d4SSatish Balay         cone[3] = 25;
27549566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
27559371c9d4SSatish Balay         ornt[0] = -1;
27569371c9d4SSatish Balay         ornt[1] = -1;
27579371c9d4SSatish Balay         ornt[2] = -1;
27589371c9d4SSatish Balay         ornt[3] = 0;
27599566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 4, ornt));
27602829fed8SMatthew G. Knepley         /* Cell 5 */
27619371c9d4SSatish Balay         cone[0] = 20;
27629371c9d4SSatish Balay         cone[1] = 17;
27639371c9d4SSatish Balay         cone[2] = 25;
27649371c9d4SSatish Balay         cone[3] = 23;
27659566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
27669371c9d4SSatish Balay         ornt[0] = -1;
27679371c9d4SSatish Balay         ornt[1] = -1;
27689371c9d4SSatish Balay         ornt[2] = -1;
27699371c9d4SSatish Balay         ornt[3] = -1;
27709566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 5, ornt));
27712829fed8SMatthew G. Knepley         /* Edges */
27729371c9d4SSatish Balay         cone[0] = 6;
27739371c9d4SSatish Balay         cone[1] = 7;
27749566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
27759371c9d4SSatish Balay         cone[0] = 7;
27769371c9d4SSatish Balay         cone[1] = 8;
27779566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 15, cone));
27789371c9d4SSatish Balay         cone[0] = 8;
27799371c9d4SSatish Balay         cone[1] = 9;
27809566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 16, cone));
27819371c9d4SSatish Balay         cone[0] = 9;
27829371c9d4SSatish Balay         cone[1] = 6;
27839566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 17, cone));
27849371c9d4SSatish Balay         cone[0] = 10;
27859371c9d4SSatish Balay         cone[1] = 11;
27869566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 18, cone));
27879371c9d4SSatish Balay         cone[0] = 11;
27889371c9d4SSatish Balay         cone[1] = 7;
27899566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 19, cone));
27909371c9d4SSatish Balay         cone[0] = 6;
27919371c9d4SSatish Balay         cone[1] = 10;
27929566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 20, cone));
27939371c9d4SSatish Balay         cone[0] = 12;
27949371c9d4SSatish Balay         cone[1] = 13;
27959566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 21, cone));
27969371c9d4SSatish Balay         cone[0] = 13;
27979371c9d4SSatish Balay         cone[1] = 11;
27989566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 22, cone));
27999371c9d4SSatish Balay         cone[0] = 10;
28009371c9d4SSatish Balay         cone[1] = 12;
28019566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 23, cone));
28029371c9d4SSatish Balay         cone[0] = 13;
28039371c9d4SSatish Balay         cone[1] = 8;
28049566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 24, cone));
28059371c9d4SSatish Balay         cone[0] = 12;
28069371c9d4SSatish Balay         cone[1] = 9;
28079566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 25, cone));
280845da822fSValeria Barra       }
28099566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
28109566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
28112829fed8SMatthew G. Knepley       /* Build coordinates */
28129566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2813dd400576SPatrick Sanan       if (rank == 0) {
28149371c9d4SSatish Balay         coordsIn[0 * embedDim + 0] = -R;
28159371c9d4SSatish Balay         coordsIn[0 * embedDim + 1] = R;
28169371c9d4SSatish Balay         coordsIn[0 * embedDim + 2] = -R;
28179371c9d4SSatish Balay         coordsIn[1 * embedDim + 0] = R;
28189371c9d4SSatish Balay         coordsIn[1 * embedDim + 1] = R;
28199371c9d4SSatish Balay         coordsIn[1 * embedDim + 2] = -R;
28209371c9d4SSatish Balay         coordsIn[2 * embedDim + 0] = R;
28219371c9d4SSatish Balay         coordsIn[2 * embedDim + 1] = -R;
28229371c9d4SSatish Balay         coordsIn[2 * embedDim + 2] = -R;
28239371c9d4SSatish Balay         coordsIn[3 * embedDim + 0] = -R;
28249371c9d4SSatish Balay         coordsIn[3 * embedDim + 1] = -R;
28259371c9d4SSatish Balay         coordsIn[3 * embedDim + 2] = -R;
28269371c9d4SSatish Balay         coordsIn[4 * embedDim + 0] = -R;
28279371c9d4SSatish Balay         coordsIn[4 * embedDim + 1] = R;
28289371c9d4SSatish Balay         coordsIn[4 * embedDim + 2] = R;
28299371c9d4SSatish Balay         coordsIn[5 * embedDim + 0] = R;
28309371c9d4SSatish Balay         coordsIn[5 * embedDim + 1] = R;
28319371c9d4SSatish Balay         coordsIn[5 * embedDim + 2] = R;
28329371c9d4SSatish Balay         coordsIn[6 * embedDim + 0] = -R;
28339371c9d4SSatish Balay         coordsIn[6 * embedDim + 1] = -R;
28349371c9d4SSatish Balay         coordsIn[6 * embedDim + 2] = R;
28359371c9d4SSatish Balay         coordsIn[7 * embedDim + 0] = R;
28369371c9d4SSatish Balay         coordsIn[7 * embedDim + 1] = -R;
28379371c9d4SSatish Balay         coordsIn[7 * embedDim + 2] = R;
283865a81367SMatthew G. Knepley       }
283945da822fSValeria Barra     }
284065a81367SMatthew G. Knepley     break;
284165a81367SMatthew G. Knepley   case 3:
2842116ded15SMatthew G. Knepley     if (simplex) {
2843116ded15SMatthew G. Knepley       const PetscReal edgeLen         = 1.0 / PETSC_PHI;
284451a74b61SMatthew G. Knepley       PetscReal       vertexA[4]      = {0.5, 0.5, 0.5, 0.5};
284551a74b61SMatthew G. Knepley       PetscReal       vertexB[4]      = {1.0, 0.0, 0.0, 0.0};
284651a74b61SMatthew G. Knepley       PetscReal       vertexC[4]      = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0};
2847116ded15SMatthew G. Knepley       const PetscInt  degree          = 12;
2848116ded15SMatthew G. Knepley       PetscInt        s[4]            = {1, 1, 1};
28499371c9d4SSatish Balay       PetscInt        evenPerm[12][4] = {
28509371c9d4SSatish Balay         {0, 1, 2, 3},
28519371c9d4SSatish Balay         {0, 2, 3, 1},
28529371c9d4SSatish Balay         {0, 3, 1, 2},
28539371c9d4SSatish Balay         {1, 0, 3, 2},
28549371c9d4SSatish Balay         {1, 2, 0, 3},
28559371c9d4SSatish Balay         {1, 3, 2, 0},
28569371c9d4SSatish Balay         {2, 0, 1, 3},
28579371c9d4SSatish Balay         {2, 1, 3, 0},
28589371c9d4SSatish Balay         {2, 3, 0, 1},
28599371c9d4SSatish Balay         {3, 0, 2, 1},
28609371c9d4SSatish Balay         {3, 1, 0, 2},
28619371c9d4SSatish Balay         {3, 2, 1, 0}
28629371c9d4SSatish Balay       };
2863116ded15SMatthew G. Knepley       PetscInt  cone[4];
2864116ded15SMatthew G. Knepley       PetscInt *graph, p, i, j, k, l;
2865116ded15SMatthew G. Knepley 
28669371c9d4SSatish Balay       vertexA[0] *= R;
28679371c9d4SSatish Balay       vertexA[1] *= R;
28689371c9d4SSatish Balay       vertexA[2] *= R;
28699371c9d4SSatish Balay       vertexA[3] *= R;
28709371c9d4SSatish Balay       vertexB[0] *= R;
28719371c9d4SSatish Balay       vertexB[1] *= R;
28729371c9d4SSatish Balay       vertexB[2] *= R;
28739371c9d4SSatish Balay       vertexB[3] *= R;
28749371c9d4SSatish Balay       vertexC[0] *= R;
28759371c9d4SSatish Balay       vertexC[1] *= R;
28769371c9d4SSatish Balay       vertexC[2] *= R;
28779371c9d4SSatish Balay       vertexC[3] *= R;
2878dd400576SPatrick Sanan       numCells    = rank == 0 ? 600 : 0;
2879dd400576SPatrick Sanan       numVerts    = rank == 0 ? 120 : 0;
2880116ded15SMatthew G. Knepley       firstVertex = numCells;
2881116ded15SMatthew G. Knepley       /* Use the 600-cell, which for a unit sphere has coordinates which are
2882116ded15SMatthew G. Knepley 
2883116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm 1,    \pm 1, \pm 1)                          16
2884116ded15SMatthew G. Knepley                (\pm 1,    0,       0,      0)  all cyclic permutations   8
2885116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm phi, \pm 1/phi, 0)  all even permutations    96
2886116ded15SMatthew G. Knepley 
2887116ded15SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
28886333ae4fSvaleriabarra          length is then given by 1/\phi = 0.61803.
2889116ded15SMatthew G. Knepley 
2890116ded15SMatthew G. Knepley          http://buzzard.pugetsound.edu/sage-practice/ch03s03.html
2891116ded15SMatthew G. Knepley          http://mathworld.wolfram.com/600-Cell.html
2892116ded15SMatthew G. Knepley       */
2893116ded15SMatthew G. Knepley       /* Construct vertices */
28949566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
2895116ded15SMatthew G. Knepley       i = 0;
2896dd400576SPatrick Sanan       if (rank == 0) {
2897116ded15SMatthew G. Knepley         for (s[0] = -1; s[0] < 2; s[0] += 2) {
2898116ded15SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
2899116ded15SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
2900116ded15SMatthew G. Knepley               for (s[3] = -1; s[3] < 2; s[3] += 2) {
2901116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d];
2902116ded15SMatthew G. Knepley                 ++i;
2903116ded15SMatthew G. Knepley               }
2904116ded15SMatthew G. Knepley             }
2905116ded15SMatthew G. Knepley           }
2906116ded15SMatthew G. Knepley         }
2907116ded15SMatthew G. Knepley         for (p = 0; p < embedDim; ++p) {
2908116ded15SMatthew G. Knepley           s[1] = s[2] = s[3] = 1;
2909116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2910116ded15SMatthew G. Knepley             for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim];
2911116ded15SMatthew G. Knepley             ++i;
2912116ded15SMatthew G. Knepley           }
2913116ded15SMatthew G. Knepley         }
2914116ded15SMatthew G. Knepley         for (p = 0; p < 12; ++p) {
2915116ded15SMatthew G. Knepley           s[3] = 1;
2916116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
2917116ded15SMatthew G. Knepley             for (s[1] = -1; s[1] < 2; s[1] += 2) {
2918116ded15SMatthew G. Knepley               for (s[2] = -1; s[2] < 2; s[2] += 2) {
2919116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]];
2920116ded15SMatthew G. Knepley                 ++i;
2921116ded15SMatthew G. Knepley               }
2922116ded15SMatthew G. Knepley             }
2923116ded15SMatthew G. Knepley           }
2924116ded15SMatthew G. Knepley         }
292545da822fSValeria Barra       }
292663a3b9bcSJacob Faibussowitsch       PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts);
2927116ded15SMatthew G. Knepley       /* Construct graph */
29289566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
2929116ded15SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
2930116ded15SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
29319371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
29329371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
29339371c9d4SSatish Balay             ++k;
29349371c9d4SSatish Balay           }
2935116ded15SMatthew G. Knepley         }
293663a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
2937116ded15SMatthew G. Knepley       }
2938116ded15SMatthew G. Knepley       /* Build Topology */
29399566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
294007c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
29419566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
2942116ded15SMatthew G. Knepley       /* Cells */
2943dd400576SPatrick Sanan       if (rank == 0) {
294407c565c5SJose E. Roman         for (PetscInt i = 0, c = 0; i < numVerts; ++i) {
2945116ded15SMatthew G. Knepley           for (j = 0; j < i; ++j) {
2946116ded15SMatthew G. Knepley             for (k = 0; k < j; ++k) {
2947116ded15SMatthew G. Knepley               for (l = 0; l < k; ++l) {
29489371c9d4SSatish 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]) {
29499371c9d4SSatish Balay                   cone[0] = firstVertex + i;
29509371c9d4SSatish Balay                   cone[1] = firstVertex + j;
29519371c9d4SSatish Balay                   cone[2] = firstVertex + k;
29529371c9d4SSatish Balay                   cone[3] = firstVertex + l;
2953116ded15SMatthew G. Knepley                   /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */
2954116ded15SMatthew G. Knepley                   {
29559371c9d4SSatish Balay                     const PetscInt epsilon[4][4][4][4] = {
29569371c9d4SSatish 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}}},
2957116ded15SMatthew G. Knepley 
29589371c9d4SSatish 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}}},
2959116ded15SMatthew G. Knepley 
29609371c9d4SSatish 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}}},
2961116ded15SMatthew G. Knepley 
29629371c9d4SSatish 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}} }
29639371c9d4SSatish Balay                     };
2964116ded15SMatthew G. Knepley                     PetscReal normal[4];
2965116ded15SMatthew G. Knepley                     PetscInt  e, f, g;
2966116ded15SMatthew G. Knepley 
2967116ded15SMatthew G. Knepley                     for (d = 0; d < embedDim; ++d) {
2968116ded15SMatthew G. Knepley                       normal[d] = 0.0;
2969116ded15SMatthew G. Knepley                       for (e = 0; e < embedDim; ++e) {
2970116ded15SMatthew G. Knepley                         for (f = 0; f < embedDim; ++f) {
2971116ded15SMatthew G. Knepley                           for (g = 0; g < embedDim; ++g) {
2972116ded15SMatthew 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]);
2973116ded15SMatthew G. Knepley                           }
2974116ded15SMatthew G. Knepley                         }
2975116ded15SMatthew G. Knepley                       }
2976116ded15SMatthew G. Knepley                     }
29779371c9d4SSatish Balay                     if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
29789371c9d4SSatish Balay                       PetscInt tmp = cone[1];
29799371c9d4SSatish Balay                       cone[1]      = cone[2];
29809371c9d4SSatish Balay                       cone[2]      = tmp;
29819371c9d4SSatish Balay                     }
2982116ded15SMatthew G. Knepley                   }
29839566063dSJacob Faibussowitsch                   PetscCall(DMPlexSetCone(dm, c++, cone));
2984116ded15SMatthew G. Knepley                 }
2985116ded15SMatthew G. Knepley               }
2986116ded15SMatthew G. Knepley             }
2987116ded15SMatthew G. Knepley           }
2988116ded15SMatthew G. Knepley         }
298945da822fSValeria Barra       }
29909566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
29919566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
29929566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
2993116ded15SMatthew G. Knepley     }
2994f4d061e9SPierre Jolivet     break;
2995d71ae5a4SJacob Faibussowitsch   default:
2996d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim);
299765a81367SMatthew G. Knepley   }
299865a81367SMatthew G. Knepley   /* Create coordinates */
29999566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
30009566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
30019566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim));
30029566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts));
30032829fed8SMatthew G. Knepley   for (v = firstVertex; v < firstVertex + numVerts; ++v) {
30049566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, embedDim));
30059566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim));
30062829fed8SMatthew G. Knepley   }
30079566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
30089566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
30099566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
30109566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, embedDim));
30119566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
30129566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
30139566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
30149566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
30159371c9d4SSatish Balay   for (v = 0; v < numVerts; ++v)
3016ad540459SPierre Jolivet     for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d];
30179566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
30189566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
30199566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
30209566063dSJacob Faibussowitsch   PetscCall(PetscFree(coordsIn));
302151a74b61SMatthew G. Knepley   {
302251a74b61SMatthew G. Knepley     DM          cdm;
302351a74b61SMatthew G. Knepley     PetscDS     cds;
30249318fe57SMatthew G. Knepley     PetscScalar c = R;
302551a74b61SMatthew G. Knepley 
3026e44f6aebSMatthew G. Knepley     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, snapToSphere));
30279566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
30289566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
30299566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 1, &c));
303051a74b61SMatthew G. Knepley   }
303146139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
30329318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
30339566063dSJacob Faibussowitsch   if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
30343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30359318fe57SMatthew G. Knepley }
30369318fe57SMatthew G. Knepley 
3037b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]);
3038b7f5c055SJed Brown 
3039b7f5c055SJed Brown /*
3040b7f5c055SJed Brown  The Schwarz P implicit surface is
3041b7f5c055SJed Brown 
3042b7f5c055SJed Brown      f(x) = cos(x0) + cos(x1) + cos(x2) = 0
3043b7f5c055SJed Brown */
3044d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
3045d71ae5a4SJacob Faibussowitsch {
3046b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)};
3047b7f5c055SJed Brown   PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)};
3048b7f5c055SJed Brown   f[0]           = c[0] + c[1] + c[2];
3049b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
3050b7f5c055SJed Brown     grad[i] = PETSC_PI * g[i];
3051ad540459SPierre Jolivet     for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.;
3052b7f5c055SJed Brown   }
3053b7f5c055SJed Brown }
3054b7f5c055SJed Brown 
30554663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
3056d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
3057d71ae5a4SJacob Faibussowitsch {
3058ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI);
30593ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
30604663dae6SJed Brown }
30614663dae6SJed Brown 
3062b7f5c055SJed Brown /*
3063b7f5c055SJed Brown  The Gyroid implicit surface is
3064b7f5c055SJed Brown 
3065b7f5c055SJed 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)
3066b7f5c055SJed Brown 
3067b7f5c055SJed Brown */
3068d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
3069d71ae5a4SJacob Faibussowitsch {
3070b7f5c055SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))};
3071b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))};
3072b7f5c055SJed Brown   f[0]           = s[0] * c[1] + s[1] * c[2] + s[2] * c[0];
3073b7f5c055SJed Brown   grad[0]        = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
3074b7f5c055SJed Brown   grad[1]        = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
3075b7f5c055SJed Brown   grad[2]        = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
3076b7f5c055SJed Brown   hess[0][0]     = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]);
3077b7f5c055SJed Brown   hess[0][1]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
3078b7f5c055SJed Brown   hess[0][2]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
3079b7f5c055SJed Brown   hess[1][0]     = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]);
3080b7f5c055SJed Brown   hess[1][1]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
3081b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
3082b7f5c055SJed Brown   hess[2][0]     = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]);
3083b7f5c055SJed Brown   hess[2][1]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
3084b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
3085b7f5c055SJed Brown }
3086b7f5c055SJed Brown 
30874663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
3088d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
3089d71ae5a4SJacob Faibussowitsch {
30904663dae6SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))};
30914663dae6SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))};
30924663dae6SJed Brown   u[0]           = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
30934663dae6SJed Brown   u[1]           = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
30944663dae6SJed Brown   u[2]           = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
30953ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
30964663dae6SJed Brown }
30974663dae6SJed Brown 
3098b7f5c055SJed Brown /*
3099b7f5c055SJed Brown    We wish to solve
3100b7f5c055SJed Brown 
3101b7f5c055SJed Brown          min_y || y - x ||^2  subject to f(y) = 0
3102b7f5c055SJed Brown 
3103b7f5c055SJed Brown    Let g(y) = grad(f).  The minimization problem is equivalent to asking to satisfy
3104b7f5c055SJed 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
3105b7f5c055SJed Brown    tangent space and ask for both components in the tangent space to be zero.
3106b7f5c055SJed Brown 
3107b7f5c055SJed Brown    Take g to be a column vector and compute the "full QR" factorization Q R = g,
3108b7f5c055SJed Brown    where Q = I - 2 n n^T is a symmetric orthogonal matrix.
3109b7f5c055SJed Brown    The first column of Q is parallel to g so the remaining two columns span the null space.
3110b7f5c055SJed Brown    Let Qn = Q[:,1:] be those remaining columns.  Then Qn Qn^T is an orthogonal projector into the tangent space.
3111da81f932SPierre Jolivet    Since Q is symmetric, this is equivalent to multiplying by Q and taking the last two entries.
3112b7f5c055SJed Brown    In total, we have a system of 3 equations in 3 unknowns:
3113b7f5c055SJed Brown 
3114b7f5c055SJed Brown      f(y) = 0                       1 equation
3115b7f5c055SJed Brown      Qn^T (y - x) = 0               2 equations
3116b7f5c055SJed Brown 
3117b7f5c055SJed Brown    Here, we compute the residual and Jacobian of this system.
3118b7f5c055SJed Brown */
3119d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[])
3120d71ae5a4SJacob Faibussowitsch {
3121b7f5c055SJed Brown   PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])};
3122b7f5c055SJed Brown   PetscReal d[3]     = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])};
31232f0490c0SSatish Balay   PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign;
31249371c9d4SSatish Balay   PetscReal n_y[3][3] = {
31259371c9d4SSatish Balay     {0, 0, 0},
31269371c9d4SSatish Balay     {0, 0, 0},
31279371c9d4SSatish Balay     {0, 0, 0}
31289371c9d4SSatish Balay   };
3129b7f5c055SJed Brown 
3130b7f5c055SJed Brown   feval(yreal, &f, grad, n_y);
3131b7f5c055SJed Brown 
3132b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n[i] = grad[i];
3133b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
3134ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i];
3135b7f5c055SJed Brown 
3136b7f5c055SJed Brown   // Define the Householder reflector
3137b7f5c055SJed Brown   sign = n[0] >= 0 ? 1. : -1.;
3138b7f5c055SJed Brown   n[0] += norm * sign;
3139b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign;
3140b7f5c055SJed Brown 
3141b7f5c055SJed Brown   norm      = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
3142b7f5c055SJed Brown   norm_y[0] = 1. / norm * (n[0] * n_y[0][0]);
3143b7f5c055SJed Brown   norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]);
3144b7f5c055SJed Brown   norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]);
3145b7f5c055SJed Brown 
3146b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
3147b7f5c055SJed Brown     n[i] /= norm;
3148b7f5c055SJed Brown     for (PetscInt j = 0; j < 3; j++) {
3149b7f5c055SJed Brown       // note that n[i] is n_old[i]/norm when executing the code below
3150b7f5c055SJed Brown       n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j];
3151b7f5c055SJed Brown     }
3152b7f5c055SJed Brown   }
3153b7f5c055SJed Brown 
3154b7f5c055SJed Brown   nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2];
3155b7f5c055SJed 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];
3156b7f5c055SJed Brown 
3157b7f5c055SJed Brown   res[0] = f;
3158b7f5c055SJed Brown   res[1] = d[1] - 2 * n[1] * nd;
3159b7f5c055SJed Brown   res[2] = d[2] - 2 * n[2] * nd;
3160b7f5c055SJed Brown   // J[j][i] is J_{ij} (column major)
3161b7f5c055SJed Brown   for (PetscInt j = 0; j < 3; j++) {
3162b7f5c055SJed Brown     J[0 + j * 3] = grad[j];
3163b7f5c055SJed Brown     J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]);
3164b7f5c055SJed Brown     J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]);
3165b7f5c055SJed Brown   }
3166b7f5c055SJed Brown }
3167b7f5c055SJed Brown 
3168b7f5c055SJed Brown /*
3169b7f5c055SJed Brown    Project x to the nearest point on the implicit surface using Newton's method.
3170b7f5c055SJed Brown */
3171d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[])
3172d71ae5a4SJacob Faibussowitsch {
3173b7f5c055SJed Brown   PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess
3174b7f5c055SJed Brown 
3175b7f5c055SJed Brown   PetscFunctionBegin;
3176b7f5c055SJed Brown   for (PetscInt iter = 0; iter < 10; iter++) {
3177b7f5c055SJed Brown     PetscScalar res[3], J[9];
3178b7f5c055SJed Brown     PetscReal   resnorm;
3179b7f5c055SJed Brown     TPSNearestPointResJac(feval, x, y, res, J);
3180b7f5c055SJed Brown     resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2])));
3181b7f5c055SJed Brown     if (0) { // Turn on this monitor if you need to confirm quadratic convergence
318263a3b9bcSJacob 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])));
3183b7f5c055SJed Brown     }
3184b7f5c055SJed Brown     if (resnorm < PETSC_SMALL) break;
3185b7f5c055SJed Brown 
3186b7f5c055SJed Brown     // Take the Newton step
31879566063dSJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL));
3188b7f5c055SJed Brown     PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res);
3189b7f5c055SJed Brown   }
3190b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) x[i] = y[i];
31913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3192b7f5c055SJed Brown }
3193b7f5c055SJed Brown 
3194b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL};
3195b7f5c055SJed Brown 
3196d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness)
3197d71ae5a4SJacob Faibussowitsch {
3198b7f5c055SJed Brown   PetscMPIInt rank;
3199b7f5c055SJed Brown   PetscInt    topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0;
3200b7f5c055SJed Brown   PetscInt(*edges)[2] = NULL, *edgeSets = NULL;
3201b7f5c055SJed Brown   PetscInt           *cells_flat = NULL;
3202b7f5c055SJed Brown   PetscReal          *vtxCoords  = NULL;
3203b7f5c055SJed Brown   TPSEvaluateFunc     evalFunc   = NULL;
32048434afd1SBarry Smith   PetscSimplePointFn *normalFunc = NULL;
3205b7f5c055SJed Brown   DMLabel             label;
3206b7f5c055SJed Brown 
3207b7f5c055SJed Brown   PetscFunctionBegin;
320846139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
32099566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
321063a3b9bcSJacob 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);
3211b7f5c055SJed Brown   switch (tpstype) {
3212b7f5c055SJed Brown   case DMPLEX_TPS_SCHWARZ_P:
3213b7f5c055SJed 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");
3214c5853193SPierre Jolivet     if (rank == 0) {
3215b7f5c055SJed Brown       PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn]
3216b7f5c055SJed Brown       PetscInt  Njunctions = 0, Ncuts = 0, Npipes[3], vcount;
3217b7f5c055SJed Brown       PetscReal L = 1;
3218b7f5c055SJed Brown 
3219b7f5c055SJed Brown       Npipes[0]   = (extent[0] + 1) * extent[1] * extent[2];
3220b7f5c055SJed Brown       Npipes[1]   = extent[0] * (extent[1] + 1) * extent[2];
3221b7f5c055SJed Brown       Npipes[2]   = extent[0] * extent[1] * (extent[2] + 1);
3222b7f5c055SJed Brown       Njunctions  = extent[0] * extent[1] * extent[2];
3223b7f5c055SJed Brown       Ncuts       = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]);
3224b7f5c055SJed Brown       numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions;
32259566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords));
32269566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Njunctions, &cells));
32279566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edges));
32289566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets));
3229b7f5c055SJed Brown       // x-normal pipes
3230b7f5c055SJed Brown       vcount = 0;
3231b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0] + 1; i++) {
3232b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3233b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3234b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3235b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * i - 1) * L;
3236b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3237b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3238b7f5c055SJed Brown             }
3239b7f5c055SJed Brown           }
3240b7f5c055SJed Brown         }
3241b7f5c055SJed Brown       }
3242b7f5c055SJed Brown       // y-normal pipes
3243b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3244b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1] + 1; j++) {
3245b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3246b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3247b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3248b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * j - 1) * L;
3249b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3250b7f5c055SJed Brown             }
3251b7f5c055SJed Brown           }
3252b7f5c055SJed Brown         }
3253b7f5c055SJed Brown       }
3254b7f5c055SJed Brown       // z-normal pipes
3255b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3256b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3257b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2] + 1; k++) {
3258b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3259b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3260b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3261b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * k - 1) * L;
3262b7f5c055SJed Brown             }
3263b7f5c055SJed Brown           }
3264b7f5c055SJed Brown         }
3265b7f5c055SJed Brown       }
3266b7f5c055SJed Brown       // junctions
3267b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3268b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3269b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3270b7f5c055SJed Brown             const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8;
3271b7f5c055SJed Brown             PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count");
3272b7f5c055SJed Brown             for (PetscInt ii = 0; ii < 2; ii++) {
3273b7f5c055SJed Brown               for (PetscInt jj = 0; jj < 2; jj++) {
3274b7f5c055SJed Brown                 for (PetscInt kk = 0; kk < 2; kk++) {
3275b7f5c055SJed Brown                   double Ls           = (1 - sqrt(2) / 4) * L;
3276b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls;
3277b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls;
3278b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls;
3279b7f5c055SJed Brown                 }
3280b7f5c055SJed Brown               }
3281b7f5c055SJed Brown             }
3282b7f5c055SJed Brown             const PetscInt jfaces[3][2][4] = {
3283b7f5c055SJed Brown               {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned
3284b7f5c055SJed Brown               {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned
3285b7f5c055SJed Brown               {{6, 2, 0, 4}, {7, 3, 1, 5}}  // z-aligned
3286b7f5c055SJed Brown             };
3287b7f5c055SJed Brown             const PetscInt pipe_lo[3] = {// vertex numbers of pipes
32889371c9d4SSatish 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};
3289b7f5c055SJed Brown             const PetscInt pipe_hi[3] = {// vertex numbers of pipes
32909371c9d4SSatish 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};
3291b7f5c055SJed Brown             for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z
3292b7f5c055SJed Brown               const PetscInt ijk[3] = {i, j, k};
3293b7f5c055SJed Brown               for (PetscInt l = 0; l < 4; l++) { // rotations
3294b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l;
3295b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l];
3296b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4];
3297b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4;
3298b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l];
3299b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l;
3300b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4;
3301b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4];
3302b7f5c055SJed Brown                 if (ijk[dir] == 0) {
3303b7f5c055SJed Brown                   edges[numEdges][0] = pipe_lo[dir] + l;
3304b7f5c055SJed Brown                   edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4;
3305b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 1;
3306b7f5c055SJed Brown                   numEdges++;
3307b7f5c055SJed Brown                 }
3308b7f5c055SJed Brown                 if (ijk[dir] + 1 == extent[dir]) {
3309b7f5c055SJed Brown                   edges[numEdges][0] = pipe_hi[dir] + l;
3310b7f5c055SJed Brown                   edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4;
3311b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 2;
3312b7f5c055SJed Brown                   numEdges++;
3313b7f5c055SJed Brown                 }
3314b7f5c055SJed Brown               }
3315b7f5c055SJed Brown             }
3316b7f5c055SJed Brown           }
3317b7f5c055SJed Brown         }
3318b7f5c055SJed Brown       }
331963a3b9bcSJacob Faibussowitsch       PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts);
3320b7f5c055SJed Brown       numFaces   = 24 * Njunctions;
3321b7f5c055SJed Brown       cells_flat = cells[0][0][0];
3322b7f5c055SJed Brown     }
3323b7f5c055SJed Brown     evalFunc   = TPSEvaluate_SchwarzP;
33244663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_SchwarzP;
3325b7f5c055SJed Brown     break;
3326b7f5c055SJed Brown   case DMPLEX_TPS_GYROID:
3327c5853193SPierre Jolivet     if (rank == 0) {
3328b7f5c055SJed Brown       // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set
3329b7f5c055SJed Brown       //
3330b7f5c055SJed 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)
3331b7f5c055SJed Brown       //
3332b7f5c055SJed Brown       // on the cell [0,2]^3.
3333b7f5c055SJed Brown       //
3334b7f5c055SJed Brown       // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2].
3335b7f5c055SJed Brown       // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins
3336b7f5c055SJed Brown       // like a boomerang:
3337b7f5c055SJed Brown       //
3338b7f5c055SJed Brown       //     z = 0          z = 1/4        z = 1/2        z = 3/4     //
3339b7f5c055SJed Brown       //     -----          -------        -------        -------     //
3340b7f5c055SJed Brown       //                                                              //
3341b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
3342b7f5c055SJed Brown       //      \                                   /            \      //
3343b7f5c055SJed Brown       //       \            `-_   _-'            /              }     //
3344b7f5c055SJed Brown       //        *-_            `-'            _-'              /      //
3345b7f5c055SJed Brown       //     +     `-+      +       +      +-'     +      +   /   +   //
3346b7f5c055SJed Brown       //                                                              //
3347b7f5c055SJed Brown       //                                                              //
3348b7f5c055SJed Brown       //     z = 1          z = 5/4        z = 3/2        z = 7/4     //
3349b7f5c055SJed Brown       //     -----          -------        -------        -------     //
3350b7f5c055SJed Brown       //                                                              //
3351b7f5c055SJed Brown       //     +-_     +      +       +      +     _-+      +   /   +   //
3352b7f5c055SJed Brown       //        `-_            _-_            _-`            /        //
3353b7f5c055SJed Brown       //           \        _-'   `-_        /              {         //
3354b7f5c055SJed Brown       //            \                       /                \        //
3355b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
3356b7f5c055SJed Brown       //
3357b7f5c055SJed Brown       //
3358b7f5c055SJed Brown       // This course mesh approximates each of these slices by two line segments,
3359b7f5c055SJed Brown       // and then connects the segments in consecutive layers with quadrilateral faces.
3360b7f5c055SJed Brown       // All of the end points of the segments are multiples of 1/4 except for the
3361b7f5c055SJed Brown       // point * in the picture for z = 0 above and the similar points in other layers.
3362b7f5c055SJed Brown       // That point is at (gamma, gamma, 0), where gamma is calculated below.
3363b7f5c055SJed Brown       //
3364b7f5c055SJed Brown       // The column  [1,2]x[1,2]x[0,2] looks the same as this column;
3365b7f5c055SJed Brown       // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images.
3366b7f5c055SJed Brown       //
3367b7f5c055SJed Brown       // As for how this method turned into the names given to the vertices:
3368b7f5c055SJed Brown       // that was not systematic, it was just the way it worked out in my handwritten notes.
3369b7f5c055SJed Brown 
3370b7f5c055SJed Brown       PetscInt facesPerBlock = 64;
3371b7f5c055SJed Brown       PetscInt vertsPerBlock = 56;
3372b7f5c055SJed Brown       PetscInt extentPlus[3];
3373b7f5c055SJed Brown       PetscInt numBlocks, numBlocksPlus;
33749371c9d4SSatish 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;
33759371c9d4SSatish Balay       const PetscInt pattern[64][4] = {
33769371c9d4SSatish Balay         /* face to vertex within the coarse discretization of a single gyroid block */
3377b7f5c055SJed Brown         /* layer 0 */
33789371c9d4SSatish Balay         {A,           C,           K,           G          },
33799371c9d4SSatish Balay         {C,           B,           II,          K          },
33809371c9d4SSatish Balay         {D,           A,           H,           L          },
33819371c9d4SSatish Balay         {B + 56 * 1,  D,           L,           J          },
33829371c9d4SSatish Balay         {E,           B + 56 * 1,  J,           N          },
33839371c9d4SSatish Balay         {A + 56 * 2,  E,           N,           H + 56 * 2 },
33849371c9d4SSatish Balay         {F,           A + 56 * 2,  G + 56 * 2,  M          },
33859371c9d4SSatish Balay         {B,           F,           M,           II         },
3386b7f5c055SJed Brown         /* layer 1 */
33879371c9d4SSatish Balay         {G,           K,           Q,           O          },
33889371c9d4SSatish Balay         {K,           II,          P,           Q          },
33899371c9d4SSatish Balay         {L,           H,           O + 56 * 1,  R          },
33909371c9d4SSatish Balay         {J,           L,           R,           P          },
33919371c9d4SSatish Balay         {N,           J,           P,           S          },
33929371c9d4SSatish Balay         {H + 56 * 2,  N,           S,           O + 56 * 3 },
33939371c9d4SSatish Balay         {M,           G + 56 * 2,  O + 56 * 2,  T          },
33949371c9d4SSatish Balay         {II,          M,           T,           P          },
3395b7f5c055SJed Brown         /* layer 2 */
33969371c9d4SSatish Balay         {O,           Q,           Y,           U          },
33979371c9d4SSatish Balay         {Q,           P,           W,           Y          },
33989371c9d4SSatish Balay         {R,           O + 56 * 1,  U + 56 * 1,  Ap         },
33999371c9d4SSatish Balay         {P,           R,           Ap,          W          },
34009371c9d4SSatish Balay         {S,           P,           X,           Bp         },
34019371c9d4SSatish Balay         {O + 56 * 3,  S,           Bp,          V + 56 * 1 },
34029371c9d4SSatish Balay         {T,           O + 56 * 2,  V,           Z          },
34039371c9d4SSatish Balay         {P,           T,           Z,           X          },
3404b7f5c055SJed Brown         /* layer 3 */
34059371c9d4SSatish Balay         {U,           Y,           Ep,          Dp         },
34069371c9d4SSatish Balay         {Y,           W,           Cp,          Ep         },
34079371c9d4SSatish Balay         {Ap,          U + 56 * 1,  Dp + 56 * 1, Gp         },
34089371c9d4SSatish Balay         {W,           Ap,          Gp,          Cp         },
34099371c9d4SSatish Balay         {Bp,          X,           Cp + 56 * 2, Fp         },
34109371c9d4SSatish Balay         {V + 56 * 1,  Bp,          Fp,          Dp + 56 * 1},
34119371c9d4SSatish Balay         {Z,           V,           Dp,          Hp         },
34129371c9d4SSatish Balay         {X,           Z,           Hp,          Cp + 56 * 2},
3413b7f5c055SJed Brown         /* layer 4 */
34149371c9d4SSatish Balay         {Dp,          Ep,          Mp,          Kp         },
34159371c9d4SSatish Balay         {Ep,          Cp,          Ip,          Mp         },
34169371c9d4SSatish Balay         {Gp,          Dp + 56 * 1, Lp,          Np         },
34179371c9d4SSatish Balay         {Cp,          Gp,          Np,          Jp         },
34189371c9d4SSatish Balay         {Fp,          Cp + 56 * 2, Jp + 56 * 2, Pp         },
34199371c9d4SSatish Balay         {Dp + 56 * 1, Fp,          Pp,          Lp         },
34209371c9d4SSatish Balay         {Hp,          Dp,          Kp,          Op         },
34219371c9d4SSatish Balay         {Cp + 56 * 2, Hp,          Op,          Ip + 56 * 2},
3422b7f5c055SJed Brown         /* layer 5 */
34239371c9d4SSatish Balay         {Kp,          Mp,          Sp,          Rp         },
34249371c9d4SSatish Balay         {Mp,          Ip,          Qp,          Sp         },
34259371c9d4SSatish Balay         {Np,          Lp,          Rp,          Tp         },
34269371c9d4SSatish Balay         {Jp,          Np,          Tp,          Qp + 56 * 1},
34279371c9d4SSatish Balay         {Pp,          Jp + 56 * 2, Qp + 56 * 3, Up         },
34289371c9d4SSatish Balay         {Lp,          Pp,          Up,          Rp         },
34299371c9d4SSatish Balay         {Op,          Kp,          Rp,          Vp         },
34309371c9d4SSatish Balay         {Ip + 56 * 2, Op,          Vp,          Qp + 56 * 2},
3431b7f5c055SJed Brown         /* layer 6 */
34329371c9d4SSatish Balay         {Rp,          Sp,          Aq,          Yp         },
34339371c9d4SSatish Balay         {Sp,          Qp,          Wp,          Aq         },
34349371c9d4SSatish Balay         {Tp,          Rp,          Yp,          Cq         },
34359371c9d4SSatish Balay         {Qp + 56 * 1, Tp,          Cq,          Wp + 56 * 1},
34369371c9d4SSatish Balay         {Up,          Qp + 56 * 3, Xp + 56 * 1, Dq         },
34379371c9d4SSatish Balay         {Rp,          Up,          Dq,          Zp         },
34389371c9d4SSatish Balay         {Vp,          Rp,          Zp,          Bq         },
34399371c9d4SSatish Balay         {Qp + 56 * 2, Vp,          Bq,          Xp         },
3440b7f5c055SJed Brown         /* layer 7 (the top is the periodic image of the bottom of layer 0) */
34419371c9d4SSatish Balay         {Yp,          Aq,          C + 56 * 4,  A + 56 * 4 },
34429371c9d4SSatish Balay         {Aq,          Wp,          B + 56 * 4,  C + 56 * 4 },
34439371c9d4SSatish Balay         {Cq,          Yp,          A + 56 * 4,  D + 56 * 4 },
34449371c9d4SSatish Balay         {Wp + 56 * 1, Cq,          D + 56 * 4,  B + 56 * 5 },
34459371c9d4SSatish Balay         {Dq,          Xp + 56 * 1, B + 56 * 5,  E + 56 * 4 },
34469371c9d4SSatish Balay         {Zp,          Dq,          E + 56 * 4,  A + 56 * 6 },
34479371c9d4SSatish Balay         {Bq,          Zp,          A + 56 * 6,  F + 56 * 4 },
34489371c9d4SSatish Balay         {Xp,          Bq,          F + 56 * 4,  B + 56 * 4 }
3449b7f5c055SJed Brown       };
3450b7f5c055SJed Brown       const PetscReal gamma                = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI;
34519371c9d4SSatish Balay       const PetscReal patternCoords[56][3] = {
3452bee3fc89SBarry Smith         {1.,        0.,        0.  }, /* A  */
3453bee3fc89SBarry Smith         {0.,        1.,        0.  }, /* B  */
3454bee3fc89SBarry Smith         {gamma,     gamma,     0.  }, /* C  */
3455bee3fc89SBarry Smith         {1 + gamma, 1 - gamma, 0.  }, /* D  */
3456bee3fc89SBarry Smith         {2 - gamma, 2 - gamma, 0.  }, /* E  */
3457bee3fc89SBarry Smith         {1 - gamma, 1 + gamma, 0.  }, /* F  */
3458b7f5c055SJed Brown 
3459bee3fc89SBarry Smith         {.5,        0,         .25 }, /* G  */
3460bee3fc89SBarry Smith         {1.5,       0.,        .25 }, /* H  */
3461bee3fc89SBarry Smith         {.5,        1.,        .25 }, /* II */
3462bee3fc89SBarry Smith         {1.5,       1.,        .25 }, /* J  */
3463bee3fc89SBarry Smith         {.25,       .5,        .25 }, /* K  */
3464bee3fc89SBarry Smith         {1.25,      .5,        .25 }, /* L  */
3465bee3fc89SBarry Smith         {.75,       1.5,       .25 }, /* M  */
3466bee3fc89SBarry Smith         {1.75,      1.5,       .25 }, /* N  */
3467b7f5c055SJed Brown 
3468bee3fc89SBarry Smith         {0.,        0.,        .5  }, /* O  */
3469bee3fc89SBarry Smith         {1.,        1.,        .5  }, /* P  */
3470bee3fc89SBarry Smith         {gamma,     1 - gamma, .5  }, /* Q  */
3471bee3fc89SBarry Smith         {1 + gamma, gamma,     .5  }, /* R  */
3472bee3fc89SBarry Smith         {2 - gamma, 1 + gamma, .5  }, /* S  */
3473bee3fc89SBarry Smith         {1 - gamma, 2 - gamma, .5  }, /* T  */
3474b7f5c055SJed Brown 
3475bee3fc89SBarry Smith         {0.,        .5,        .75 }, /* U  */
3476bee3fc89SBarry Smith         {0.,        1.5,       .75 }, /* V  */
3477bee3fc89SBarry Smith         {1.,        .5,        .75 }, /* W  */
3478bee3fc89SBarry Smith         {1.,        1.5,       .75 }, /* X  */
3479bee3fc89SBarry Smith         {.5,        .75,       .75 }, /* Y  */
3480bee3fc89SBarry Smith         {.5,        1.75,      .75 }, /* Z  */
3481bee3fc89SBarry Smith         {1.5,       .25,       .75 }, /* Ap */
3482bee3fc89SBarry Smith         {1.5,       1.25,      .75 }, /* Bp */
3483b7f5c055SJed Brown 
3484bee3fc89SBarry Smith         {1.,        0.,        1.  }, /* Cp */
3485bee3fc89SBarry Smith         {0.,        1.,        1.  }, /* Dp */
3486bee3fc89SBarry Smith         {1 - gamma, 1 - gamma, 1.  }, /* Ep */
3487bee3fc89SBarry Smith         {1 + gamma, 1 + gamma, 1.  }, /* Fp */
3488bee3fc89SBarry Smith         {2 - gamma, gamma,     1.  }, /* Gp */
3489bee3fc89SBarry Smith         {gamma,     2 - gamma, 1.  }, /* Hp */
3490b7f5c055SJed Brown 
3491bee3fc89SBarry Smith         {.5,        0.,        1.25}, /* Ip */
3492bee3fc89SBarry Smith         {1.5,       0.,        1.25}, /* Jp */
3493bee3fc89SBarry Smith         {.5,        1.,        1.25}, /* Kp */
3494bee3fc89SBarry Smith         {1.5,       1.,        1.25}, /* Lp */
3495bee3fc89SBarry Smith         {.75,       .5,        1.25}, /* Mp */
3496bee3fc89SBarry Smith         {1.75,      .5,        1.25}, /* Np */
3497bee3fc89SBarry Smith         {.25,       1.5,       1.25}, /* Op */
3498bee3fc89SBarry Smith         {1.25,      1.5,       1.25}, /* Pp */
3499b7f5c055SJed Brown 
3500bee3fc89SBarry Smith         {0.,        0.,        1.5 }, /* Qp */
3501bee3fc89SBarry Smith         {1.,        1.,        1.5 }, /* Rp */
3502bee3fc89SBarry Smith         {1 - gamma, gamma,     1.5 }, /* Sp */
3503bee3fc89SBarry Smith         {2 - gamma, 1 - gamma, 1.5 }, /* Tp */
3504bee3fc89SBarry Smith         {1 + gamma, 2 - gamma, 1.5 }, /* Up */
3505bee3fc89SBarry Smith         {gamma,     1 + gamma, 1.5 }, /* Vp */
3506b7f5c055SJed Brown 
3507bee3fc89SBarry Smith         {0.,        .5,        1.75}, /* Wp */
3508bee3fc89SBarry Smith         {0.,        1.5,       1.75}, /* Xp */
3509bee3fc89SBarry Smith         {1.,        .5,        1.75}, /* Yp */
3510bee3fc89SBarry Smith         {1.,        1.5,       1.75}, /* Zp */
3511bee3fc89SBarry Smith         {.5,        .25,       1.75}, /* Aq */
3512bee3fc89SBarry Smith         {.5,        1.25,      1.75}, /* Bq */
3513bee3fc89SBarry Smith         {1.5,       .75,       1.75}, /* Cq */
3514bee3fc89SBarry Smith         {1.5,       1.75,      1.75}, /* Dq */
3515b7f5c055SJed Brown       };
3516b7f5c055SJed Brown       PetscInt(*cells)[64][4] = NULL;
3517b7f5c055SJed Brown       PetscBool *seen;
3518b7f5c055SJed Brown       PetscInt  *vertToTrueVert;
3519b7f5c055SJed Brown       PetscInt   count;
3520b7f5c055SJed Brown 
3521b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1;
3522b7f5c055SJed Brown       numBlocks = 1;
3523b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i];
3524b7f5c055SJed Brown       numBlocksPlus = 1;
3525b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i];
3526b7f5c055SJed Brown       numFaces = numBlocks * facesPerBlock;
35279566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocks, &cells));
35289566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen));
3529b7f5c055SJed Brown       for (PetscInt k = 0; k < extent[2]; k++) {
3530b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3531b7f5c055SJed Brown           for (PetscInt i = 0; i < extent[0]; i++) {
3532b7f5c055SJed Brown             for (PetscInt f = 0; f < facesPerBlock; f++) {
3533b7f5c055SJed Brown               for (PetscInt v = 0; v < 4; v++) {
3534b7f5c055SJed Brown                 PetscInt vertRaw     = pattern[f][v];
3535b7f5c055SJed Brown                 PetscInt blockidx    = vertRaw / 56;
3536b7f5c055SJed Brown                 PetscInt patternvert = vertRaw % 56;
3537b7f5c055SJed Brown                 PetscInt xplus       = (blockidx & 1);
3538b7f5c055SJed Brown                 PetscInt yplus       = (blockidx & 2) >> 1;
3539b7f5c055SJed Brown                 PetscInt zplus       = (blockidx & 4) >> 2;
3540b7f5c055SJed Brown                 PetscInt zcoord      = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus);
3541b7f5c055SJed Brown                 PetscInt ycoord      = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus);
3542b7f5c055SJed Brown                 PetscInt xcoord      = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus);
3543b7f5c055SJed Brown                 PetscInt vert        = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert;
3544b7f5c055SJed Brown 
3545b7f5c055SJed Brown                 cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert;
3546b7f5c055SJed Brown                 seen[vert]                                       = PETSC_TRUE;
3547b7f5c055SJed Brown               }
3548b7f5c055SJed Brown             }
3549b7f5c055SJed Brown           }
3550b7f5c055SJed Brown         }
3551b7f5c055SJed Brown       }
35529371c9d4SSatish Balay       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++)
35539371c9d4SSatish Balay         if (seen[i]) numVertices++;
3554b7f5c055SJed Brown       count = 0;
35559566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert));
35569566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords));
3557b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1;
3558b7f5c055SJed Brown       for (PetscInt k = 0; k < extentPlus[2]; k++) {
3559b7f5c055SJed Brown         for (PetscInt j = 0; j < extentPlus[1]; j++) {
3560b7f5c055SJed Brown           for (PetscInt i = 0; i < extentPlus[0]; i++) {
3561b7f5c055SJed Brown             for (PetscInt v = 0; v < vertsPerBlock; v++) {
3562b7f5c055SJed Brown               PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v;
3563b7f5c055SJed Brown 
3564b7f5c055SJed Brown               if (seen[vIdx]) {
3565b7f5c055SJed Brown                 PetscInt thisVert;
3566b7f5c055SJed Brown 
3567b7f5c055SJed Brown                 vertToTrueVert[vIdx] = thisVert = count++;
3568b7f5c055SJed Brown 
3569b7f5c055SJed Brown                 for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d];
3570b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 0] += i * 2;
3571b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 1] += j * 2;
3572b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 2] += k * 2;
3573b7f5c055SJed Brown               }
3574b7f5c055SJed Brown             }
3575b7f5c055SJed Brown           }
3576b7f5c055SJed Brown         }
3577b7f5c055SJed Brown       }
3578b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocks; i++) {
3579b7f5c055SJed Brown         for (PetscInt f = 0; f < facesPerBlock; f++) {
3580ad540459SPierre Jolivet           for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]];
3581b7f5c055SJed Brown         }
3582b7f5c055SJed Brown       }
35839566063dSJacob Faibussowitsch       PetscCall(PetscFree(vertToTrueVert));
35849566063dSJacob Faibussowitsch       PetscCall(PetscFree(seen));
3585b7f5c055SJed Brown       cells_flat = cells[0][0];
3586b7f5c055SJed Brown       numEdges   = 0;
3587b7f5c055SJed Brown       for (PetscInt i = 0; i < numFaces; i++) {
3588b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3589b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3590b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3591b7f5c055SJed Brown 
3592b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3593b7f5c055SJed Brown             if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) {
3594b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++;
3595b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++;
3596b7f5c055SJed Brown             }
3597b7f5c055SJed Brown           }
3598b7f5c055SJed Brown         }
3599b7f5c055SJed Brown       }
36009566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edges));
36019566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edgeSets));
3602b7f5c055SJed Brown       for (PetscInt edge = 0, i = 0; i < numFaces; i++) {
3603b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
3604b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
3605b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
3606b7f5c055SJed Brown 
3607b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
3608b7f5c055SJed Brown             if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) {
3609b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) {
3610b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3611b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3612b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d;
3613b7f5c055SJed Brown               }
3614b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) {
3615b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
3616b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
3617b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d + 1;
3618b7f5c055SJed Brown               }
3619b7f5c055SJed Brown             }
3620b7f5c055SJed Brown           }
3621b7f5c055SJed Brown         }
3622b7f5c055SJed Brown       }
3623b7f5c055SJed Brown     }
3624b7f5c055SJed Brown     evalFunc   = TPSEvaluate_Gyroid;
36254663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_Gyroid;
3626b7f5c055SJed Brown     break;
3627b7f5c055SJed Brown   }
3628b7f5c055SJed Brown 
36299566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, topoDim));
3630c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat));
36319566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL));
36329566063dSJacob Faibussowitsch   PetscCall(PetscFree(cells_flat));
3633b7f5c055SJed Brown   {
3634b7f5c055SJed Brown     DM idm;
36359566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
363669d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &idm));
3637b7f5c055SJed Brown   }
3638c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords));
36399566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL));
36409566063dSJacob Faibussowitsch   PetscCall(PetscFree(vtxCoords));
3641b7f5c055SJed Brown 
36429566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
36439566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
3644b7f5c055SJed Brown   for (PetscInt e = 0; e < numEdges; e++) {
3645b7f5c055SJed Brown     PetscInt        njoin;
3646b7f5c055SJed Brown     const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]};
36479566063dSJacob Faibussowitsch     PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join));
364863a3b9bcSJacob 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]);
36499566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(label, join[0], edgeSets[e]));
36509566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join));
3651b7f5c055SJed Brown   }
36529566063dSJacob Faibussowitsch   PetscCall(PetscFree(edges));
36539566063dSJacob Faibussowitsch   PetscCall(PetscFree(edgeSets));
36541436d7faSJed Brown   if (tps_distribute) {
36551436d7faSJed Brown     DM               pdm = NULL;
36561436d7faSJed Brown     PetscPartitioner part;
36571436d7faSJed Brown 
36589566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
36599566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
36609566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm));
366148a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
36621436d7faSJed Brown     // Do not auto-distribute again
36639566063dSJacob Faibussowitsch     PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
36641436d7faSJed Brown   }
3665b7f5c055SJed Brown 
36669566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
3667b7f5c055SJed Brown   for (PetscInt refine = 0; refine < refinements; refine++) {
3668b7f5c055SJed Brown     PetscInt     m;
3669b7f5c055SJed Brown     DM           dmf;
3670b7f5c055SJed Brown     Vec          X;
3671b7f5c055SJed Brown     PetscScalar *x;
36729566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf));
367369d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmf));
3674b7f5c055SJed Brown 
36759566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &X));
36769566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(X, &m));
36779566063dSJacob Faibussowitsch     PetscCall(VecGetArray(X, &x));
367848a46eb9SPierre Jolivet     for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i]));
36799566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(X, &x));
3680b7f5c055SJed Brown   }
3681b7f5c055SJed Brown 
3682b7f5c055SJed Brown   // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices.
36839566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
36849566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, label));
3685b7f5c055SJed Brown 
368646139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
368746139095SJed Brown 
3688b7f5c055SJed Brown   if (thickness > 0) {
36894663dae6SJed Brown     DM              edm, cdm, ecdm;
36904663dae6SJed Brown     DMPlexTransform tr;
36914663dae6SJed Brown     const char     *prefix;
36924663dae6SJed Brown     PetscOptions    options;
36934663dae6SJed Brown     // Code from DMPlexExtrude
36944663dae6SJed Brown     PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr));
36954663dae6SJed Brown     PetscCall(DMPlexTransformSetDM(tr, dm));
36964663dae6SJed Brown     PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE));
36974663dae6SJed Brown     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
36984663dae6SJed Brown     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix));
36994663dae6SJed Brown     PetscCall(PetscObjectGetOptions((PetscObject)dm, &options));
37004663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, options));
37014663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers));
37024663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness));
37034663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE));
37044663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE));
37054663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc));
37064663dae6SJed Brown     PetscCall(DMPlexTransformSetFromOptions(tr));
37074663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL));
37084663dae6SJed Brown     PetscCall(DMPlexTransformSetUp(tr));
37094663dae6SJed Brown     PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view"));
37104663dae6SJed Brown     PetscCall(DMPlexTransformApply(tr, dm, &edm));
37114663dae6SJed Brown     PetscCall(DMCopyDisc(dm, edm));
37124663dae6SJed Brown     PetscCall(DMGetCoordinateDM(dm, &cdm));
37134663dae6SJed Brown     PetscCall(DMGetCoordinateDM(edm, &ecdm));
37144663dae6SJed Brown     PetscCall(DMCopyDisc(cdm, ecdm));
37154663dae6SJed Brown     PetscCall(DMPlexTransformCreateDiscLabels(tr, edm));
37164663dae6SJed Brown     PetscCall(DMPlexTransformDestroy(&tr));
3717a77a5016SMatthew G. Knepley     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, edm));
371869d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
3719b7f5c055SJed Brown   }
37203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3721b7f5c055SJed Brown }
3722b7f5c055SJed Brown 
3723b7f5c055SJed Brown /*@
3724b7f5c055SJed Brown   DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface
3725b7f5c055SJed Brown 
3726b7f5c055SJed Brown   Collective
3727b7f5c055SJed Brown 
3728b7f5c055SJed Brown   Input Parameters:
3729a1cb98faSBarry Smith + comm           - The communicator for the `DM` object
3730b7f5c055SJed Brown . tpstype        - Type of triply-periodic surface
3731b7f5c055SJed Brown . extent         - Array of length 3 containing number of periods in each direction
373220f4b53cSBarry Smith . periodic       - array of length 3 with periodicity, or `NULL` for non-periodic
37331436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable)
3734817da375SSatish Balay . refinements    - Number of factor-of-2 refinements of 2D manifold mesh
37351436d7faSJed Brown . layers         - Number of cell layers extruded in normal direction
3736817da375SSatish Balay - thickness      - Thickness in normal direction
3737b7f5c055SJed Brown 
3738b7f5c055SJed Brown   Output Parameter:
3739a1cb98faSBarry Smith . dm - The `DM` object
3740a1cb98faSBarry Smith 
3741a1cb98faSBarry Smith   Level: beginner
3742b7f5c055SJed Brown 
3743b7f5c055SJed Brown   Notes:
374415229ffcSPierre Jolivet   This meshes the surface of the Schwarz P or Gyroid surfaces.  Schwarz P is the simplest member of the triply-periodic minimal surfaces.
37451d27aa22SBarry Smith   <https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22)> and can be cut with "clean" boundaries.
37461d27aa22SBarry Smith   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.
3747b7f5c055SJed Brown   Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested.
3748b7f5c055SJed Brown   On each refinement, all vertices are projected to their nearest point on the surface.
3749b7f5c055SJed Brown   This projection could readily be extended to related surfaces.
3750b7f5c055SJed Brown 
37511d27aa22SBarry Smith   See {cite}`maskery2018insights`
37521d27aa22SBarry Smith 
37531d27aa22SBarry Smith   The face (edge) sets for the Schwarz P surface are numbered $1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z)$.
37541d27aa22SBarry Smith   When the mesh is refined, "Face Sets" contain the new vertices (created during refinement).
37551d27aa22SBarry Smith   Use `DMPlexLabelComplete()` to propagate to coarse-level vertices.
3756b7f5c055SJed Brown 
375760225df5SJacob Faibussowitsch   Developer Notes:
3758b7f5c055SJed Brown   The Gyroid mesh does not currently mark boundary sets.
3759b7f5c055SJed Brown 
37601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()`
3761b7f5c055SJed Brown @*/
3762d71ae5a4SJacob 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)
3763d71ae5a4SJacob Faibussowitsch {
3764b7f5c055SJed Brown   PetscFunctionBegin;
37659566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
37669566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
37679566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness));
37683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3769b7f5c055SJed Brown }
3770b7f5c055SJed Brown 
37719318fe57SMatthew G. Knepley /*@
37729318fe57SMatthew G. Knepley   DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d.
37739318fe57SMatthew G. Knepley 
37749318fe57SMatthew G. Knepley   Collective
37759318fe57SMatthew G. Knepley 
37769318fe57SMatthew G. Knepley   Input Parameters:
3777a1cb98faSBarry Smith + comm    - The communicator for the `DM` object
37789318fe57SMatthew G. Knepley . dim     - The dimension
37799318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells
37809318fe57SMatthew G. Knepley - R       - The radius
37819318fe57SMatthew G. Knepley 
37829318fe57SMatthew G. Knepley   Output Parameter:
3783a1cb98faSBarry Smith . dm - The `DM` object
37849318fe57SMatthew G. Knepley 
37859318fe57SMatthew G. Knepley   Level: beginner
37869318fe57SMatthew G. Knepley 
37871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
37889318fe57SMatthew G. Knepley @*/
3789d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm)
3790d71ae5a4SJacob Faibussowitsch {
37919318fe57SMatthew G. Knepley   PetscFunctionBegin;
37924f572ea9SToby Isaac   PetscAssertPointer(dm, 5);
37939566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
37949566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
37959566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R));
37963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
37979318fe57SMatthew G. Knepley }
37989318fe57SMatthew G. Knepley 
3799d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R)
3800d71ae5a4SJacob Faibussowitsch {
38019318fe57SMatthew G. Knepley   DM          sdm, vol;
38029318fe57SMatthew G. Knepley   DMLabel     bdlabel;
3803dd2b43ebSStefano Zampini   const char *prefix;
38049318fe57SMatthew G. Knepley 
38059318fe57SMatthew G. Knepley   PetscFunctionBegin;
38069566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm));
38079566063dSJacob Faibussowitsch   PetscCall(DMSetType(sdm, DMPLEX));
3808dd2b43ebSStefano Zampini   PetscCall(DMGetOptionsPrefix(dm, &prefix));
3809dd2b43ebSStefano Zampini   PetscCall(DMSetOptionsPrefix(sdm, prefix));
3810dd2b43ebSStefano Zampini   PetscCall(DMAppendOptionsPrefix(sdm, "bd_"));
3811dd2b43ebSStefano Zampini   PetscCall(DMPlexDistributeSetDefault(sdm, PETSC_FALSE));
38129566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R));
38139566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(sdm));
38149566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view"));
38159566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol));
38169566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&sdm));
381769d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
38189566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
38199566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
38209566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
38219566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, bdlabel));
38223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
382351a74b61SMatthew G. Knepley }
382451a74b61SMatthew G. Knepley 
382551a74b61SMatthew G. Knepley /*@
382651a74b61SMatthew G. Knepley   DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d.
382751a74b61SMatthew G. Knepley 
382851a74b61SMatthew G. Knepley   Collective
382951a74b61SMatthew G. Knepley 
383051a74b61SMatthew G. Knepley   Input Parameters:
3831a1cb98faSBarry Smith + comm - The communicator for the `DM` object
383251a74b61SMatthew G. Knepley . dim  - The dimension
383351a74b61SMatthew G. Knepley - R    - The radius
383451a74b61SMatthew G. Knepley 
383551a74b61SMatthew G. Knepley   Output Parameter:
3836a1cb98faSBarry Smith . dm - The `DM` object
383751a74b61SMatthew G. Knepley 
3838a1cb98faSBarry Smith   Options Database Key:
383960225df5SJacob Faibussowitsch . bd_dm_refine - This will refine the surface mesh preserving the sphere geometry
384051a74b61SMatthew G. Knepley 
384151a74b61SMatthew G. Knepley   Level: beginner
384251a74b61SMatthew G. Knepley 
38431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
384451a74b61SMatthew G. Knepley @*/
3845d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm)
3846d71ae5a4SJacob Faibussowitsch {
384751a74b61SMatthew G. Knepley   PetscFunctionBegin;
38489566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
38499566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
38509566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R));
38513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
38522829fed8SMatthew G. Knepley }
38532829fed8SMatthew G. Knepley 
3854d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct)
3855d71ae5a4SJacob Faibussowitsch {
38560a6ba040SMatthew G. Knepley   PetscFunctionBegin;
38579318fe57SMatthew G. Knepley   switch (ct) {
38589371c9d4SSatish Balay   case DM_POLYTOPE_POINT: {
38599318fe57SMatthew G. Knepley     PetscInt    numPoints[1]        = {1};
38609318fe57SMatthew G. Knepley     PetscInt    coneSize[1]         = {0};
38619318fe57SMatthew G. Knepley     PetscInt    cones[1]            = {0};
38629318fe57SMatthew G. Knepley     PetscInt    coneOrientations[1] = {0};
38639318fe57SMatthew G. Knepley     PetscScalar vertexCoords[1]     = {0.0};
38649318fe57SMatthew G. Knepley 
38659566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 0));
38669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords));
38679371c9d4SSatish Balay   } break;
38689371c9d4SSatish Balay   case DM_POLYTOPE_SEGMENT: {
38699318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
38709318fe57SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
38719318fe57SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
38729318fe57SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
38739318fe57SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
38749318fe57SMatthew G. Knepley 
38759566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
38769566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
38779371c9d4SSatish Balay   } break;
38789371c9d4SSatish Balay   case DM_POLYTOPE_POINT_PRISM_TENSOR: {
3879b5a892a1SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
3880b5a892a1SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
3881b5a892a1SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
3882b5a892a1SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
3883b5a892a1SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
3884b5a892a1SMatthew G. Knepley 
38859566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
38869566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
38879371c9d4SSatish Balay   } break;
38889371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
38899318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {3, 1};
38909318fe57SMatthew G. Knepley     PetscInt    coneSize[4]         = {3, 0, 0, 0};
38919318fe57SMatthew G. Knepley     PetscInt    cones[3]            = {1, 2, 3};
38929318fe57SMatthew G. Knepley     PetscInt    coneOrientations[3] = {0, 0, 0};
38939318fe57SMatthew G. Knepley     PetscScalar vertexCoords[6]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0};
38949318fe57SMatthew G. Knepley 
38959566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
38969566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
38979371c9d4SSatish Balay   } break;
38989371c9d4SSatish Balay   case DM_POLYTOPE_QUADRILATERAL: {
38999318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
39009318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
39019318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
39029318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
39039318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0};
39049318fe57SMatthew G. Knepley 
39059566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
39069566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
39079371c9d4SSatish Balay   } break;
39089371c9d4SSatish Balay   case DM_POLYTOPE_SEG_PRISM_TENSOR: {
39099318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
39109318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
39119318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
39129318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
39139318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0};
39149318fe57SMatthew G. Knepley 
39159566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
39169566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
39179371c9d4SSatish Balay   } break;
39189371c9d4SSatish Balay   case DM_POLYTOPE_TETRAHEDRON: {
39199318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
39209318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
3921f0edb160SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
39229318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
3923f0edb160SMatthew 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};
39249318fe57SMatthew G. Knepley 
39259566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
39269566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
39279371c9d4SSatish Balay   } break;
39289371c9d4SSatish Balay   case DM_POLYTOPE_HEXAHEDRON: {
39299318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
39309318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
3931f0edb160SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
39329318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
39339371c9d4SSatish 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};
39349318fe57SMatthew G. Knepley 
39359566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
39369566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
39379371c9d4SSatish Balay   } break;
39389371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM: {
39399318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
39409318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
3941f0edb160SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
39429318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
39439371c9d4SSatish 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};
39449318fe57SMatthew G. Knepley 
39459566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
39469566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
39479371c9d4SSatish Balay   } break;
39489371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM_TENSOR: {
39499318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
39509318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
39519318fe57SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
39529318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
39539371c9d4SSatish 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};
39549318fe57SMatthew G. Knepley 
39559566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
39569566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
39579371c9d4SSatish Balay   } break;
39589371c9d4SSatish Balay   case DM_POLYTOPE_QUAD_PRISM_TENSOR: {
39599318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
39609318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
39619318fe57SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
39629318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
39639371c9d4SSatish 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};
39649318fe57SMatthew G. Knepley 
39659566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
39669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
39679371c9d4SSatish Balay   } break;
39689371c9d4SSatish Balay   case DM_POLYTOPE_PYRAMID: {
39699318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {5, 1};
39709318fe57SMatthew G. Knepley     PetscInt    coneSize[6]         = {5, 0, 0, 0, 0, 0};
3971f0edb160SMatthew G. Knepley     PetscInt    cones[5]            = {1, 2, 3, 4, 5};
39729318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
39739371c9d4SSatish 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};
39749318fe57SMatthew G. Knepley 
39759566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
39769566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
39779371c9d4SSatish Balay   } break;
3978d71ae5a4SJacob Faibussowitsch   default:
3979d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]);
39809318fe57SMatthew G. Knepley   }
39819318fe57SMatthew G. Knepley   {
39829318fe57SMatthew G. Knepley     PetscInt Nv, v;
39839318fe57SMatthew G. Knepley 
39849318fe57SMatthew G. Knepley     /* Must create the celltype label here so that we do not automatically try to compute the types */
39859566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(rdm, "celltype"));
39869566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(rdm, 0, ct));
39879566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(rdm, NULL, &Nv));
39889566063dSJacob Faibussowitsch     for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT));
39899318fe57SMatthew G. Knepley   }
39909566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(rdm));
39919566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct]));
39923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
39930a6ba040SMatthew G. Knepley }
39940a6ba040SMatthew G. Knepley 
39959318fe57SMatthew G. Knepley /*@
3996a1cb98faSBarry Smith   DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell
39979318fe57SMatthew G. Knepley 
39989318fe57SMatthew G. Knepley   Collective
39999318fe57SMatthew G. Knepley 
40009318fe57SMatthew G. Knepley   Input Parameters:
40019318fe57SMatthew G. Knepley + comm - The communicator
40029318fe57SMatthew G. Knepley - ct   - The cell type of the reference cell
40039318fe57SMatthew G. Knepley 
40049318fe57SMatthew G. Knepley   Output Parameter:
40059318fe57SMatthew G. Knepley . refdm - The reference cell
40069318fe57SMatthew G. Knepley 
40079318fe57SMatthew G. Knepley   Level: intermediate
40089318fe57SMatthew G. Knepley 
400942747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`
40109318fe57SMatthew G. Knepley @*/
4011d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm)
4012d71ae5a4SJacob Faibussowitsch {
40130a6ba040SMatthew G. Knepley   PetscFunctionBegin;
40149566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, refdm));
40159566063dSJacob Faibussowitsch   PetscCall(DMSetType(*refdm, DMPLEX));
40169566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct));
40173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40189318fe57SMatthew G. Knepley }
401979a015ccSMatthew G. Knepley 
4020d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[])
4021d71ae5a4SJacob Faibussowitsch {
40229318fe57SMatthew G. Knepley   DM        plex;
40239318fe57SMatthew G. Knepley   DMLabel   label;
40249318fe57SMatthew G. Knepley   PetscBool hasLabel;
40250a6ba040SMatthew G. Knepley 
4026c22d3578SMatthew G. Knepley   PetscFunctionBegin;
40279566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &hasLabel));
40283ba16761SJacob Faibussowitsch   if (hasLabel) PetscFunctionReturn(PETSC_SUCCESS);
40299566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, name));
40309566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
40319566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
40329566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label));
40331c8afea9SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(plex, label));
40349566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
40353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
40369318fe57SMatthew G. Knepley }
4037acdc6f61SToby Isaac 
4038669647acSMatthew G. Knepley /*
4039669647acSMatthew 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.
4040669647acSMatthew G. Knepley 
4041669647acSMatthew G. Knepley     (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0]))
4042669647acSMatthew G. Knepley */
4043d71ae5a4SJacob 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[])
4044d71ae5a4SJacob Faibussowitsch {
4045669647acSMatthew G. Knepley   const PetscReal low = PetscRealPart(constants[0]);
4046669647acSMatthew G. Knepley   const PetscReal upp = PetscRealPart(constants[1]);
4047669647acSMatthew G. Knepley   const PetscReal r   = PetscRealPart(u[1]);
4048669647acSMatthew G. Knepley   const PetscReal th  = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low);
4049669647acSMatthew G. Knepley 
4050669647acSMatthew G. Knepley   f0[0] = r * PetscCosReal(th);
4051669647acSMatthew G. Knepley   f0[1] = r * PetscSinReal(th);
4052669647acSMatthew G. Knepley }
4053669647acSMatthew G. Knepley 
40545390be7dSMatthew G. Knepley // Insert vertices and their joins, marked by depth
40555390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Vertices(DM dm, DMLabel label, DMLabel vlabel, PetscInt val, PetscInt n, const PetscInt vertices[])
40565390be7dSMatthew G. Knepley {
40575390be7dSMatthew G. Knepley   PetscFunctionBegin;
40585390be7dSMatthew G. Knepley   PetscCall(DMPlexMarkSubmesh_Interpolated(dm, vlabel, val, PETSC_FALSE, PETSC_FALSE, label, NULL));
40595390be7dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
40605390be7dSMatthew G. Knepley }
40615390be7dSMatthew G. Knepley 
40625390be7dSMatthew G. Knepley // Insert faces and their closures, marked by depth
40635390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Faces(DM dm, DMLabel label, PetscInt n, const PetscInt faces[])
40645390be7dSMatthew G. Knepley {
40655390be7dSMatthew G. Knepley   PetscFunctionBegin;
40665390be7dSMatthew G. Knepley   for (PetscInt p = 0; p < n; ++p) {
40675390be7dSMatthew G. Knepley     const PetscInt point   = faces[p];
40685390be7dSMatthew G. Knepley     PetscInt      *closure = NULL;
40695390be7dSMatthew G. Knepley     PetscInt       clSize, pdepth;
40705390be7dSMatthew G. Knepley 
40715390be7dSMatthew G. Knepley     PetscCall(DMPlexGetPointDepth(dm, point, &pdepth));
40725390be7dSMatthew G. Knepley     PetscCall(DMLabelSetValue(label, point, pdepth));
40735390be7dSMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure));
40745390be7dSMatthew G. Knepley     for (PetscInt cl = 0; cl < clSize * 2; cl += 2) {
40755390be7dSMatthew G. Knepley       PetscCall(DMPlexGetPointDepth(dm, closure[cl], &pdepth));
40765390be7dSMatthew G. Knepley       PetscCall(DMLabelSetValue(label, closure[cl], pdepth));
40775390be7dSMatthew G. Knepley     }
40785390be7dSMatthew G. Knepley     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure));
40795390be7dSMatthew G. Knepley   }
40805390be7dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
40815390be7dSMatthew G. Knepley }
40825390be7dSMatthew G. Knepley 
40834e22dd4cSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *flg);
40844e22dd4cSMatthew G. Knepley 
40855dca41c3SJed Brown const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "zbox", "unknown", "DMPlexShape", "DM_SHAPE_", NULL};
40869318fe57SMatthew G. Knepley 
4087d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm)
4088d71ae5a4SJacob Faibussowitsch {
40899318fe57SMatthew G. Knepley   DMPlexShape    shape   = DM_SHAPE_BOX;
40909318fe57SMatthew G. Knepley   DMPolytopeType cell    = DM_POLYTOPE_TRIANGLE;
40919318fe57SMatthew G. Knepley   PetscInt       dim     = 2;
40929318fe57SMatthew G. Knepley   PetscBool      simplex = PETSC_TRUE, interpolate = PETSC_TRUE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE;
4093d0812dedSMatthew G. Knepley   PetscBool      flg, flg2, fflg, strflg, bdfflg, nameflg;
40949318fe57SMatthew G. Knepley   MPI_Comm       comm;
4095ed5e4e85SVaclav Hapla   char           filename[PETSC_MAX_PATH_LEN]   = "<unspecified>";
4096ed5e4e85SVaclav Hapla   char           bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>";
4097ed5e4e85SVaclav Hapla   char           plexname[PETSC_MAX_PATH_LEN]   = "";
40984e22dd4cSMatthew G. Knepley   const char    *option;
40999318fe57SMatthew G. Knepley 
41009318fe57SMatthew G. Knepley   PetscFunctionBegin;
4101708be2fdSJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromOptions, dm, 0, 0, 0));
41029566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
41039318fe57SMatthew G. Knepley   /* TODO Turn this into a registration interface */
41049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg));
4105d0812dedSMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_plex_file_contents", "Contents of a file format in a string", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &strflg));
41069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg));
41079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg));
41089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL));
41099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL));
41109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg));
41119566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0));
41129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg));
41139566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg));
41149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg));
41159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2));
41169566063dSJacob Faibussowitsch   if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure));
41179318fe57SMatthew G. Knepley 
411861a622f3SMatthew G. Knepley   switch (cell) {
411961a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT:
412061a622f3SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
412161a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
412261a622f3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
412361a622f3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
412461a622f3SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
4125d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_HEXAHEDRON:
4126d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_TRUE;
4127d71ae5a4SJacob Faibussowitsch     break;
4128d71ae5a4SJacob Faibussowitsch   default:
4129d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_FALSE;
4130d71ae5a4SJacob Faibussowitsch     break;
413161a622f3SMatthew G. Knepley   }
413261a622f3SMatthew G. Knepley 
41339318fe57SMatthew G. Knepley   if (fflg) {
41349318fe57SMatthew G. Knepley     DM          dmnew;
41351e4a82c4SMatthew G. Knepley     const char *name;
41369318fe57SMatthew G. Knepley 
41371e4a82c4SMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
41381e4a82c4SMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, nameflg ? plexname : name, interpolate, &dmnew));
41395de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
414069d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
41419318fe57SMatthew G. Knepley   } else if (refDomain) {
41429566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell));
41439318fe57SMatthew G. Knepley   } else if (bdfflg) {
41449318fe57SMatthew G. Knepley     DM          bdm, dmnew;
41451e4a82c4SMatthew G. Knepley     const char *name;
41469318fe57SMatthew G. Knepley 
41471e4a82c4SMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
41481e4a82c4SMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, nameflg ? plexname : name, interpolate, &bdm));
41499566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_"));
41509566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(bdm));
41519566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew));
41529566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&bdm));
41535de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
415469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
4155d0812dedSMatthew G. Knepley   } else if (strflg) {
4156d0812dedSMatthew G. Knepley     DM          dmnew;
4157d0812dedSMatthew G. Knepley     PetscViewer viewer;
4158d0812dedSMatthew G. Knepley     const char *contents;
4159d0812dedSMatthew G. Knepley     char       *strname;
4160d0812dedSMatthew G. Knepley     char        tmpdir[PETSC_MAX_PATH_LEN];
4161d0812dedSMatthew G. Knepley     char        tmpfilename[PETSC_MAX_PATH_LEN];
4162d0812dedSMatthew G. Knepley     char        name[PETSC_MAX_PATH_LEN];
4163d0812dedSMatthew G. Knepley     MPI_Comm    comm;
4164d0812dedSMatthew G. Knepley     PetscMPIInt rank;
4165d0812dedSMatthew G. Knepley 
4166d0812dedSMatthew G. Knepley     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4167d0812dedSMatthew G. Knepley     PetscCallMPI(MPI_Comm_rank(comm, &rank));
4168d0812dedSMatthew G. Knepley     PetscCall(PetscStrchr(filename, ':', &strname));
4169d0812dedSMatthew G. Knepley     PetscCheck(strname, comm, PETSC_ERR_ARG_WRONG, "File contents must have the form \"ext:string_name\", not %s", filename);
4170d0812dedSMatthew G. Knepley     strname[0] = '\0';
4171d0812dedSMatthew G. Knepley     ++strname;
4172d0812dedSMatthew G. Knepley     PetscCall(PetscDLSym(NULL, strname, (void **)&contents));
4173d0812dedSMatthew G. Knepley     PetscCheck(contents, comm, PETSC_ERR_ARG_WRONG, "Could not locate mesh string %s", strname);
4174d0812dedSMatthew G. Knepley     PetscCall(PetscGetTmp(comm, tmpdir, PETSC_MAX_PATH_LEN));
4175ed32af8cSMatthew G. Knepley     PetscCall(PetscStrlcat(tmpdir, "/meshXXXXXX", PETSC_MAX_PATH_LEN));
4176ed32af8cSMatthew G. Knepley     PetscCall(PetscMkdtemp(tmpdir));
4177ed32af8cSMatthew G. Knepley     PetscCall(PetscSNPrintf(tmpfilename, PETSC_MAX_PATH_LEN, "%s/mesh.%s", tmpdir, filename));
4178d0812dedSMatthew G. Knepley     PetscCall(PetscViewerASCIIOpen(comm, tmpfilename, &viewer));
4179d0812dedSMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", contents));
4180d0812dedSMatthew G. Knepley     PetscCall(PetscViewerDestroy(&viewer));
4181d0812dedSMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), tmpfilename, plexname, interpolate, &dmnew));
4182ed32af8cSMatthew G. Knepley     PetscCall(PetscRMTree(tmpdir));
4183d0812dedSMatthew G. Knepley     PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%s Mesh", strname));
4184d0812dedSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, name));
4185d0812dedSMatthew G. Knepley     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
4186d0812dedSMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
41879318fe57SMatthew G. Knepley   } else {
41889566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape]));
41899318fe57SMatthew G. Knepley     switch (shape) {
4190669647acSMatthew G. Knepley     case DM_SHAPE_BOX:
41915dca41c3SJed Brown     case DM_SHAPE_ZBOX:
4192669647acSMatthew G. Knepley     case DM_SHAPE_ANNULUS: {
41939318fe57SMatthew G. Knepley       PetscInt       faces[3]  = {0, 0, 0};
41949318fe57SMatthew G. Knepley       PetscReal      lower[3]  = {0, 0, 0};
41959318fe57SMatthew G. Knepley       PetscReal      upper[3]  = {1, 1, 1};
41969318fe57SMatthew G. Knepley       DMBoundaryType bdt[3]    = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
4197669647acSMatthew G. Knepley       PetscBool      isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE;
41989318fe57SMatthew G. Knepley       PetscInt       i, n;
41999318fe57SMatthew G. Knepley 
42009318fe57SMatthew G. Knepley       n = dim;
42019318fe57SMatthew G. Knepley       for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim);
42029566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
42039318fe57SMatthew G. Knepley       n = 3;
42049566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
420563a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
42069318fe57SMatthew G. Knepley       n = 3;
42079566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
420863a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
42099318fe57SMatthew G. Knepley       n = 3;
42109566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
421163a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
4212669647acSMatthew G. Knepley 
4213669647acSMatthew G. Knepley       PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented");
4214669647acSMatthew G. Knepley       if (isAnnular)
4215669647acSMatthew G. Knepley         for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC;
4216669647acSMatthew G. Knepley 
42179318fe57SMatthew G. Knepley       switch (cell) {
421861a622f3SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
42199566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt));
4220d410b0cfSMatthew G. Knepley         if (!interpolate) {
4221d410b0cfSMatthew G. Knepley           DM udm;
4222d410b0cfSMatthew G. Knepley 
42239566063dSJacob Faibussowitsch           PetscCall(DMPlexUninterpolate(dm, &udm));
422469d8a87bSksagiyam           PetscCall(DMPlexReplace_Internal(dm, &udm));
4225d410b0cfSMatthew G. Knepley         }
42269318fe57SMatthew G. Knepley         break;
4227d71ae5a4SJacob Faibussowitsch       default:
42285dca41c3SJed Brown         PetscCall(DMPlexCreateBoxMesh_Internal(dm, shape, dim, simplex, faces, lower, upper, bdt, interpolate));
4229d71ae5a4SJacob Faibussowitsch         break;
42309318fe57SMatthew G. Knepley       }
4231669647acSMatthew G. Knepley       if (isAnnular) {
4232669647acSMatthew G. Knepley         DM          cdm;
4233669647acSMatthew G. Knepley         PetscDS     cds;
4234669647acSMatthew G. Knepley         PetscScalar bounds[2] = {lower[0], upper[0]};
4235669647acSMatthew G. Knepley 
4236669647acSMatthew G. Knepley         // Fix coordinates for annular region
4237669647acSMatthew G. Knepley         PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL));
4238669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinatesLocal(dm, NULL));
4239669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinates(dm, NULL));
4240e44f6aebSMatthew G. Knepley         PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL));
4241669647acSMatthew G. Knepley         PetscCall(DMGetCoordinateDM(dm, &cdm));
4242669647acSMatthew G. Knepley         PetscCall(DMGetDS(cdm, &cds));
4243669647acSMatthew G. Knepley         PetscCall(PetscDSSetConstants(cds, 2, bounds));
4244669647acSMatthew G. Knepley         PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus));
4245669647acSMatthew G. Knepley       }
42469371c9d4SSatish Balay     } break;
42479371c9d4SSatish Balay     case DM_SHAPE_BOX_SURFACE: {
42489318fe57SMatthew G. Knepley       PetscInt  faces[3] = {0, 0, 0};
42499318fe57SMatthew G. Knepley       PetscReal lower[3] = {0, 0, 0};
42509318fe57SMatthew G. Knepley       PetscReal upper[3] = {1, 1, 1};
42519318fe57SMatthew G. Knepley       PetscInt  i, n;
42529318fe57SMatthew G. Knepley 
42539318fe57SMatthew G. Knepley       n = dim + 1;
42549318fe57SMatthew G. Knepley       for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1));
42559566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
42569318fe57SMatthew G. Knepley       n = 3;
42579566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
425863a3b9bcSJacob 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);
42599318fe57SMatthew G. Knepley       n = 3;
42609566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
426163a3b9bcSJacob 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);
42629566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate));
42639371c9d4SSatish Balay     } break;
42649371c9d4SSatish Balay     case DM_SHAPE_SPHERE: {
42659318fe57SMatthew G. Knepley       PetscReal R = 1.0;
42669318fe57SMatthew G. Knepley 
42679566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg));
42689566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R));
42699371c9d4SSatish Balay     } break;
42709371c9d4SSatish Balay     case DM_SHAPE_BALL: {
42719318fe57SMatthew G. Knepley       PetscReal R = 1.0;
42729318fe57SMatthew G. Knepley 
42739566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg));
42749566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R));
42759371c9d4SSatish Balay     } break;
42769371c9d4SSatish Balay     case DM_SHAPE_CYLINDER: {
42779318fe57SMatthew G. Knepley       DMBoundaryType bdt = DM_BOUNDARY_NONE;
42789318fe57SMatthew G. Knepley       PetscInt       Nw  = 6;
427949704ca5SMatthew G. Knepley       PetscInt       Nr  = 0;
42809318fe57SMatthew G. Knepley 
42819566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL));
42829566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL));
428349704ca5SMatthew G. Knepley       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_refine", "Number of refinements before projection", "", Nr, &Nr, NULL));
42849318fe57SMatthew G. Knepley       switch (cell) {
4285d71ae5a4SJacob Faibussowitsch       case DM_POLYTOPE_TRI_PRISM_TENSOR:
4286d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate));
4287d71ae5a4SJacob Faibussowitsch         break;
4288d71ae5a4SJacob Faibussowitsch       default:
428949704ca5SMatthew G. Knepley         PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt, Nr));
4290d71ae5a4SJacob Faibussowitsch         break;
42919318fe57SMatthew G. Knepley       }
42929371c9d4SSatish Balay     } break;
4293b7f5c055SJed Brown     case DM_SHAPE_SCHWARZ_P: // fallthrough
42949371c9d4SSatish Balay     case DM_SHAPE_GYROID: {
4295b7f5c055SJed Brown       PetscInt       extent[3] = {1, 1, 1}, refine = 0, layers = 0, three;
4296b7f5c055SJed Brown       PetscReal      thickness   = 0.;
4297b7f5c055SJed Brown       DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
4298b7f5c055SJed Brown       DMPlexTPSType  tps_type    = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID;
42991436d7faSJed Brown       PetscBool      tps_distribute;
43009566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL));
43019566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL));
43029566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL));
43039566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL));
43049566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL));
43059566063dSJacob Faibussowitsch       PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute));
43069566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL));
43079566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness));
43089371c9d4SSatish Balay     } break;
43099371c9d4SSatish Balay     case DM_SHAPE_DOUBLET: {
431005bd46c0SStefano Zampini       DM        dmnew;
431105bd46c0SStefano Zampini       PetscReal rl = 0.0;
431205bd46c0SStefano Zampini 
431305bd46c0SStefano Zampini       PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL));
431405bd46c0SStefano Zampini       PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew));
43155de52c6dSVaclav Hapla       PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
431669d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &dmnew));
43179371c9d4SSatish Balay     } break;
4318cfb853baSMatthew G. Knepley     case DM_SHAPE_HYPERCUBIC: {
4319cfb853baSMatthew G. Knepley       PetscInt       *edges;
4320cfb853baSMatthew G. Knepley       PetscReal      *lower, *upper;
4321cfb853baSMatthew G. Knepley       DMBoundaryType *bdt;
4322cfb853baSMatthew G. Knepley       PetscInt        n, d;
4323cfb853baSMatthew G. Knepley 
4324cfb853baSMatthew G. Knepley       *useCoordSpace = PETSC_FALSE;
4325cfb853baSMatthew G. Knepley       PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt));
4326cfb853baSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
4327cfb853baSMatthew G. Knepley         edges[d] = 1;
4328cfb853baSMatthew G. Knepley         lower[d] = 0.;
4329cfb853baSMatthew G. Knepley         upper[d] = 1.;
4330cfb853baSMatthew G. Knepley         bdt[d]   = DM_BOUNDARY_PERIODIC;
4331cfb853baSMatthew G. Knepley       }
4332cfb853baSMatthew G. Knepley       n = dim;
4333cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg));
4334cfb853baSMatthew G. Knepley       n = dim;
4335cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
4336cfb853baSMatthew G. Knepley       PetscCheck(!flg || n == dim, comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
4337cfb853baSMatthew G. Knepley       n = dim;
4338cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
4339cfb853baSMatthew G. Knepley       PetscCheck(!flg || n == dim, comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
4340cfb853baSMatthew G. Knepley       n = dim;
4341cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
4342cfb853baSMatthew G. Knepley       PetscCheck(!flg || n == dim, comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
4343cfb853baSMatthew G. Knepley       PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, bdt));
4344cfb853baSMatthew G. Knepley       PetscCall(PetscFree4(edges, lower, upper, bdt));
4345cfb853baSMatthew G. Knepley     } break;
4346d71ae5a4SJacob Faibussowitsch     default:
4347d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]);
43489318fe57SMatthew G. Knepley     }
43499318fe57SMatthew G. Knepley   }
43509566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
435148a46eb9SPierre Jolivet   if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname));
43524e22dd4cSMatthew G. Knepley   // Allow label creation
43534e22dd4cSMatthew G. Knepley   PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_label_", &option, NULL, &flg));
43544e22dd4cSMatthew G. Knepley   if (flg) {
43554e22dd4cSMatthew G. Knepley     DMLabel     label;
43564e22dd4cSMatthew G. Knepley     PetscInt    points[1024], n = 1024;
43574e22dd4cSMatthew G. Knepley     char        fulloption[PETSC_MAX_PATH_LEN];
43584e22dd4cSMatthew G. Knepley     const char *name = &option[14];
43594e22dd4cSMatthew G. Knepley 
43604e22dd4cSMatthew G. Knepley     PetscCall(DMCreateLabel(dm, name));
43614e22dd4cSMatthew G. Knepley     PetscCall(DMGetLabel(dm, name, &label));
43624e22dd4cSMatthew G. Knepley     fulloption[0] = '-';
43634e22dd4cSMatthew G. Knepley     fulloption[1] = 0;
43644e22dd4cSMatthew G. Knepley     PetscCall(PetscStrlcat(fulloption, option, PETSC_MAX_PATH_LEN));
43654e22dd4cSMatthew G. Knepley     PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, NULL));
43664e22dd4cSMatthew G. Knepley     for (PetscInt p = 0; p < n; ++p) PetscCall(DMLabelSetValue(label, points[p], 1));
43674e22dd4cSMatthew G. Knepley   }
4368dd0eeac9SMatthew G. Knepley   // Allow cohesive label creation
4369dd0eeac9SMatthew G. Knepley   //   Faces are input, completed, and all points are marked with their depth
4370dd0eeac9SMatthew G. Knepley   PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_cohesive_label_", &option, NULL, &flg));
4371dd0eeac9SMatthew G. Knepley   if (flg) {
4372dd0eeac9SMatthew G. Knepley     DMLabel   label;
4373dd0eeac9SMatthew G. Knepley     PetscInt  points[1024], n, pStart, pEnd, Nl = 1;
43745390be7dSMatthew G. Knepley     PetscBool noCreate = PETSC_FALSE;
4375dd0eeac9SMatthew G. Knepley     char      fulloption[PETSC_MAX_PATH_LEN];
4376dd0eeac9SMatthew G. Knepley     char      name[PETSC_MAX_PATH_LEN];
4377dd0eeac9SMatthew G. Knepley     size_t    len;
4378dd0eeac9SMatthew G. Knepley 
4379dd0eeac9SMatthew G. Knepley     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4380dd0eeac9SMatthew G. Knepley     PetscCall(PetscStrncpy(name, &option[23], PETSC_MAX_PATH_LEN));
4381dd0eeac9SMatthew G. Knepley     PetscCall(PetscStrlen(name, &len));
4382dd0eeac9SMatthew G. Knepley     if (name[len - 1] == '0') Nl = 10;
4383dd0eeac9SMatthew G. Knepley     for (PetscInt l = 0; l < Nl; ++l) {
43846497c311SBarry Smith       if (l > 0) name[len - 1] = (char)('0' + l);
4385dd0eeac9SMatthew G. Knepley       fulloption[0] = 0;
4386dd0eeac9SMatthew G. Knepley       PetscCall(PetscStrlcat(fulloption, "-dm_plex_cohesive_label_", 32));
4387dd0eeac9SMatthew G. Knepley       PetscCall(PetscStrlcat(fulloption, name, PETSC_MAX_PATH_LEN - 32));
4388dd0eeac9SMatthew G. Knepley       n = 1024;
4389dd0eeac9SMatthew G. Knepley       PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, &flg));
4390dd0eeac9SMatthew G. Knepley       if (!flg) break;
43915390be7dSMatthew G. Knepley       PetscCall(DMHasLabel(dm, name, &noCreate));
43925390be7dSMatthew G. Knepley       if (noCreate) {
43935390be7dSMatthew G. Knepley         DMLabel         inlabel;
43945390be7dSMatthew G. Knepley         IS              pointIS;
43955390be7dSMatthew G. Knepley         const PetscInt *lpoints;
43965390be7dSMatthew G. Knepley         PetscInt        pdep, ln, inval = points[0];
43975390be7dSMatthew G. Knepley         char            newname[PETSC_MAX_PATH_LEN];
43985390be7dSMatthew G. Knepley 
43995390be7dSMatthew G. Knepley         PetscCheck(n == 1, comm, PETSC_ERR_ARG_WRONG, "Must specify a label value with this option");
44005390be7dSMatthew G. Knepley         PetscCall(DMGetLabel(dm, name, &inlabel));
44015390be7dSMatthew G. Knepley         PetscCall(DMLabelGetStratumIS(inlabel, inval, &pointIS));
44025390be7dSMatthew G. Knepley         PetscCall(ISGetLocalSize(pointIS, &ln));
44035390be7dSMatthew G. Knepley         PetscCall(ISGetIndices(pointIS, &lpoints));
44045390be7dSMatthew G. Knepley         PetscCall(DMPlexGetPointDepth(dm, lpoints[0], &pdep));
44055390be7dSMatthew G. Knepley         PetscCall(PetscSNPrintf(newname, PETSC_MAX_PATH_LEN, "%s%" PetscInt_FMT, name, points[0]));
44065390be7dSMatthew G. Knepley         PetscCall(DMCreateLabel(dm, newname));
44075390be7dSMatthew G. Knepley         PetscCall(DMGetLabel(dm, newname, &label));
44085390be7dSMatthew G. Knepley         if (!pdep) PetscCall(ProcessCohesiveLabel_Vertices(dm, label, inlabel, inval, ln, lpoints));
44095390be7dSMatthew G. Knepley         else PetscCall(ProcessCohesiveLabel_Faces(dm, label, ln, lpoints));
44105390be7dSMatthew G. Knepley         PetscCall(ISRestoreIndices(pointIS, &lpoints));
44115390be7dSMatthew G. Knepley         PetscCall(ISDestroy(&pointIS));
44125390be7dSMatthew G. Knepley       } else {
4413dd0eeac9SMatthew G. Knepley         PetscCall(DMCreateLabel(dm, name));
4414dd0eeac9SMatthew G. Knepley         PetscCall(DMGetLabel(dm, name, &label));
4415dd0eeac9SMatthew G. Knepley         if (pStart >= pEnd) n = 0;
44165390be7dSMatthew G. Knepley         PetscCall(ProcessCohesiveLabel_Faces(dm, label, n, points));
4417dd0eeac9SMatthew G. Knepley       }
4418dd0eeac9SMatthew G. Knepley       PetscCall(DMPlexOrientLabel(dm, label));
44190542aa8cSMatthew G. Knepley       PetscCall(DMPlexLabelCohesiveComplete(dm, label, NULL, 1, PETSC_FALSE, PETSC_FALSE, NULL));
4420dd0eeac9SMatthew G. Knepley     }
4421dd0eeac9SMatthew G. Knepley   }
44225390be7dSMatthew G. Knepley   PetscCall(DMViewFromOptions(dm, NULL, "-created_dm_view"));
4423708be2fdSJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromOptions, dm, 0, 0, 0));
44243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44250a6ba040SMatthew G. Knepley }
44260a6ba040SMatthew G. Knepley 
4427d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
4428d71ae5a4SJacob Faibussowitsch {
44290a6ba040SMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
44307f9d8d6cSVaclav Hapla   PetscBool flg, flg2;
44319318fe57SMatthew G. Knepley   char      bdLabel[PETSC_MAX_PATH_LEN];
4432adc21957SMatthew G. Knepley   char      method[PETSC_MAX_PATH_LEN];
44330a6ba040SMatthew G. Knepley 
44340a6ba040SMatthew G. Knepley   PetscFunctionBegin;
44350a6ba040SMatthew G. Knepley   /* Handle viewing */
44369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL));
44375962854dSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level for all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0));
44385962854dSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fvm", "Debug output level for all fvm computations", "DMPlexSNESComputeResidualFVM", 0, &mesh->printFVM, NULL, 0));
44399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL));
44409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0));
4441f5867de0SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0));
4442a77a5016SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_project", "Debug output level all projection computations", "DMPlexProject", 0, &mesh->printProject, NULL, 0));
44439566063dSJacob Faibussowitsch   PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg));
44449566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscLogDefaultBegin());
44459318fe57SMatthew G. Knepley   /* Labeling */
44469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg));
44479566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel));
4448953fc75cSMatthew G. Knepley   /* Point Location */
44499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL));
44500848f4b5SMatthew G. Knepley   /* Partitioning and distribution */
44519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL));
4452d02c7345SMatthew G. Knepley   /* Reordering */
4453adc21957SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_reorder_section", "Compute point permutation for local section", "DMReorderSectionSetDefault", PETSC_FALSE, &flg2, &flg));
4454adc21957SMatthew G. Knepley   if (flg) PetscCall(DMReorderSectionSetDefault(dm, flg2 ? DM_REORDER_DEFAULT_TRUE : DM_REORDER_DEFAULT_FALSE));
4455adc21957SMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_reorder_section_type", "Reordering method for local section", "DMReorderSectionSetType", method, method, PETSC_MAX_PATH_LEN, &flg));
4456adc21957SMatthew G. Knepley   if (flg) PetscCall(DMReorderSectionSetType(dm, method));
44572e62ab5aSMatthew G. Knepley   /* Generation and remeshing */
44589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL));
4459b29cfa1cSToby Isaac   /* Projection behavior */
4460d5b43468SJose E. Roman   PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0));
44619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL));
4462f12cf164SMatthew G. Knepley   /* Checking structure */
4463f12cf164SMatthew G. Knepley   {
44647f9d8d6cSVaclav Hapla     PetscBool all = PETSC_FALSE;
4465f12cf164SMatthew G. Knepley 
44667f9d8d6cSVaclav Hapla     PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL));
44677f9d8d6cSVaclav Hapla     if (all) {
44687f9d8d6cSVaclav Hapla       PetscCall(DMPlexCheck(dm));
44697f9d8d6cSVaclav Hapla     } else {
44709566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2));
44717f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm));
44729566063dSJacob 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));
44737f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0));
44749566063dSJacob 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));
44757f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0));
44769566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2));
44777f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm));
44789566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2));
4479d7d32a9aSMatthew G. Knepley       if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
44809566063dSJacob 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));
44817f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm));
44827f9d8d6cSVaclav Hapla     }
44839566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2));
44849566063dSJacob Faibussowitsch     if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE));
4485f12cf164SMatthew G. Knepley   }
44869318fe57SMatthew G. Knepley   {
44879318fe57SMatthew G. Knepley     PetscReal scale = 1.0;
44884f3833eaSMatthew G. Knepley 
44899566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg));
44909318fe57SMatthew G. Knepley     if (flg) {
44919318fe57SMatthew G. Knepley       Vec coordinates, coordinatesLocal;
44929318fe57SMatthew G. Knepley 
44939566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinates(dm, &coordinates));
44949566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
44959566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinates, scale));
44969566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinatesLocal, scale));
44979318fe57SMatthew G. Knepley     }
44989318fe57SMatthew G. Knepley   }
44999566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner));
45003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
450168d4fef7SMatthew G. Knepley }
450268d4fef7SMatthew G. Knepley 
4503d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap)
4504d71ae5a4SJacob Faibussowitsch {
4505c506a872SMatthew G. Knepley   PetscInt  numOvLabels = 16, numOvExLabels = 16;
4506c506a872SMatthew G. Knepley   char     *ovLabelNames[16], *ovExLabelNames[16];
4507c506a872SMatthew G. Knepley   PetscInt  numOvValues = 16, numOvExValues = 16, l;
4508c506a872SMatthew G. Knepley   PetscBool flg;
4509c506a872SMatthew G. Knepley 
4510c506a872SMatthew G. Knepley   PetscFunctionBegin;
4511c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0));
4512c506a872SMatthew G. Knepley   PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg));
4513c506a872SMatthew G. Knepley   if (!flg) numOvLabels = 0;
4514c506a872SMatthew G. Knepley   if (numOvLabels) {
4515c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvLabels = numOvLabels;
4516c506a872SMatthew G. Knepley     for (l = 0; l < numOvLabels; ++l) {
4517c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l]));
4518c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]);
4519c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovLabelNames[l]));
4520c506a872SMatthew G. Knepley     }
4521c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg));
4522c506a872SMatthew G. Knepley     if (!flg) numOvValues = 0;
4523c506a872SMatthew 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);
4524c506a872SMatthew G. Knepley 
4525c506a872SMatthew G. Knepley     PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg));
4526c506a872SMatthew G. Knepley     if (!flg) numOvExLabels = 0;
4527c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels;
4528c506a872SMatthew G. Knepley     for (l = 0; l < numOvExLabels; ++l) {
4529c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l]));
4530c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]);
4531c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovExLabelNames[l]));
4532c506a872SMatthew G. Knepley     }
4533c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg));
4534c506a872SMatthew G. Knepley     if (!flg) numOvExValues = 0;
4535c506a872SMatthew 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);
4536c506a872SMatthew G. Knepley   }
45373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4538c506a872SMatthew G. Knepley }
4539c506a872SMatthew G. Knepley 
4540d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
4541d71ae5a4SJacob Faibussowitsch {
4542bdf63967SMatthew G. Knepley   PetscFunctionList    ordlist;
4543bdf63967SMatthew G. Knepley   char                 oname[256];
45444e22dd4cSMatthew G. Knepley   char                 sublabelname[PETSC_MAX_PATH_LEN] = "";
4545adc21957SMatthew G. Knepley   DMReorderDefaultFlag reorder;
4546d410b0cfSMatthew G. Knepley   PetscReal            volume    = -1.0;
45479318fe57SMatthew G. Knepley   PetscInt             prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim;
45481b742f01SMatthew G. Knepley   PetscBool            uniformOrig = PETSC_FALSE, created = PETSC_FALSE, uniform = PETSC_TRUE, distribute, saveSF = PETSC_FALSE, interpolate = PETSC_TRUE, coordSpace = PETSC_TRUE, remap = PETSC_TRUE, ghostCells = PETSC_FALSE, isHierarchy, flg;
454968d4fef7SMatthew G. Knepley 
455068d4fef7SMatthew G. Knepley   PetscFunctionBegin;
4551d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options");
4552dd4c3f67SMatthew G. Knepley   if (dm->cloneOpts) goto non_refine;
45539318fe57SMatthew G. Knepley   /* Handle automatic creation */
45549566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
45556bc1bd01Sksagiyam   if (dim < 0) {
45566bc1bd01Sksagiyam     PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));
45576bc1bd01Sksagiyam     created = PETSC_TRUE;
45586bc1bd01Sksagiyam   }
45596bc1bd01Sksagiyam   PetscCall(DMGetDimension(dm, &dim));
4560d89e6e46SMatthew G. Knepley   /* Handle interpolation before distribution */
45619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg));
4562d89e6e46SMatthew G. Knepley   if (flg) {
4563d89e6e46SMatthew G. Knepley     DMPlexInterpolatedFlag interpolated;
4564d89e6e46SMatthew G. Knepley 
45659566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpolated));
4566d89e6e46SMatthew G. Knepley     if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) {
4567d89e6e46SMatthew G. Knepley       DM udm;
4568d89e6e46SMatthew G. Knepley 
45699566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(dm, &udm));
457069d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &udm));
4571d89e6e46SMatthew G. Knepley     } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) {
4572d89e6e46SMatthew G. Knepley       DM idm;
4573d89e6e46SMatthew G. Knepley 
45749566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(dm, &idm));
457569d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &idm));
4576d89e6e46SMatthew G. Knepley     }
4577d89e6e46SMatthew G. Knepley   }
45784e22dd4cSMatthew G. Knepley   // Handle submesh selection before distribution
45794e22dd4cSMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_plex_submesh", "Label to use for submesh selection", "", sublabelname, sublabelname, PETSC_MAX_PATH_LEN, &flg));
45804e22dd4cSMatthew G. Knepley   if (flg) {
45814e22dd4cSMatthew G. Knepley     DM              subdm;
45824e22dd4cSMatthew G. Knepley     DMLabel         label;
45834e22dd4cSMatthew G. Knepley     IS              valueIS, pointIS;
45844e22dd4cSMatthew G. Knepley     const PetscInt *values, *points;
45854e22dd4cSMatthew G. Knepley     PetscBool       markedFaces = PETSC_FALSE;
45864e22dd4cSMatthew G. Knepley     PetscInt        Nv, value, Np;
45874e22dd4cSMatthew G. Knepley 
45884e22dd4cSMatthew G. Knepley     PetscCall(DMGetLabel(dm, sublabelname, &label));
45894e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetNumValues(label, &Nv));
45904e22dd4cSMatthew G. Knepley     PetscCheck(Nv == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only a single label value is currently supported for submesh selection, not %" PetscInt_FMT, Nv);
45914e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetValueIS(label, &valueIS));
45924e22dd4cSMatthew G. Knepley     PetscCall(ISGetIndices(valueIS, &values));
45934e22dd4cSMatthew G. Knepley     value = values[0];
45944e22dd4cSMatthew G. Knepley     PetscCall(ISRestoreIndices(valueIS, &values));
45954e22dd4cSMatthew G. Knepley     PetscCall(ISDestroy(&valueIS));
45964e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetStratumSize(label, value, &Np));
45974e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetStratumIS(label, value, &pointIS));
45984e22dd4cSMatthew G. Knepley     PetscCall(ISGetIndices(pointIS, &points));
45994e22dd4cSMatthew G. Knepley     for (PetscInt p = 0; p < Np; ++p) {
46004e22dd4cSMatthew G. Knepley       PetscInt pdepth;
46014e22dd4cSMatthew G. Knepley 
46024e22dd4cSMatthew G. Knepley       PetscCall(DMPlexGetPointDepth(dm, points[p], &pdepth));
46034e22dd4cSMatthew G. Knepley       if (pdepth) {
46044e22dd4cSMatthew G. Knepley         markedFaces = PETSC_TRUE;
46054e22dd4cSMatthew G. Knepley         break;
46064e22dd4cSMatthew G. Knepley       }
46074e22dd4cSMatthew G. Knepley     }
46084e22dd4cSMatthew G. Knepley     PetscCall(ISRestoreIndices(pointIS, &points));
46094e22dd4cSMatthew G. Knepley     PetscCall(ISDestroy(&pointIS));
46104e22dd4cSMatthew G. Knepley     PetscCall(DMPlexCreateSubmesh(dm, label, value, markedFaces, &subdm));
46114e22dd4cSMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &subdm));
46124e22dd4cSMatthew G. Knepley     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
46134e22dd4cSMatthew G. Knepley   }
46149b44eab4SMatthew G. Knepley   /* Handle DMPlex refinement before distribution */
46159566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig));
46169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0));
46179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
46189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg));
46199566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform));
46209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg));
46219318fe57SMatthew G. Knepley   if (flg) {
46229566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE));
46239566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(dm, volume));
46249318fe57SMatthew G. Knepley     prerefine = PetscMax(prerefine, 1);
46259318fe57SMatthew G. Knepley   }
4626b23db253SStefano Zampini   if (prerefine) PetscCall(DMLocalizeCoordinates(dm));
46279b44eab4SMatthew G. Knepley   for (r = 0; r < prerefine; ++r) {
46289b44eab4SMatthew G. Knepley     DM             rdm;
46299b44eab4SMatthew G. Knepley     PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
46309b44eab4SMatthew G. Knepley 
4631dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
46329566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
463369d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &rdm));
4634dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
463561a622f3SMatthew G. Knepley     if (coordFunc && remap) {
46369566063dSJacob Faibussowitsch       PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
46379b44eab4SMatthew G. Knepley       ((DM_Plex *)dm->data)->coordFunc = coordFunc;
46389b44eab4SMatthew G. Knepley     }
46399b44eab4SMatthew G. Knepley   }
46409566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig));
46419318fe57SMatthew G. Knepley   /* Handle DMPlex extrusion before distribution */
46429566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0));
46439318fe57SMatthew G. Knepley   if (extLayers) {
46449318fe57SMatthew G. Knepley     DM edm;
46459318fe57SMatthew G. Knepley 
46469566063dSJacob Faibussowitsch     PetscCall(DMExtrude(dm, extLayers, &edm));
464769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
464848d16a33SMatthew G. Knepley     ((DM_Plex *)dm->data)->coordFunc = NULL;
4649dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
4650d410b0cfSMatthew G. Knepley     extLayers = 0;
46515e17fc22SAidan Hamilton     PetscCall(DMGetDimension(dm, &dim));
46529318fe57SMatthew G. Knepley   }
4653bdf63967SMatthew G. Knepley   /* Handle DMPlex reordering before distribution */
46546bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dm, &reorder));
46559566063dSJacob Faibussowitsch   PetscCall(MatGetOrderingList(&ordlist));
46566bc1bd01Sksagiyam   PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname)));
46579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg));
4658adc21957SMatthew G. Knepley   if (reorder == DM_REORDER_DEFAULT_TRUE || flg) {
4659bdf63967SMatthew G. Knepley     DM pdm;
4660bdf63967SMatthew G. Knepley     IS perm;
4661bdf63967SMatthew G. Knepley 
46629566063dSJacob Faibussowitsch     PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm));
46639566063dSJacob Faibussowitsch     PetscCall(DMPlexPermute(dm, perm, &pdm));
46649566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&perm));
466569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &pdm));
4666dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
4667bdf63967SMatthew G. Knepley   }
46689b44eab4SMatthew G. Knepley   /* Handle DMPlex distribution */
46699566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dm, &distribute));
4670c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL));
4671a286e215SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute_save_sf", "Flag to save the migration SF", "DMPlexSetMigrationSF", saveSF, &saveSF, NULL));
4672dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap));
46739b44eab4SMatthew G. Knepley   if (distribute) {
46749b44eab4SMatthew G. Knepley     DM               pdm = NULL;
46759b44eab4SMatthew G. Knepley     PetscPartitioner part;
4676a286e215SMatthew G. Knepley     PetscSF          sfMigration;
46779b44eab4SMatthew G. Knepley 
46789566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
46799566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
4680a286e215SMatthew G. Knepley     PetscCall(DMPlexDistribute(dm, overlap, &sfMigration, &pdm));
468148a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
4682a286e215SMatthew G. Knepley     if (saveSF) PetscCall(DMPlexSetMigrationSF(dm, sfMigration));
4683a286e215SMatthew G. Knepley     PetscCall(PetscSFDestroy(&sfMigration));
46849b44eab4SMatthew G. Knepley   }
46854054ae39SJames Wright 
46864054ae39SJames Wright   {
46874054ae39SJames Wright     PetscBool useBoxLabel = PETSC_FALSE;
46884054ae39SJames Wright     PetscCall(PetscOptionsBool("-dm_plex_box_label", "Create 'Face Sets' assuming boundary faces align with cartesian directions", "DMCreate", useBoxLabel, &useBoxLabel, NULL));
46894054ae39SJames Wright     if (useBoxLabel) PetscCall(DMPlexSetBoxLabel_Internal(dm));
46904054ae39SJames Wright   }
4691d2b2dc1eSMatthew G. Knepley   /* Must check CEED options before creating function space for coordinates */
4692d2b2dc1eSMatthew G. Knepley   {
4693d2b2dc1eSMatthew G. Knepley     PetscBool useCeed = PETSC_FALSE, flg;
4694d2b2dc1eSMatthew G. Knepley 
4695d2b2dc1eSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_plex_use_ceed", "Use LibCEED as the FEM backend", "DMPlexSetUseCeed", useCeed, &useCeed, &flg));
4696d2b2dc1eSMatthew G. Knepley     if (flg) PetscCall(DMPlexSetUseCeed(dm, useCeed));
4697d2b2dc1eSMatthew G. Knepley   }
46989318fe57SMatthew G. Knepley   /* Create coordinate space */
46999318fe57SMatthew G. Knepley   if (created) {
470061a622f3SMatthew G. Knepley     DM_Plex  *mesh   = (DM_Plex *)dm->data;
4701e44f6aebSMatthew G. Knepley     PetscInt  degree = 1, deg;
47025515ebd3SMatthew G. Knepley     PetscInt  height = 0;
47035515ebd3SMatthew G. Knepley     DM        cdm;
4704c3db174cSMatthew G. Knepley     PetscBool flg, localize = PETSC_TRUE, sparseLocalize = PETSC_TRUE;
47059318fe57SMatthew G. Knepley 
47069566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg));
47079566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, &degree, NULL));
4708e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDegree_Internal(dm, &deg));
4709e44f6aebSMatthew G. Knepley     if (coordSpace && deg <= 1) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_TRUE, mesh->coordFunc));
47105515ebd3SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
471161a622f3SMatthew G. Knepley     if (flg && !coordSpace) {
471261a622f3SMatthew G. Knepley       PetscDS      cds;
471361a622f3SMatthew G. Knepley       PetscObject  obj;
471461a622f3SMatthew G. Knepley       PetscClassId id;
471561a622f3SMatthew G. Knepley 
47169566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdm, &cds));
47179566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
47189566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
471961a622f3SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
472061a622f3SMatthew G. Knepley         PetscContainer dummy;
472161a622f3SMatthew G. Knepley 
47229566063dSJacob Faibussowitsch         PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy));
47239566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates"));
47249566063dSJacob Faibussowitsch         PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy));
47259566063dSJacob Faibussowitsch         PetscCall(PetscContainerDestroy(&dummy));
47269566063dSJacob Faibussowitsch         PetscCall(DMClearDS(cdm));
472761a622f3SMatthew G. Knepley       }
472861a622f3SMatthew G. Knepley       mesh->coordFunc = NULL;
472961a622f3SMatthew G. Knepley     }
4730c3db174cSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_localize", "Localize mesh coordinates", "", localize, &localize, NULL));
4731c3db174cSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "DMSetSparseLocalize", sparseLocalize, &sparseLocalize, &flg));
4732c3db174cSMatthew G. Knepley     if (flg) PetscCall(DMSetSparseLocalize(dm, sparseLocalize));
47335515ebd3SMatthew G. Knepley     PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg));
47345515ebd3SMatthew G. Knepley     if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height));
4735c3db174cSMatthew G. Knepley     if (localize) PetscCall(DMLocalizeCoordinates(dm));
47369318fe57SMatthew G. Knepley   }
473768d4fef7SMatthew G. Knepley   /* Handle DMPlex refinement */
473861a622f3SMatthew G. Knepley   remap = PETSC_TRUE;
47399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0));
47409566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
47419566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0));
47429566063dSJacob Faibussowitsch   if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
474368d4fef7SMatthew G. Knepley   if (refine && isHierarchy) {
4744acdc6f61SToby Isaac     DM *dms, coarseDM;
474568d4fef7SMatthew G. Knepley 
47469566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &coarseDM));
47479566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarseDM));
47489566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(refine, &dms));
47499566063dSJacob Faibussowitsch     PetscCall(DMRefineHierarchy(dm, refine, dms));
475068d4fef7SMatthew G. Knepley     /* Total hack since we do not pass in a pointer */
47519566063dSJacob Faibussowitsch     PetscCall(DMPlexSwap_Static(dm, dms[refine - 1]));
475268d4fef7SMatthew G. Knepley     if (refine == 1) {
47539566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[0]));
47549566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
475568d4fef7SMatthew G. Knepley     } else {
47569566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[refine - 2]));
47579566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
47589566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1]));
47599566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE));
476068d4fef7SMatthew G. Knepley     }
47619566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM));
47629566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coarseDM));
476368d4fef7SMatthew G. Knepley     /* Free DMs */
476468d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
4765dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
47669566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
476768d4fef7SMatthew G. Knepley     }
47689566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
476968d4fef7SMatthew G. Knepley   } else {
477068d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
47719318fe57SMatthew G. Knepley       DM             rdm;
477251a74b61SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
477368d4fef7SMatthew G. Knepley 
4774dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
47759566063dSJacob Faibussowitsch       PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
477668d4fef7SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
477769d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
4778dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
477961a622f3SMatthew G. Knepley       if (coordFunc && remap) {
47809566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
478151a74b61SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
478251a74b61SMatthew G. Knepley       }
478368d4fef7SMatthew G. Knepley     }
478468d4fef7SMatthew G. Knepley   }
47853cf6fe12SMatthew G. Knepley   /* Handle DMPlex coarsening */
47869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0));
47879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0));
4788b653a561SMatthew G. Knepley   if (coarsen && isHierarchy) {
4789b653a561SMatthew G. Knepley     DM *dms;
4790b653a561SMatthew G. Knepley 
47919566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coarsen, &dms));
47929566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHierarchy(dm, coarsen, dms));
4793b653a561SMatthew G. Knepley     /* Free DMs */
4794b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
4795dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
47969566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
4797b653a561SMatthew G. Knepley     }
47989566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
4799b653a561SMatthew G. Knepley   } else {
4800b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
48019318fe57SMatthew G. Knepley       DM             cdm;
48029318fe57SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
48033cf6fe12SMatthew G. Knepley 
4804dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
48059566063dSJacob Faibussowitsch       PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm));
48063cf6fe12SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
480769d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &cdm));
4808dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
48099318fe57SMatthew G. Knepley       if (coordFunc) {
48109566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
48119318fe57SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
48129318fe57SMatthew G. Knepley       }
48133cf6fe12SMatthew G. Knepley     }
4814b653a561SMatthew G. Knepley   }
4815be664eb1SMatthew G. Knepley   // Handle coordinate remapping
4816be664eb1SMatthew G. Knepley   remap = PETSC_FALSE;
4817be664eb1SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_coord_remap", "Flag to control coordinate remapping", "", remap, &remap, NULL));
4818be664eb1SMatthew G. Knepley   if (remap) {
4819be664eb1SMatthew G. Knepley     DMPlexCoordMap map     = DM_COORD_MAP_NONE;
4820be664eb1SMatthew G. Knepley     PetscPointFunc mapFunc = NULL;
4821be664eb1SMatthew G. Knepley     PetscScalar    params[16];
4822f45b553cSPierre Jolivet     PetscInt       Np = PETSC_STATIC_ARRAY_LENGTH(params), cdim;
4823be664eb1SMatthew G. Knepley     MPI_Comm       comm;
4824be664eb1SMatthew G. Knepley 
4825be664eb1SMatthew G. Knepley     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4826be664eb1SMatthew G. Knepley     PetscCall(DMGetCoordinateDim(dm, &cdim));
4827be664eb1SMatthew G. Knepley     PetscCall(PetscOptionsScalarArray("-dm_coord_map_params", "Parameters for the coordinate remapping", "", params, &Np, &flg));
4828be664eb1SMatthew G. Knepley     if (!flg) Np = 0;
4829be664eb1SMatthew G. Knepley     // TODO Allow user to pass a map function by name
4830be664eb1SMatthew G. Knepley     PetscCall(PetscOptionsEnum("-dm_coord_map", "Coordinate mapping for built-in mesh", "", DMPlexCoordMaps, (PetscEnum)map, (PetscEnum *)&map, &flg));
4831be664eb1SMatthew G. Knepley     if (flg) {
4832be664eb1SMatthew G. Knepley       switch (map) {
4833be664eb1SMatthew G. Knepley       case DM_COORD_MAP_NONE:
4834be664eb1SMatthew G. Knepley         mapFunc = coordMap_identity;
4835be664eb1SMatthew G. Knepley         break;
4836be664eb1SMatthew G. Knepley       case DM_COORD_MAP_SHEAR:
4837be664eb1SMatthew G. Knepley         mapFunc = coordMap_shear;
4838be664eb1SMatthew G. Knepley         if (!Np) {
4839be664eb1SMatthew G. Knepley           Np        = cdim + 1;
4840be664eb1SMatthew G. Knepley           params[0] = 0;
4841be664eb1SMatthew G. Knepley           for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0;
4842be664eb1SMatthew G. Knepley         }
4843be664eb1SMatthew G. Knepley         PetscCheck(Np == cdim + 1, comm, PETSC_ERR_ARG_WRONG, "The shear coordinate map must have cdim + 1 = %" PetscInt_FMT " parameters, not %" PetscInt_FMT, cdim + 1, Np);
4844be664eb1SMatthew G. Knepley         break;
4845be664eb1SMatthew G. Knepley       case DM_COORD_MAP_FLARE:
4846be664eb1SMatthew G. Knepley         mapFunc = coordMap_flare;
4847be664eb1SMatthew G. Knepley         if (!Np) {
4848be664eb1SMatthew G. Knepley           Np        = cdim + 1;
4849be664eb1SMatthew G. Knepley           params[0] = 0;
4850be664eb1SMatthew G. Knepley           for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0;
4851be664eb1SMatthew G. Knepley         }
4852be664eb1SMatthew G. Knepley         PetscCheck(Np == cdim + 1, comm, PETSC_ERR_ARG_WRONG, "The flare coordinate map must have cdim + 1 = %" PetscInt_FMT " parameters, not %" PetscInt_FMT, cdim + 1, Np);
4853be664eb1SMatthew G. Knepley         break;
4854be664eb1SMatthew G. Knepley       case DM_COORD_MAP_ANNULUS:
4855be664eb1SMatthew G. Knepley         mapFunc = coordMap_annulus;
4856be664eb1SMatthew G. Knepley         if (!Np) {
4857be664eb1SMatthew G. Knepley           Np        = 2;
4858be664eb1SMatthew G. Knepley           params[0] = 1.;
4859be664eb1SMatthew G. Knepley           params[1] = 2.;
4860be664eb1SMatthew G. Knepley         }
4861be664eb1SMatthew G. Knepley         PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The annulus coordinate map must have 2 parameters, not %" PetscInt_FMT, Np);
4862be664eb1SMatthew G. Knepley         break;
4863be664eb1SMatthew G. Knepley       case DM_COORD_MAP_SHELL:
4864be664eb1SMatthew G. Knepley         mapFunc = coordMap_shell;
4865be664eb1SMatthew G. Knepley         if (!Np) {
4866be664eb1SMatthew G. Knepley           Np        = 2;
4867be664eb1SMatthew G. Knepley           params[0] = 1.;
4868be664eb1SMatthew G. Knepley           params[1] = 2.;
4869be664eb1SMatthew G. Knepley         }
4870be664eb1SMatthew G. Knepley         PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The spherical shell coordinate map must have 2 parameters, not %" PetscInt_FMT, Np);
4871be664eb1SMatthew G. Knepley         break;
4872be664eb1SMatthew G. Knepley       default:
4873be664eb1SMatthew G. Knepley         mapFunc = coordMap_identity;
4874be664eb1SMatthew G. Knepley       }
4875be664eb1SMatthew G. Knepley     }
4876be664eb1SMatthew G. Knepley     if (Np) {
4877be664eb1SMatthew G. Knepley       DM      cdm;
4878be664eb1SMatthew G. Knepley       PetscDS cds;
4879be664eb1SMatthew G. Knepley 
4880be664eb1SMatthew G. Knepley       PetscCall(DMGetCoordinateDM(dm, &cdm));
4881be664eb1SMatthew G. Knepley       PetscCall(DMGetDS(cdm, &cds));
4882be664eb1SMatthew G. Knepley       PetscCall(PetscDSSetConstants(cds, Np, params));
4883be664eb1SMatthew G. Knepley     }
4884be664eb1SMatthew G. Knepley     PetscCall(DMPlexRemapGeometry(dm, 0.0, mapFunc));
4885be664eb1SMatthew G. Knepley   }
4886909dfd52SMatthew G. Knepley   /* Handle ghost cells */
48879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL));
4888909dfd52SMatthew G. Knepley   if (ghostCells) {
4889909dfd52SMatthew G. Knepley     DM   gdm;
4890909dfd52SMatthew G. Knepley     char lname[PETSC_MAX_PATH_LEN];
4891909dfd52SMatthew G. Knepley 
4892909dfd52SMatthew G. Knepley     lname[0] = '\0';
48939566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg));
48949566063dSJacob Faibussowitsch     PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm));
489569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &gdm));
4896909dfd52SMatthew G. Knepley   }
48976913077dSMatthew G. Knepley   /* Handle 1D order */
4898adc21957SMatthew G. Knepley   if (reorder != DM_REORDER_DEFAULT_FALSE && dim == 1) {
48996913077dSMatthew G. Knepley     DM           cdm, rdm;
49006913077dSMatthew G. Knepley     PetscDS      cds;
49016913077dSMatthew G. Knepley     PetscObject  obj;
49026913077dSMatthew G. Knepley     PetscClassId id = PETSC_OBJECT_CLASSID;
49036913077dSMatthew G. Knepley     IS           perm;
49046bc1bd01Sksagiyam     PetscInt     Nf;
49056913077dSMatthew G. Knepley     PetscBool    distributed;
49066913077dSMatthew G. Knepley 
49079566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(dm, &distributed));
49089566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
49099566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
49109566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(cds, &Nf));
49116913077dSMatthew G. Knepley     if (Nf) {
49129566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
49139566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
49146913077dSMatthew G. Knepley     }
49156bc1bd01Sksagiyam     if (!distributed && id != PETSCFE_CLASSID) {
49169566063dSJacob Faibussowitsch       PetscCall(DMPlexGetOrdering1D(dm, &perm));
49179566063dSJacob Faibussowitsch       PetscCall(DMPlexPermute(dm, perm, &rdm));
491869d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
49199566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&perm));
49206913077dSMatthew G. Knepley     }
49216913077dSMatthew G. Knepley   }
49223cf6fe12SMatthew G. Knepley /* Handle */
4923dd4c3f67SMatthew G. Knepley non_refine:
4924dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
4925*22d6dc08SStefano Zampini   char    *phases[16];
4926*22d6dc08SStefano Zampini   PetscInt Nphases = 16;
4927*22d6dc08SStefano Zampini   PetscCall(PetscOptionsStringArray("-dm_plex_option_phases", "Option phase prefixes", "DMSetFromOptions", phases, &Nphases, &flg));
4928d0609cedSBarry Smith   PetscOptionsHeadEnd();
4929*22d6dc08SStefano Zampini 
4930*22d6dc08SStefano Zampini   // Phases
4931*22d6dc08SStefano Zampini   if (flg) {
4932*22d6dc08SStefano Zampini     const char *oldPrefix;
4933*22d6dc08SStefano Zampini 
4934*22d6dc08SStefano Zampini     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &oldPrefix));
4935*22d6dc08SStefano Zampini     for (PetscInt ph = 0; ph < Nphases; ++ph) {
4936*22d6dc08SStefano Zampini       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, phases[ph]));
4937*22d6dc08SStefano Zampini       PetscCall(PetscInfo(dm, "Options phase %s for DM %s\n", phases[ph], dm->hdr.name));
4938*22d6dc08SStefano Zampini       PetscCall(DMSetFromOptions(dm));
4939*22d6dc08SStefano Zampini       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix));
4940*22d6dc08SStefano Zampini       PetscCall(PetscFree(phases[ph]));
4941*22d6dc08SStefano Zampini     }
4942*22d6dc08SStefano Zampini   }
49433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
49440a6ba040SMatthew G. Knepley }
49450a6ba040SMatthew G. Knepley 
4946d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec)
4947d71ae5a4SJacob Faibussowitsch {
4948552f7358SJed Brown   PetscFunctionBegin;
49499566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector_Section_Private(dm, vec));
49509566063dSJacob Faibussowitsch   /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
49519566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex));
49529566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native));
49539566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex));
49549566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native));
49553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4956552f7358SJed Brown }
4957552f7358SJed Brown 
4958d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec)
4959d71ae5a4SJacob Faibussowitsch {
4960552f7358SJed Brown   PetscFunctionBegin;
49619566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector_Section_Private(dm, vec));
49629566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local));
49639566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local));
49643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4965552f7358SJed Brown }
4966552f7358SJed Brown 
4967d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
4968d71ae5a4SJacob Faibussowitsch {
4969793f3fe5SMatthew G. Knepley   PetscInt depth, d;
4970793f3fe5SMatthew G. Knepley 
4971793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
49729566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
4973793f3fe5SMatthew G. Knepley   if (depth == 1) {
49749566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &d));
49759566063dSJacob Faibussowitsch     if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
49769566063dSJacob Faibussowitsch     else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd));
49779371c9d4SSatish Balay     else {
49789371c9d4SSatish Balay       *pStart = 0;
49799371c9d4SSatish Balay       *pEnd   = 0;
49809371c9d4SSatish Balay     }
4981793f3fe5SMatthew G. Knepley   } else {
49829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
4983793f3fe5SMatthew G. Knepley   }
49843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4985793f3fe5SMatthew G. Knepley }
4986793f3fe5SMatthew G. Knepley 
4987d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
4988d71ae5a4SJacob Faibussowitsch {
4989502a2867SDave May   PetscSF            sf;
49906497c311SBarry Smith   PetscMPIInt        niranks, njranks;
49916497c311SBarry Smith   PetscInt           n;
49920a19bb7dSprj-   const PetscMPIInt *iranks, *jranks;
49930a19bb7dSprj-   DM_Plex           *data = (DM_Plex *)dm->data;
4994502a2867SDave May 
49952f356facSMatthew G. Knepley   PetscFunctionBegin;
49969566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
49970a19bb7dSprj-   if (!data->neighbors) {
49989566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sf));
49999566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL));
50009566063dSJacob Faibussowitsch     PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL));
50019566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors));
50029566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks));
50039566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks));
50040a19bb7dSprj-     n = njranks + niranks;
50059566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1));
50060a19bb7dSprj-     /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */
50079566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(n, data->neighbors));
50080a19bb7dSprj-   }
50090a19bb7dSprj-   if (nranks) *nranks = data->neighbors[0];
50100a19bb7dSprj-   if (ranks) {
50110a19bb7dSprj-     if (data->neighbors[0]) *ranks = data->neighbors + 1;
50120a19bb7dSprj-     else *ranks = NULL;
50130a19bb7dSprj-   }
50143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5015502a2867SDave May }
5016502a2867SDave May 
50171eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec);
50181eb70e55SToby Isaac 
5019d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm)
5020d71ae5a4SJacob Faibussowitsch {
5021552f7358SJed Brown   PetscFunctionBegin;
5022552f7358SJed Brown   dm->ops->view                      = DMView_Plex;
50232c40f234SMatthew G. Knepley   dm->ops->load                      = DMLoad_Plex;
5024552f7358SJed Brown   dm->ops->setfromoptions            = DMSetFromOptions_Plex;
502538221697SMatthew G. Knepley   dm->ops->clone                     = DMClone_Plex;
5026552f7358SJed Brown   dm->ops->setup                     = DMSetUp_Plex;
50271bb6d2a8SBarry Smith   dm->ops->createlocalsection        = DMCreateLocalSection_Plex;
5028adc21957SMatthew G. Knepley   dm->ops->createsectionpermutation  = DMCreateSectionPermutation_Plex;
502966ad2231SToby Isaac   dm->ops->createdefaultconstraints  = DMCreateDefaultConstraints_Plex;
5030552f7358SJed Brown   dm->ops->createglobalvector        = DMCreateGlobalVector_Plex;
5031552f7358SJed Brown   dm->ops->createlocalvector         = DMCreateLocalVector_Plex;
5032184d77edSJed Brown   dm->ops->getlocaltoglobalmapping   = NULL;
50330298fd71SBarry Smith   dm->ops->createfieldis             = NULL;
5034552f7358SJed Brown   dm->ops->createcoordinatedm        = DMCreateCoordinateDM_Plex;
5035f19dbd58SToby Isaac   dm->ops->createcoordinatefield     = DMCreateCoordinateField_Plex;
50360a6ba040SMatthew G. Knepley   dm->ops->getcoloring               = NULL;
5037552f7358SJed Brown   dm->ops->creatematrix              = DMCreateMatrix_Plex;
5038bceba477SMatthew G. Knepley   dm->ops->createinterpolation       = DMCreateInterpolation_Plex;
5039bd041c0cSMatthew G. Knepley   dm->ops->createmassmatrix          = DMCreateMassMatrix_Plex;
5040b4937a87SMatthew G. Knepley   dm->ops->createmassmatrixlumped    = DMCreateMassMatrixLumped_Plex;
50415a84ad33SLisandro Dalcin   dm->ops->createinjection           = DMCreateInjection_Plex;
5042552f7358SJed Brown   dm->ops->refine                    = DMRefine_Plex;
50430a6ba040SMatthew G. Knepley   dm->ops->coarsen                   = DMCoarsen_Plex;
50440a6ba040SMatthew G. Knepley   dm->ops->refinehierarchy           = DMRefineHierarchy_Plex;
5045b653a561SMatthew G. Knepley   dm->ops->coarsenhierarchy          = DMCoarsenHierarchy_Plex;
5046d410b0cfSMatthew G. Knepley   dm->ops->extrude                   = DMExtrude_Plex;
50470298fd71SBarry Smith   dm->ops->globaltolocalbegin        = NULL;
50480298fd71SBarry Smith   dm->ops->globaltolocalend          = NULL;
50490298fd71SBarry Smith   dm->ops->localtoglobalbegin        = NULL;
50500298fd71SBarry Smith   dm->ops->localtoglobalend          = NULL;
5051552f7358SJed Brown   dm->ops->destroy                   = DMDestroy_Plex;
5052552f7358SJed Brown   dm->ops->createsubdm               = DMCreateSubDM_Plex;
50532adcc780SMatthew G. Knepley   dm->ops->createsuperdm             = DMCreateSuperDM_Plex;
5054793f3fe5SMatthew G. Knepley   dm->ops->getdimpoints              = DMGetDimPoints_Plex;
5055552f7358SJed Brown   dm->ops->locatepoints              = DMLocatePoints_Plex;
50560709b2feSToby Isaac   dm->ops->projectfunctionlocal      = DMProjectFunctionLocal_Plex;
50570709b2feSToby Isaac   dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex;
5058bfc4295aSToby Isaac   dm->ops->projectfieldlocal         = DMProjectFieldLocal_Plex;
50598c6c5593SMatthew G. Knepley   dm->ops->projectfieldlabellocal    = DMProjectFieldLabelLocal_Plex;
5060ece3a9fcSMatthew G. Knepley   dm->ops->projectbdfieldlabellocal  = DMProjectBdFieldLabelLocal_Plex;
50610709b2feSToby Isaac   dm->ops->computel2diff             = DMComputeL2Diff_Plex;
5062b698f381SToby Isaac   dm->ops->computel2gradientdiff     = DMComputeL2GradientDiff_Plex;
50632a16baeaSToby Isaac   dm->ops->computel2fielddiff        = DMComputeL2FieldDiff_Plex;
506428d58a37SPierre Jolivet   dm->ops->getneighbors              = DMGetNeighbors_Plex;
50656c6a6b79SMatthew G. Knepley   dm->ops->getlocalboundingbox       = DMGetLocalBoundingBox_Coordinates;
5066907a3e9cSStefano Zampini   dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_Plex;
5067907a3e9cSStefano Zampini   dm->ops->createddscatters          = DMCreateDomainDecompositionScatters_Plex;
50689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex));
50696c51210dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex));
50709566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex));
50719566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex));
50729566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex));
50739566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex));
50746bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex));
50756bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex));
5076adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", DMReorderSectionGetDefault_Plex));
5077adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", DMReorderSectionSetDefault_Plex));
5078adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", DMReorderSectionGetType_Plex));
5079adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", DMReorderSectionSetType_Plex));
50809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex));
5081c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
5082c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex));
5083d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", DMPlexGetUseCeed_Plex));
5084d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", DMPlexSetUseCeed_Plex));
50853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5086552f7358SJed Brown }
5087552f7358SJed Brown 
5088d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm)
5089d71ae5a4SJacob Faibussowitsch {
509063a16f15SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex *)dm->data;
50911fca310dSJames Wright   const PetscSF *face_sfs;
50921fca310dSJames Wright   PetscInt       num_face_sfs;
509363a16f15SMatthew G. Knepley 
509463a16f15SMatthew G. Knepley   PetscFunctionBegin;
509563a16f15SMatthew G. Knepley   mesh->refct++;
509663a16f15SMatthew G. Knepley   (*newdm)->data = mesh;
50971fca310dSJames Wright   PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &face_sfs));
50981fca310dSJames Wright   PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, num_face_sfs, (PetscSF *)face_sfs));
50999566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX));
51009566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(*newdm));
51013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
510263a16f15SMatthew G. Knepley }
510363a16f15SMatthew G. Knepley 
51048818961aSMatthew G Knepley /*MC
5105a1cb98faSBarry Smith   DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram.
510620f4b53cSBarry Smith                     In the local representation, `Vec`s contain all unknowns in the interior and shared boundary. This is
51078818961aSMatthew G Knepley                     specified by a PetscSection object. Ownership in the global representation is determined by
5108a1cb98faSBarry Smith                     ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object.
51098818961aSMatthew G Knepley 
5110e5893cccSMatthew G. Knepley   Options Database Keys:
5111250712c9SMatthew G. Knepley + -dm_refine_pre                     - Refine mesh before distribution
5112250712c9SMatthew G. Knepley + -dm_refine_uniform_pre             - Choose uniform or generator-based refinement
5113250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre        - Cell volume limit after pre-refinement using generator
5114250712c9SMatthew G. Knepley . -dm_distribute                     - Distribute mesh across processes
5115250712c9SMatthew G. Knepley . -dm_distribute_overlap             - Number of cells to overlap for distribution
5116250712c9SMatthew G. Knepley . -dm_refine                         - Refine mesh after distribution
5117c3db174cSMatthew G. Knepley . -dm_localize <bool>                - Whether to localize coordinates for periodic meshes
5118c3db174cSMatthew G. Knepley . -dm_sparse_localize <bool>         - Whether to only localize cells on the periodic boundary
5119250712c9SMatthew G. Knepley . -dm_plex_hash_location             - Use grid hashing for point location
5120ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p>    - The number of divisions in each direction of the grid hash
5121f12cf164SMatthew G. Knepley . -dm_plex_partition_balance         - Attempt to evenly divide points on partition boundary between processes
5122f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd                 - Allow changes to the boundary on remeshing
5123d5b43468SJose E. Roman . -dm_plex_max_projection_height     - Maximum mesh point height used to project locally
5124f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement        - Use special nested projection algorithm for regular refinement
5125d02c7345SMatthew G. Knepley . -dm_plex_reorder_section           - Use specialized blocking if available
5126aaa8cc7dSPierre Jolivet . -dm_plex_check_all                 - Perform all checks below
5127f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry            - Check that the adjacency information in the mesh is symmetric
5128f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices
5129f12cf164SMatthew 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
5130f12cf164SMatthew G. Knepley . -dm_plex_check_geometry            - Check that cells have positive volume
5131f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex     - View the mesh in LaTeX/TikZ
5132e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num>          - Scale the TikZ
51335962854dSMatthew G. Knepley . -dm_plex_print_fem <num>           - View FEM assembly information, such as element vectors and matrices
51345962854dSMatthew G. Knepley - -dm_plex_print_fvm <num>           - View FVM assembly information, such as flux updates
5135e5893cccSMatthew G. Knepley 
51368818961aSMatthew G Knepley   Level: intermediate
51378818961aSMatthew G Knepley 
51381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection`
51398818961aSMatthew G Knepley M*/
51408818961aSMatthew G Knepley 
5141d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
5142d71ae5a4SJacob Faibussowitsch {
5143552f7358SJed Brown   DM_Plex *mesh;
5144412e9a14SMatthew G. Knepley   PetscInt unit;
5145552f7358SJed Brown 
5146552f7358SJed Brown   PetscFunctionBegin;
5147f39ec787SMatthew G. Knepley   PetscCall(PetscCitationsRegister(PlexCitation, &Plexcite));
5148552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
51494dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&mesh));
5150adc21957SMatthew G. Knepley   dm->reorderSection = DM_REORDER_DEFAULT_NOTSET;
5151552f7358SJed Brown   dm->data           = mesh;
5152552f7358SJed Brown 
5153552f7358SJed Brown   mesh->refct = 1;
51549566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection));
51559566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection));
5156552f7358SJed Brown   mesh->refinementUniform      = PETSC_TRUE;
5157552f7358SJed Brown   mesh->refinementLimit        = -1.0;
5158e600fa54SMatthew G. Knepley   mesh->distDefault            = PETSC_TRUE;
5159adc21957SMatthew G. Knepley   mesh->reorderDefault         = DM_REORDER_DEFAULT_NOTSET;
51601d1f2f2aSksagiyam   mesh->distributionName       = NULL;
51617d0f5628SVaclav Hapla   mesh->interpolated           = DMPLEX_INTERPOLATED_INVALID;
51627d0f5628SVaclav Hapla   mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID;
5163552f7358SJed Brown 
51649566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner));
51652e62ab5aSMatthew G. Knepley   mesh->remeshBd = PETSC_FALSE;
5166d9deefdfSMatthew G. Knepley 
51678865f1eaSKarl Rupp   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
5168552f7358SJed Brown 
5169df0420ecSMatthew G. Knepley   mesh->depthState    = -1;
5170ba2698f1SMatthew G. Knepley   mesh->celltypeState = -1;
51716113b454SMatthew G. Knepley   mesh->printTol      = 1.0e-10;
5172c29ce622SStefano Zampini   mesh->nonempty_comm = MPI_COMM_SELF;
5173552f7358SJed Brown 
51749566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
51753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5176552f7358SJed Brown }
5177552f7358SJed Brown 
5178552f7358SJed Brown /*@
5179a1cb98faSBarry Smith   DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
5180552f7358SJed Brown 
5181d083f849SBarry Smith   Collective
5182552f7358SJed Brown 
5183552f7358SJed Brown   Input Parameter:
5184a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object
5185552f7358SJed Brown 
5186552f7358SJed Brown   Output Parameter:
5187a1cb98faSBarry Smith . mesh - The `DMPLEX` object
5188552f7358SJed Brown 
5189552f7358SJed Brown   Level: beginner
5190552f7358SJed Brown 
519142747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMCreate()`, `DMSetType()`
5192552f7358SJed Brown @*/
5193d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
5194d71ae5a4SJacob Faibussowitsch {
5195552f7358SJed Brown   PetscFunctionBegin;
51964f572ea9SToby Isaac   PetscAssertPointer(mesh, 2);
51979566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, mesh));
51989566063dSJacob Faibussowitsch   PetscCall(DMSetType(*mesh, DMPLEX));
51993ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5200552f7358SJed Brown }
5201552f7358SJed Brown 
5202b09969d6SVaclav Hapla /*@C
5203b0fe842aSMatthew G. Knepley   DMPlexBuildFromCellListParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) where all cells have the same celltype
5204a1cb98faSBarry Smith 
520520f4b53cSBarry Smith   Collective; No Fortran Support
5206b09969d6SVaclav Hapla 
5207b09969d6SVaclav Hapla   Input Parameters:
5208a1cb98faSBarry Smith + dm          - The `DM`
5209b09969d6SVaclav Hapla . numCells    - The number of cells owned by this process
5210a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
5211a1cb98faSBarry Smith . NVertices   - The global number of vertices, or `PETSC_DETERMINE`
5212b09969d6SVaclav Hapla . numCorners  - The number of vertices for each cell
52135e488331SVaclav Hapla - cells       - An array of numCells*numCorners numbers, the global vertex numbers for each cell
5214b09969d6SVaclav Hapla 
5215be8c289dSNicolas Barral   Output Parameters:
5216a1cb98faSBarry Smith + vertexSF         - (Optional) `PetscSF` describing complete vertex ownership
5217be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
5218b09969d6SVaclav Hapla 
5219b09969d6SVaclav Hapla   Level: advanced
5220b09969d6SVaclav Hapla 
5221a1cb98faSBarry Smith   Notes:
5222a1cb98faSBarry Smith   Two triangles sharing a face
5223a1cb98faSBarry Smith .vb
5224a1cb98faSBarry Smith 
5225a1cb98faSBarry Smith         2
5226a1cb98faSBarry Smith       / | \
5227a1cb98faSBarry Smith      /  |  \
5228a1cb98faSBarry Smith     /   |   \
5229a1cb98faSBarry Smith    0  0 | 1  3
5230a1cb98faSBarry Smith     \   |   /
5231a1cb98faSBarry Smith      \  |  /
5232a1cb98faSBarry Smith       \ | /
5233a1cb98faSBarry Smith         1
5234a1cb98faSBarry Smith .ve
5235a1cb98faSBarry Smith   would have input
5236a1cb98faSBarry Smith .vb
5237a1cb98faSBarry Smith   numCells = 2, numVertices = 4
5238a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
5239a1cb98faSBarry Smith .ve
5240a1cb98faSBarry Smith   which would result in the `DMPLEX`
5241a1cb98faSBarry Smith .vb
5242a1cb98faSBarry Smith 
5243a1cb98faSBarry Smith         4
5244a1cb98faSBarry Smith       / | \
5245a1cb98faSBarry Smith      /  |  \
5246a1cb98faSBarry Smith     /   |   \
5247a1cb98faSBarry Smith    2  0 | 1  5
5248a1cb98faSBarry Smith     \   |   /
5249a1cb98faSBarry Smith      \  |  /
5250a1cb98faSBarry Smith       \ | /
5251a1cb98faSBarry Smith         3
5252a1cb98faSBarry Smith .ve
5253a1cb98faSBarry Smith 
5254a1cb98faSBarry Smith   Vertices are implicitly numbered consecutively 0,...,NVertices.
5255a1cb98faSBarry Smith   Each rank owns a chunk of numVertices consecutive vertices.
5256a1cb98faSBarry Smith   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
5257a1cb98faSBarry Smith   If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
5258a1cb98faSBarry Smith   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
5259a1cb98faSBarry Smith 
5260a1cb98faSBarry Smith   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
5261a1cb98faSBarry Smith 
52621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
5263a1cb98faSBarry Smith           `PetscSF`
5264b09969d6SVaclav Hapla @*/
5265d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved)
5266d71ae5a4SJacob Faibussowitsch {
52672464107aSksagiyam   PetscSF     sfPoint;
52682464107aSksagiyam   PetscLayout layout;
526982fb893eSVaclav Hapla   PetscInt    numVerticesAdj, *verticesAdj, *cones, c, p;
5270a47d0d45SMatthew G. Knepley 
5271a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
527225b6865aSVaclav Hapla   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
52739566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
527425b6865aSVaclav Hapla   /* Get/check global number of vertices */
527525b6865aSVaclav Hapla   {
527625b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
527725b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
527825b6865aSVaclav Hapla 
527925b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
52801690c2aeSBarry Smith     NVerticesInCells = PETSC_INT_MIN;
52819371c9d4SSatish Balay     for (i = 0; i < len; i++)
52829371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
528325b6865aSVaclav Hapla     ++NVerticesInCells;
5284462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
528525b6865aSVaclav Hapla 
528625b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
52879371c9d4SSatish Balay     else
52889371c9d4SSatish 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);
528925b6865aSVaclav Hapla   }
52909079aca8SVaclav Hapla   /* Count locally unique vertices */
52919079aca8SVaclav Hapla   {
52929079aca8SVaclav Hapla     PetscHSetI vhash;
52939079aca8SVaclav Hapla     PetscInt   off = 0;
52949079aca8SVaclav Hapla 
52959566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&vhash));
5296a47d0d45SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
529748a46eb9SPierre Jolivet       for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p]));
5298a47d0d45SMatthew G. Knepley     }
52999566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
53009566063dSJacob Faibussowitsch     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
5301ad540459SPierre Jolivet     else verticesAdj = *verticesAdjSaved;
53029566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
53039566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&vhash));
530463a3b9bcSJacob Faibussowitsch     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
5305a47d0d45SMatthew G. Knepley   }
53069566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
5307a47d0d45SMatthew G. Knepley   /* Create cones */
53089566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
53099566063dSJacob Faibussowitsch   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
53109566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
53119566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
5312a47d0d45SMatthew G. Knepley   for (c = 0; c < numCells; ++c) {
5313a47d0d45SMatthew G. Knepley     for (p = 0; p < numCorners; ++p) {
5314a47d0d45SMatthew G. Knepley       const PetscInt gv = cells[c * numCorners + p];
5315a47d0d45SMatthew G. Knepley       PetscInt       lv;
5316a47d0d45SMatthew G. Knepley 
53179079aca8SVaclav Hapla       /* Positions within verticesAdj form 0-based local vertex numbering;
53189079aca8SVaclav Hapla          we need to shift it by numCells to get correct DAG points (cells go first) */
53199566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
532063a3b9bcSJacob Faibussowitsch       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
5321961cfab0SVaclav Hapla       cones[c * numCorners + p] = lv + numCells;
5322a47d0d45SMatthew G. Knepley     }
5323a47d0d45SMatthew G. Knepley   }
53242464107aSksagiyam   /* Build point sf */
53259566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
53269566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(layout, NVertices));
53279566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
53289566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
53299566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
53309566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
53319566063dSJacob Faibussowitsch   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
53329566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
53332464107aSksagiyam   if (dm->sf) {
53342464107aSksagiyam     const char *prefix;
53352464107aSksagiyam 
53369566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
53379566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
53382464107aSksagiyam   }
53399566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sfPoint));
53409566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfPoint));
5341f4f49eeaSPierre Jolivet   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF"));
5342a47d0d45SMatthew G. Knepley   /* Fill in the rest of the topology structure */
53439566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
53449566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
53459566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
53463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5347a47d0d45SMatthew G. Knepley }
5348a47d0d45SMatthew G. Knepley 
5349b0fe842aSMatthew G. Knepley /*@C
5350b0fe842aSMatthew G. Knepley   DMPlexBuildFromCellSectionParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) allowing multiple celltypes
5351b0fe842aSMatthew G. Knepley 
5352b0fe842aSMatthew G. Knepley   Collective; No Fortran Support
5353b0fe842aSMatthew G. Knepley 
5354b0fe842aSMatthew G. Knepley   Input Parameters:
5355b0fe842aSMatthew G. Knepley + dm          - The `DM`
5356b0fe842aSMatthew G. Knepley . numCells    - The number of cells owned by this process
5357b0fe842aSMatthew G. Knepley . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
5358b0fe842aSMatthew G. Knepley . NVertices   - The global number of vertices, or `PETSC_DETERMINE`
5359b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells)
5360b0fe842aSMatthew G. Knepley - cells       - An array of the global vertex numbers for each cell
5361b0fe842aSMatthew G. Knepley 
5362b0fe842aSMatthew G. Knepley   Output Parameters:
5363b0fe842aSMatthew G. Knepley + vertexSF         - (Optional) `PetscSF` describing complete vertex ownership
5364b0fe842aSMatthew G. Knepley - verticesAdjSaved - (Optional) vertex adjacency array
5365b0fe842aSMatthew G. Knepley 
5366b0fe842aSMatthew G. Knepley   Level: advanced
5367b0fe842aSMatthew G. Knepley 
5368b0fe842aSMatthew G. Knepley   Notes:
5369b0fe842aSMatthew G. Knepley   A triangle and quadrilateral sharing a face
5370b0fe842aSMatthew G. Knepley .vb
5371b0fe842aSMatthew G. Knepley         2----------3
5372b0fe842aSMatthew G. Knepley       / |          |
5373b0fe842aSMatthew G. Knepley      /  |          |
5374b0fe842aSMatthew G. Knepley     /   |          |
5375b0fe842aSMatthew G. Knepley    0  0 |     1    |
5376b0fe842aSMatthew G. Knepley     \   |          |
5377b0fe842aSMatthew G. Knepley      \  |          |
5378b0fe842aSMatthew G. Knepley       \ |          |
5379b0fe842aSMatthew G. Knepley         1----------4
5380b0fe842aSMatthew G. Knepley .ve
5381b0fe842aSMatthew G. Knepley   would have input
5382b0fe842aSMatthew G. Knepley .vb
5383b0fe842aSMatthew G. Knepley   numCells = 2, numVertices = 5
5384b0fe842aSMatthew G. Knepley   cells = [0 1 2  1 4 3 2]
5385b0fe842aSMatthew G. Knepley .ve
5386b0fe842aSMatthew G. Knepley   which would result in the `DMPLEX`
5387b0fe842aSMatthew G. Knepley .vb
5388b0fe842aSMatthew G. Knepley         4----------5
5389b0fe842aSMatthew G. Knepley       / |          |
5390b0fe842aSMatthew G. Knepley      /  |          |
5391b0fe842aSMatthew G. Knepley     /   |          |
5392b0fe842aSMatthew G. Knepley    2  0 |     1    |
5393b0fe842aSMatthew G. Knepley     \   |          |
5394b0fe842aSMatthew G. Knepley      \  |          |
5395b0fe842aSMatthew G. Knepley       \ |          |
5396b0fe842aSMatthew G. Knepley         3----------6
5397b0fe842aSMatthew G. Knepley .ve
5398b0fe842aSMatthew G. Knepley 
5399b0fe842aSMatthew G. Knepley   Vertices are implicitly numbered consecutively 0,...,NVertices.
5400b0fe842aSMatthew G. Knepley   Each rank owns a chunk of numVertices consecutive vertices.
5401b0fe842aSMatthew G. Knepley   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
5402b0fe842aSMatthew G. Knepley   If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
5403b0fe842aSMatthew G. Knepley   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
5404b0fe842aSMatthew G. Knepley 
5405b0fe842aSMatthew G. Knepley   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
5406b0fe842aSMatthew G. Knepley 
5407b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexCreateFromCellSectionParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
5408b0fe842aSMatthew G. Knepley           `PetscSF`
5409b0fe842aSMatthew G. Knepley @*/
5410b0fe842aSMatthew G. Knepley PetscErrorCode DMPlexBuildFromCellSectionParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved)
5411b0fe842aSMatthew G. Knepley {
5412b0fe842aSMatthew G. Knepley   PetscSF     sfPoint;
5413b0fe842aSMatthew G. Knepley   PetscLayout layout;
5414b0fe842aSMatthew G. Knepley   PetscInt    numVerticesAdj, *verticesAdj, *cones, cStart, cEnd, len;
5415b0fe842aSMatthew G. Knepley 
5416b0fe842aSMatthew G. Knepley   PetscFunctionBegin;
5417b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
5418b0fe842aSMatthew G. Knepley   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
5419b0fe842aSMatthew G. Knepley   PetscCall(PetscSectionGetChart(cellSection, &cStart, &cEnd));
5420b0fe842aSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(cellSection, &len));
5421b0fe842aSMatthew G. Knepley   PetscCheck(cStart == 0 && cEnd == numCells, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Section chart [%" PetscInt_FMT ", %" PetscInt_FMT ") should be [0, %" PetscInt_FMT ")", cStart, cEnd, numCells);
5422b0fe842aSMatthew G. Knepley   /* Get/check global number of vertices */
5423b0fe842aSMatthew G. Knepley   {
5424b0fe842aSMatthew G. Knepley     PetscInt NVerticesInCells;
5425b0fe842aSMatthew G. Knepley 
5426b0fe842aSMatthew G. Knepley     /* NVerticesInCells = max(cells) + 1 */
5427b0fe842aSMatthew G. Knepley     NVerticesInCells = PETSC_MIN_INT;
5428b0fe842aSMatthew G. Knepley     for (PetscInt i = 0; i < len; i++)
5429b0fe842aSMatthew G. Knepley       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
5430b0fe842aSMatthew G. Knepley     ++NVerticesInCells;
5431b0fe842aSMatthew G. Knepley     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
5432b0fe842aSMatthew G. Knepley 
5433b0fe842aSMatthew G. Knepley     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
5434b0fe842aSMatthew G. Knepley     else
5435b0fe842aSMatthew G. Knepley       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);
5436b0fe842aSMatthew G. Knepley   }
5437b0fe842aSMatthew G. Knepley   /* Count locally unique vertices */
5438b0fe842aSMatthew G. Knepley   {
5439b0fe842aSMatthew G. Knepley     PetscHSetI vhash;
5440b0fe842aSMatthew G. Knepley     PetscInt   off = 0;
5441b0fe842aSMatthew G. Knepley 
5442b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetICreate(&vhash));
5443b0fe842aSMatthew G. Knepley     for (PetscInt i = 0; i < len; i++) PetscCall(PetscHSetIAdd(vhash, cells[i]));
5444b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
5445b0fe842aSMatthew G. Knepley     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
5446b0fe842aSMatthew G. Knepley     else verticesAdj = *verticesAdjSaved;
5447b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
5448b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIDestroy(&vhash));
5449b0fe842aSMatthew G. Knepley     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
5450b0fe842aSMatthew G. Knepley   }
5451b0fe842aSMatthew G. Knepley   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
5452b0fe842aSMatthew G. Knepley   /* Create cones */
5453b0fe842aSMatthew G. Knepley   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
5454b0fe842aSMatthew G. Knepley   for (PetscInt c = 0; c < numCells; ++c) {
5455b0fe842aSMatthew G. Knepley     PetscInt dof;
5456b0fe842aSMatthew G. Knepley 
5457b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetDof(cellSection, c, &dof));
5458b0fe842aSMatthew G. Knepley     PetscCall(DMPlexSetConeSize(dm, c, dof));
5459b0fe842aSMatthew G. Knepley   }
5460b0fe842aSMatthew G. Knepley   PetscCall(DMSetUp(dm));
5461b0fe842aSMatthew G. Knepley   PetscCall(DMPlexGetCones(dm, &cones));
5462b0fe842aSMatthew G. Knepley   for (PetscInt c = 0; c < numCells; ++c) {
5463b0fe842aSMatthew G. Knepley     PetscInt dof, off;
5464b0fe842aSMatthew G. Knepley 
5465b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetDof(cellSection, c, &dof));
5466b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetOffset(cellSection, c, &off));
5467b0fe842aSMatthew G. Knepley     for (PetscInt p = off; p < off + dof; ++p) {
5468b0fe842aSMatthew G. Knepley       const PetscInt gv = cells[p];
5469b0fe842aSMatthew G. Knepley       PetscInt       lv;
5470b0fe842aSMatthew G. Knepley 
5471b0fe842aSMatthew G. Knepley       /* Positions within verticesAdj form 0-based local vertex numbering;
5472b0fe842aSMatthew G. Knepley          we need to shift it by numCells to get correct DAG points (cells go first) */
5473b0fe842aSMatthew G. Knepley       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
5474b0fe842aSMatthew G. Knepley       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
5475b0fe842aSMatthew G. Knepley       cones[p] = lv + numCells;
5476b0fe842aSMatthew G. Knepley     }
5477b0fe842aSMatthew G. Knepley   }
5478b0fe842aSMatthew G. Knepley   /* Build point sf */
5479b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
5480b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetSize(layout, NVertices));
5481b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
5482b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetBlockSize(layout, 1));
5483b0fe842aSMatthew G. Knepley   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
5484b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutDestroy(&layout));
5485b0fe842aSMatthew G. Knepley   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
5486b0fe842aSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
5487b0fe842aSMatthew G. Knepley   if (dm->sf) {
5488b0fe842aSMatthew G. Knepley     const char *prefix;
5489b0fe842aSMatthew G. Knepley 
5490b0fe842aSMatthew G. Knepley     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
5491b0fe842aSMatthew G. Knepley     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
5492b0fe842aSMatthew G. Knepley   }
5493b0fe842aSMatthew G. Knepley   PetscCall(DMSetPointSF(dm, sfPoint));
5494b0fe842aSMatthew G. Knepley   PetscCall(PetscSFDestroy(&sfPoint));
5495b0fe842aSMatthew G. Knepley   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF"));
5496b0fe842aSMatthew G. Knepley   /* Fill in the rest of the topology structure */
5497b0fe842aSMatthew G. Knepley   PetscCall(DMPlexSymmetrize(dm));
5498b0fe842aSMatthew G. Knepley   PetscCall(DMPlexStratify(dm));
5499b0fe842aSMatthew G. Knepley   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
5500b0fe842aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
5501b0fe842aSMatthew G. Knepley }
5502b0fe842aSMatthew G. Knepley 
5503cc4c1da9SBarry Smith /*@
5504a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
5505a1cb98faSBarry Smith 
550620f4b53cSBarry Smith   Collective; No Fortran Support
5507b09969d6SVaclav Hapla 
5508b09969d6SVaclav Hapla   Input Parameters:
5509a1cb98faSBarry Smith + dm           - The `DM`
5510b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
5511a1cb98faSBarry Smith . sfVert       - `PetscSF` describing complete vertex ownership
5512b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
5513b09969d6SVaclav Hapla 
5514b09969d6SVaclav Hapla   Level: advanced
5515b09969d6SVaclav Hapla 
55161cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()`
5517b09969d6SVaclav Hapla @*/
5518d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[])
5519d71ae5a4SJacob Faibussowitsch {
5520a47d0d45SMatthew G. Knepley   PetscSection coordSection;
5521a47d0d45SMatthew G. Knepley   Vec          coordinates;
5522a47d0d45SMatthew G. Knepley   PetscScalar *coords;
55231edcf0b2SVaclav Hapla   PetscInt     numVertices, numVerticesAdj, coordSize, v, vStart, vEnd;
5524a47d0d45SMatthew G. Knepley 
5525a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
55269566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
55279566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
55281dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
55299566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
55309566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL));
55311dca8a05SBarry 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);
55329566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
55339566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
55349566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
55359566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
55361edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
55379566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
55389566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
5539a47d0d45SMatthew G. Knepley   }
55409566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
55419566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
55429566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
55439566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
55449566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
55459566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
55469566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
55479566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
5548a47d0d45SMatthew G. Knepley   {
5549a47d0d45SMatthew G. Knepley     MPI_Datatype coordtype;
5550a47d0d45SMatthew G. Knepley 
5551a47d0d45SMatthew G. Knepley     /* Need a temp buffer for coords if we have complex/single */
55526497c311SBarry Smith     PetscCallMPI(MPI_Type_contiguous((PetscMPIInt)spaceDim, MPIU_SCALAR, &coordtype));
55539566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&coordtype));
555421016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX)
555521016a8bSBarry Smith     {
555621016a8bSBarry Smith       PetscScalar *svertexCoords;
555721016a8bSBarry Smith       PetscInt     i;
55589566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords));
55593612f820SVaclav Hapla       for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i];
55609566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
55619566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
55629566063dSJacob Faibussowitsch       PetscCall(PetscFree(svertexCoords));
556321016a8bSBarry Smith     }
556421016a8bSBarry Smith #else
55659566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
55669566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
556721016a8bSBarry Smith #endif
55689566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&coordtype));
5569a47d0d45SMatthew G. Knepley   }
55709566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
55719566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
55729566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
55739566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
55743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5575a47d0d45SMatthew G. Knepley }
5576a47d0d45SMatthew G. Knepley 
5577c3edce3dSSatish Balay /*@
5578b0fe842aSMatthew G. Knepley   DMPlexCreateFromCellListParallelPetsc - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) where all cells have the same celltype
5579a1cb98faSBarry Smith 
5580a1cb98faSBarry Smith   Collective
5581a47d0d45SMatthew G. Knepley 
5582a47d0d45SMatthew G. Knepley   Input Parameters:
5583a47d0d45SMatthew G. Knepley + comm         - The communicator
5584a47d0d45SMatthew G. Knepley . dim          - The topological dimension of the mesh
5585a47d0d45SMatthew G. Knepley . numCells     - The number of cells owned by this process
5586a1cb98faSBarry Smith . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`
5587a1cb98faSBarry Smith . NVertices    - The global number of vertices, or `PETSC_DECIDE`
5588a47d0d45SMatthew G. Knepley . numCorners   - The number of vertices for each cell
5589a47d0d45SMatthew G. Knepley . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
5590a47d0d45SMatthew G. Knepley . cells        - An array of numCells*numCorners numbers, the global vertex numbers for each cell
5591a47d0d45SMatthew G. Knepley . spaceDim     - The spatial dimension used for coordinates
5592a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
5593a47d0d45SMatthew G. Knepley 
5594d8d19677SJose E. Roman   Output Parameters:
5595a1cb98faSBarry Smith + dm          - The `DM`
5596a1cb98faSBarry Smith . vertexSF    - (Optional) `PetscSF` describing complete vertex ownership
559760225df5SJacob Faibussowitsch - verticesAdj - (Optional) vertex adjacency array
5598a47d0d45SMatthew G. Knepley 
5599b09969d6SVaclav Hapla   Level: intermediate
5600a47d0d45SMatthew G. Knepley 
5601a1cb98faSBarry Smith   Notes:
5602a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
5603a1cb98faSBarry Smith   `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
5604a1cb98faSBarry Smith 
5605a1cb98faSBarry Smith   See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters.
5606a1cb98faSBarry Smith 
5607a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
5608a1cb98faSBarry Smith 
56091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
5610a47d0d45SMatthew G. Knepley @*/
5611d71ae5a4SJacob 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)
5612d71ae5a4SJacob Faibussowitsch {
5613a47d0d45SMatthew G. Knepley   PetscSF sfVert;
5614a47d0d45SMatthew G. Knepley 
5615a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
56169566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
56179566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
5618a47d0d45SMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
5619064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
56209566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
56219566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj));
5622a47d0d45SMatthew G. Knepley   if (interpolate) {
56235fd9971aSMatthew G. Knepley     DM idm;
5624a47d0d45SMatthew G. Knepley 
56259566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
56269566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
5627a47d0d45SMatthew G. Knepley     *dm = idm;
5628a47d0d45SMatthew G. Knepley   }
56299566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
563018d54ad4SMichael Lange   if (vertexSF) *vertexSF = sfVert;
56319566063dSJacob Faibussowitsch   else PetscCall(PetscSFDestroy(&sfVert));
56323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5633a47d0d45SMatthew G. Knepley }
5634a47d0d45SMatthew G. Knepley 
5635cc4c1da9SBarry Smith /*@
5636b0fe842aSMatthew G. Knepley   DMPlexCreateFromCellSectionParallel - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) and supports multiple celltypes
5637b0fe842aSMatthew G. Knepley 
5638b0fe842aSMatthew G. Knepley   Collective
5639b0fe842aSMatthew G. Knepley 
5640b0fe842aSMatthew G. Knepley   Input Parameters:
5641b0fe842aSMatthew G. Knepley + comm         - The communicator
5642b0fe842aSMatthew G. Knepley . dim          - The topological dimension of the mesh
5643b0fe842aSMatthew G. Knepley . numCells     - The number of cells owned by this process
5644b0fe842aSMatthew G. Knepley . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`
5645b0fe842aSMatthew G. Knepley . NVertices    - The global number of vertices, or `PETSC_DECIDE`
5646b0fe842aSMatthew G. Knepley . cellSection  - The `PetscSection` giving the number of vertices for each cell (layout of cells)
5647b0fe842aSMatthew G. Knepley . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
5648b0fe842aSMatthew G. Knepley . cells        - An array of the global vertex numbers for each cell
5649b0fe842aSMatthew G. Knepley . spaceDim     - The spatial dimension used for coordinates
5650b0fe842aSMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
5651b0fe842aSMatthew G. Knepley 
5652b0fe842aSMatthew G. Knepley   Output Parameters:
5653b0fe842aSMatthew G. Knepley + dm          - The `DM`
5654b0fe842aSMatthew G. Knepley . vertexSF    - (Optional) `PetscSF` describing complete vertex ownership
5655b0fe842aSMatthew G. Knepley - verticesAdj - (Optional) vertex adjacency array
5656b0fe842aSMatthew G. Knepley 
5657b0fe842aSMatthew G. Knepley   Level: intermediate
5658b0fe842aSMatthew G. Knepley 
5659b0fe842aSMatthew G. Knepley   Notes:
5660b0fe842aSMatthew G. Knepley   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
5661b0fe842aSMatthew G. Knepley   `DMPlexBuildFromCellSectionParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
5662b0fe842aSMatthew G. Knepley 
5663b0fe842aSMatthew G. Knepley   See `DMPlexBuildFromCellSectionParallel()` for an example and details about the topology-related parameters.
5664b0fe842aSMatthew G. Knepley 
5665b0fe842aSMatthew G. Knepley   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
5666b0fe842aSMatthew G. Knepley 
5667b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
5668b0fe842aSMatthew G. Knepley @*/
5669b0fe842aSMatthew G. Knepley PetscErrorCode DMPlexCreateFromCellSectionParallel(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PetscSF *vertexSF, PetscInt **verticesAdj, DM *dm)
5670b0fe842aSMatthew G. Knepley {
5671b0fe842aSMatthew G. Knepley   PetscSF sfVert;
5672b0fe842aSMatthew G. Knepley 
5673b0fe842aSMatthew G. Knepley   PetscFunctionBegin;
5674b0fe842aSMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
5675b0fe842aSMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
5676b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
5677b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
5678b0fe842aSMatthew G. Knepley   PetscCall(DMSetDimension(*dm, dim));
5679b0fe842aSMatthew G. Knepley   PetscCall(DMPlexBuildFromCellSectionParallel(*dm, numCells, numVertices, NVertices, cellSection, cells, &sfVert, verticesAdj));
5680b0fe842aSMatthew G. Knepley   if (interpolate) {
5681b0fe842aSMatthew G. Knepley     DM idm;
5682b0fe842aSMatthew G. Knepley 
5683b0fe842aSMatthew G. Knepley     PetscCall(DMPlexInterpolate(*dm, &idm));
5684b0fe842aSMatthew G. Knepley     PetscCall(DMDestroy(dm));
5685b0fe842aSMatthew G. Knepley     *dm = idm;
5686b0fe842aSMatthew G. Knepley   }
5687b0fe842aSMatthew G. Knepley   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
5688b0fe842aSMatthew G. Knepley   if (vertexSF) *vertexSF = sfVert;
5689b0fe842aSMatthew G. Knepley   else PetscCall(PetscSFDestroy(&sfVert));
5690b0fe842aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
5691b0fe842aSMatthew G. Knepley }
5692b0fe842aSMatthew G. Knepley 
5693b0fe842aSMatthew G. Knepley /*@
5694a1cb98faSBarry Smith   DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output)
5695a1cb98faSBarry Smith 
569620f4b53cSBarry Smith   Collective; No Fortran Support
56979298eaa6SMatthew G Knepley 
56989298eaa6SMatthew G Knepley   Input Parameters:
5699a1cb98faSBarry Smith + dm          - The `DM`
5700b09969d6SVaclav Hapla . numCells    - The number of cells owned by this process
5701a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE`
57029298eaa6SMatthew G Knepley . numCorners  - The number of vertices for each cell
5703a3b724e8SBarry Smith - cells       - An array of `numCells` x `numCorners` numbers, the global vertex numbers for each cell
57049298eaa6SMatthew G Knepley 
5705b09969d6SVaclav Hapla   Level: advanced
57069298eaa6SMatthew G Knepley 
5707b09969d6SVaclav Hapla   Notes:
5708b09969d6SVaclav Hapla   Two triangles sharing a face
5709a1cb98faSBarry Smith .vb
57109298eaa6SMatthew G Knepley 
5711a1cb98faSBarry Smith         2
5712a1cb98faSBarry Smith       / | \
5713a1cb98faSBarry Smith      /  |  \
5714a1cb98faSBarry Smith     /   |   \
5715a1cb98faSBarry Smith    0  0 | 1  3
5716a1cb98faSBarry Smith     \   |   /
5717a1cb98faSBarry Smith      \  |  /
5718a1cb98faSBarry Smith       \ | /
5719a1cb98faSBarry Smith         1
5720a1cb98faSBarry Smith .ve
5721a1cb98faSBarry Smith   would have input
5722a1cb98faSBarry Smith .vb
5723a1cb98faSBarry Smith   numCells = 2, numVertices = 4
5724a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
5725a1cb98faSBarry Smith .ve
5726a1cb98faSBarry Smith   which would result in the `DMPLEX`
5727a1cb98faSBarry Smith .vb
5728a1cb98faSBarry Smith 
5729a1cb98faSBarry Smith         4
5730a1cb98faSBarry Smith       / | \
5731a1cb98faSBarry Smith      /  |  \
5732a1cb98faSBarry Smith     /   |   \
5733a1cb98faSBarry Smith    2  0 | 1  5
5734a1cb98faSBarry Smith     \   |   /
5735a1cb98faSBarry Smith      \  |  /
5736a1cb98faSBarry Smith       \ | /
5737a1cb98faSBarry Smith         3
5738a1cb98faSBarry Smith .ve
5739a1cb98faSBarry Smith 
5740a1cb98faSBarry Smith   If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1.
574125b6865aSVaclav Hapla 
57421cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()`
5743b09969d6SVaclav Hapla @*/
5744d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[])
5745d71ae5a4SJacob Faibussowitsch {
5746961cfab0SVaclav Hapla   PetscInt *cones, c, p, dim;
5747b09969d6SVaclav Hapla 
5748b09969d6SVaclav Hapla   PetscFunctionBegin;
57499566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
57509566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
575125b6865aSVaclav Hapla   /* Get/check global number of vertices */
575225b6865aSVaclav Hapla   {
575325b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
575425b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
575525b6865aSVaclav Hapla 
575625b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
57571690c2aeSBarry Smith     NVerticesInCells = PETSC_INT_MIN;
57589371c9d4SSatish Balay     for (i = 0; i < len; i++)
57599371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
576025b6865aSVaclav Hapla     ++NVerticesInCells;
576125b6865aSVaclav Hapla 
576225b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells;
57639371c9d4SSatish Balay     else
57649371c9d4SSatish 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);
576525b6865aSVaclav Hapla   }
57669566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
576748a46eb9SPierre Jolivet   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
57689566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
57699566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
5770b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
5771ad540459SPierre Jolivet     for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells;
5772b09969d6SVaclav Hapla   }
57739566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
57749566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
57759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
57763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5777b09969d6SVaclav Hapla }
5778b09969d6SVaclav Hapla 
5779cc4c1da9SBarry Smith /*@
5780a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
5781a1cb98faSBarry Smith 
5782cc4c1da9SBarry Smith   Collective
5783b09969d6SVaclav Hapla 
5784b09969d6SVaclav Hapla   Input Parameters:
5785a1cb98faSBarry Smith + dm           - The `DM`
5786b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
5787b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
5788b09969d6SVaclav Hapla 
5789b09969d6SVaclav Hapla   Level: advanced
5790b09969d6SVaclav Hapla 
57911cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()`
5792b09969d6SVaclav Hapla @*/
5793d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[])
5794d71ae5a4SJacob Faibussowitsch {
5795b09969d6SVaclav Hapla   PetscSection coordSection;
5796b09969d6SVaclav Hapla   Vec          coordinates;
5797b09969d6SVaclav Hapla   DM           cdm;
5798b09969d6SVaclav Hapla   PetscScalar *coords;
57991edcf0b2SVaclav Hapla   PetscInt     v, vStart, vEnd, d;
5800b09969d6SVaclav Hapla 
5801b09969d6SVaclav Hapla   PetscFunctionBegin;
58029566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
58039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
58041dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
58059566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
58069566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
58079566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
58089566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
58099566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
58101edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
58119566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
58129566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
5813b09969d6SVaclav Hapla   }
58149566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
5815b09969d6SVaclav Hapla 
58169566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
58179566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(cdm, &coordinates));
58189566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
58199566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
58209566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(coordinates, &coords));
58211edcf0b2SVaclav Hapla   for (v = 0; v < vEnd - vStart; ++v) {
5822ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d];
5823b09969d6SVaclav Hapla   }
58249566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
58259566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
58269566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
58279566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
58283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5829b09969d6SVaclav Hapla }
5830b09969d6SVaclav Hapla 
5831b09969d6SVaclav Hapla /*@
5832a1cb98faSBarry Smith   DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input
58333df08285SMatthew G. Knepley 
5834a1cb98faSBarry Smith   Collective
5835b09969d6SVaclav Hapla 
5836b09969d6SVaclav Hapla   Input Parameters:
5837b09969d6SVaclav Hapla + comm         - The communicator
5838b09969d6SVaclav Hapla . dim          - The topological dimension of the mesh
58393df08285SMatthew G. Knepley . numCells     - The number of cells, only on process 0
5840a1cb98faSBarry Smith . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0
58413df08285SMatthew G. Knepley . numCorners   - The number of vertices for each cell, only on process 0
5842b09969d6SVaclav Hapla . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
58433df08285SMatthew G. Knepley . cells        - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0
5844b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
58453df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0
5846b09969d6SVaclav Hapla 
5847b09969d6SVaclav Hapla   Output Parameter:
5848a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0
584925b6865aSVaclav Hapla 
5850b09969d6SVaclav Hapla   Level: intermediate
5851b09969d6SVaclav Hapla 
5852a1cb98faSBarry Smith   Notes:
5853a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`,
5854a1cb98faSBarry Smith   `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()`
5855a1cb98faSBarry Smith 
5856a1cb98faSBarry Smith   See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters.
5857a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters.
5858a1cb98faSBarry Smith   See `DMPlexCreateFromCellListParallelPetsc()` for parallel input
5859a1cb98faSBarry Smith 
58601cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
58619298eaa6SMatthew G Knepley @*/
5862d71ae5a4SJacob 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)
5863d71ae5a4SJacob Faibussowitsch {
58643df08285SMatthew G. Knepley   PetscMPIInt rank;
58659298eaa6SMatthew G Knepley 
58669298eaa6SMatthew G Knepley   PetscFunctionBegin;
586728b400f6SJacob 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.");
58689566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
58699566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
58709566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
58719566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
5872c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells));
58739566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL));
58749298eaa6SMatthew G Knepley   if (interpolate) {
58755fd9971aSMatthew G. Knepley     DM idm;
58769298eaa6SMatthew G Knepley 
58779566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
58789566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
58799298eaa6SMatthew G Knepley     *dm = idm;
58809298eaa6SMatthew G Knepley   }
5881c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords));
58829566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL));
58833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58849298eaa6SMatthew G Knepley }
58859298eaa6SMatthew G Knepley 
5886939f6067SMatthew G. Knepley /*@
588720f4b53cSBarry Smith   DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a `DM`
5888939f6067SMatthew G. Knepley 
5889939f6067SMatthew G. Knepley   Input Parameters:
589020f4b53cSBarry Smith + dm               - The empty `DM` object, usually from `DMCreate()` and `DMSetDimension()`
5891939f6067SMatthew G. Knepley . depth            - The depth of the DAG
589220f4b53cSBarry Smith . numPoints        - Array of size depth + 1 containing the number of points at each `depth`
5893939f6067SMatthew G. Knepley . coneSize         - The cone size of each point
5894939f6067SMatthew G. Knepley . cones            - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
5895939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point
589620f4b53cSBarry Smith - vertexCoords     - An array of `numPoints`[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via `DMSetCoordinateDim()`
5897939f6067SMatthew G. Knepley 
5898939f6067SMatthew G. Knepley   Output Parameter:
589920f4b53cSBarry Smith . dm - The `DM`
590020f4b53cSBarry Smith 
590120f4b53cSBarry Smith   Level: advanced
5902939f6067SMatthew G. Knepley 
5903a1cb98faSBarry Smith   Note:
5904a1cb98faSBarry Smith   Two triangles sharing a face would have input
5905a1cb98faSBarry Smith .vb
5906a1cb98faSBarry Smith   depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
5907a1cb98faSBarry Smith   cones = [2 3 4  3 5 4], coneOrientations = [0 0 0  0 0 0]
5908a1cb98faSBarry Smith  vertexCoords = [-1.0 0.0  0.0 -1.0  0.0 1.0  1.0 0.0]
5909a1cb98faSBarry Smith .ve
5910939f6067SMatthew G. Knepley   which would result in the DMPlex
5911a1cb98faSBarry Smith .vb
5912a1cb98faSBarry Smith         4
5913a1cb98faSBarry Smith       / | \
5914a1cb98faSBarry Smith      /  |  \
5915a1cb98faSBarry Smith     /   |   \
5916a1cb98faSBarry Smith    2  0 | 1  5
5917a1cb98faSBarry Smith     \   |   /
5918a1cb98faSBarry Smith      \  |  /
5919a1cb98faSBarry Smith       \ | /
5920a1cb98faSBarry Smith         3
5921a1cb98faSBarry Smith .ve
5922a1cb98faSBarry Smith   Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()`
5923939f6067SMatthew G. Knepley 
59241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
5925939f6067SMatthew G. Knepley @*/
5926d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
5927d71ae5a4SJacob Faibussowitsch {
59289298eaa6SMatthew G Knepley   Vec          coordinates;
59299298eaa6SMatthew G Knepley   PetscSection coordSection;
59309298eaa6SMatthew G Knepley   PetscScalar *coords;
5931811e8653SToby Isaac   PetscInt     coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off;
59329298eaa6SMatthew G Knepley 
59339298eaa6SMatthew G Knepley   PetscFunctionBegin;
59349566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
59359566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
593663a3b9bcSJacob Faibussowitsch   PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim);
59379298eaa6SMatthew G Knepley   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
59389566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, pStart, pEnd));
59399298eaa6SMatthew G Knepley   for (p = pStart; p < pEnd; ++p) {
59409566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart]));
5941ad540459SPierre Jolivet     if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart;
594297e052ccSToby Isaac   }
59431dca8a05SBarry Smith   PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]);
59449566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm)); /* Allocate space for cones */
59459298eaa6SMatthew G Knepley   for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) {
59469566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(dm, p, &cones[off]));
59479566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off]));
59489298eaa6SMatthew G Knepley   }
59499566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
59509566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
59519298eaa6SMatthew G Knepley   /* Build coordinates */
59529566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
59539566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
59549566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
59559566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0]));
59569298eaa6SMatthew G Knepley   for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) {
59579566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
59589566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
59599298eaa6SMatthew G Knepley   }
59609566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
59619566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
59629566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
59639566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
59649566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
59659566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, dimEmbed));
59669566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
59679318fe57SMatthew G. Knepley   if (vertexCoords) {
59689566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
59699298eaa6SMatthew G Knepley     for (v = 0; v < numPoints[0]; ++v) {
59709298eaa6SMatthew G Knepley       PetscInt off;
59719298eaa6SMatthew G Knepley 
59729566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off));
5973ad540459SPierre Jolivet       for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d];
59749298eaa6SMatthew G Knepley     }
59759318fe57SMatthew G. Knepley   }
59769566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
59779566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
59789566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
59793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
59809298eaa6SMatthew G Knepley }
59818415267dSToby Isaac 
5982a4e35b19SJacob Faibussowitsch /*
5983a1cb98faSBarry Smith   DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file.
5984a1cb98faSBarry Smith 
5985a1cb98faSBarry Smith   Collective
59868ca92349SMatthew G. Knepley 
59878ca92349SMatthew G. Knepley + comm        - The MPI communicator
59888ca92349SMatthew G. Knepley . filename    - Name of the .dat file
59898ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
59908ca92349SMatthew G. Knepley 
59918ca92349SMatthew G. Knepley   Output Parameter:
5992a1cb98faSBarry Smith . dm  - The `DM` object representing the mesh
59938ca92349SMatthew G. Knepley 
59948ca92349SMatthew G. Knepley   Level: beginner
59958ca92349SMatthew G. Knepley 
5996a1cb98faSBarry Smith   Note:
5997a1cb98faSBarry Smith   The format is the simplest possible:
5998a1cb98faSBarry Smith .vb
5999d0812dedSMatthew G. Knepley   dim Ne Nv Nc Nl
6000d0812dedSMatthew G. Knepley   v_1 v_2 ... v_Nc
6001d0812dedSMatthew G. Knepley   ...
6002d0812dedSMatthew G. Knepley   x y z marker_1 ... marker_Nl
6003a1cb98faSBarry Smith .ve
6004a1cb98faSBarry Smith 
6005a1cb98faSBarry Smith   Developer Note:
6006a1cb98faSBarry Smith   Should use a `PetscViewer` not a filename
6007a1cb98faSBarry Smith 
60086afe31f6SMartin Diehl .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
6009a4e35b19SJacob Faibussowitsch */
6010ff6a9541SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
6011d71ae5a4SJacob Faibussowitsch {
60128ca92349SMatthew G. Knepley   DMLabel      marker;
60138ca92349SMatthew G. Knepley   PetscViewer  viewer;
60148ca92349SMatthew G. Knepley   Vec          coordinates;
60158ca92349SMatthew G. Knepley   PetscSection coordSection;
60168ca92349SMatthew G. Knepley   PetscScalar *coords;
60178ca92349SMatthew G. Knepley   char         line[PETSC_MAX_PATH_LEN];
6018d0812dedSMatthew G. Knepley   PetscInt     cdim, coordSize, v, c, d;
60198ca92349SMatthew G. Knepley   PetscMPIInt  rank;
6020d0812dedSMatthew G. Knepley   int          snum, dim, Nv, Nc, Ncn, Nl;
60218ca92349SMatthew G. Knepley 
60228ca92349SMatthew G. Knepley   PetscFunctionBegin;
60239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
60249566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
60259566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
60269566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
60279566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
6028dd400576SPatrick Sanan   if (rank == 0) {
6029d0812dedSMatthew G. Knepley     PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING));
6030d0812dedSMatthew G. Knepley     snum = sscanf(line, "%d %d %d %d %d", &dim, &Nc, &Nv, &Ncn, &Nl);
6031d0812dedSMatthew G. Knepley     PetscCheck(snum == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
603225ce1634SJed Brown   } else {
6033f8d5e320SMatthew G. Knepley     Nc = Nv = Ncn = Nl = 0;
60348ca92349SMatthew G. Knepley   }
6035d0812dedSMatthew G. Knepley   PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm));
6036d0812dedSMatthew G. Knepley   cdim = (PetscInt)dim;
60379566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
60389566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
60399566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
6040d0812dedSMatthew G. Knepley   PetscCall(DMSetDimension(*dm, (PetscInt)dim));
60419566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, cdim));
60428ca92349SMatthew G. Knepley   /* Read topology */
6043dd400576SPatrick Sanan   if (rank == 0) {
6044f8d5e320SMatthew G. Knepley     char     format[PETSC_MAX_PATH_LEN];
6045f8d5e320SMatthew G. Knepley     PetscInt cone[8];
60468ca92349SMatthew G. Knepley     int      vbuf[8], v;
60478ca92349SMatthew G. Knepley 
60489371c9d4SSatish Balay     for (c = 0; c < Ncn; ++c) {
60499371c9d4SSatish Balay       format[c * 3 + 0] = '%';
60509371c9d4SSatish Balay       format[c * 3 + 1] = 'd';
60519371c9d4SSatish Balay       format[c * 3 + 2] = ' ';
60529371c9d4SSatish Balay     }
6053f8d5e320SMatthew G. Knepley     format[Ncn * 3 - 1] = '\0';
60549566063dSJacob Faibussowitsch     for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn));
60559566063dSJacob Faibussowitsch     PetscCall(DMSetUp(*dm));
60568ca92349SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
60579566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING));
6058f8d5e320SMatthew G. Knepley       switch (Ncn) {
6059d71ae5a4SJacob Faibussowitsch       case 2:
6060d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1]);
6061d71ae5a4SJacob Faibussowitsch         break;
6062d71ae5a4SJacob Faibussowitsch       case 3:
6063d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]);
6064d71ae5a4SJacob Faibussowitsch         break;
6065d71ae5a4SJacob Faibussowitsch       case 4:
6066d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]);
6067d71ae5a4SJacob Faibussowitsch         break;
6068d71ae5a4SJacob Faibussowitsch       case 6:
6069d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]);
6070d71ae5a4SJacob Faibussowitsch         break;
6071d71ae5a4SJacob Faibussowitsch       case 8:
6072d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]);
6073d71ae5a4SJacob Faibussowitsch         break;
6074d71ae5a4SJacob Faibussowitsch       default:
6075d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn);
6076f8d5e320SMatthew G. Knepley       }
607708401ef6SPierre Jolivet       PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
6078f8d5e320SMatthew G. Knepley       for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc;
60798ca92349SMatthew G. Knepley       /* Hexahedra are inverted */
6080f8d5e320SMatthew G. Knepley       if (Ncn == 8) {
60818ca92349SMatthew G. Knepley         PetscInt tmp = cone[1];
60828ca92349SMatthew G. Knepley         cone[1]      = cone[3];
60838ca92349SMatthew G. Knepley         cone[3]      = tmp;
60848ca92349SMatthew G. Knepley       }
60859566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(*dm, c, cone));
60868ca92349SMatthew G. Knepley     }
60878ca92349SMatthew G. Knepley   }
60889566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
60899566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
60908ca92349SMatthew G. Knepley   /* Read coordinates */
60919566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
60929566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
60939566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
60949566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
60958ca92349SMatthew G. Knepley   for (v = Nc; v < Nc + Nv; ++v) {
60969566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
60979566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
60988ca92349SMatthew G. Knepley   }
60999566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
61009566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
61019566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
61029566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
61039566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
61049566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
61059566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
61069566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
6107dd400576SPatrick Sanan   if (rank == 0) {
6108f8d5e320SMatthew G. Knepley     char   format[PETSC_MAX_PATH_LEN];
61098ca92349SMatthew G. Knepley     double x[3];
6110f8d5e320SMatthew G. Knepley     int    l, val[3];
61118ca92349SMatthew G. Knepley 
6112f8d5e320SMatthew G. Knepley     if (Nl) {
61139371c9d4SSatish Balay       for (l = 0; l < Nl; ++l) {
61149371c9d4SSatish Balay         format[l * 3 + 0] = '%';
61159371c9d4SSatish Balay         format[l * 3 + 1] = 'd';
61169371c9d4SSatish Balay         format[l * 3 + 2] = ' ';
61179371c9d4SSatish Balay       }
6118f8d5e320SMatthew G. Knepley       format[Nl * 3 - 1] = '\0';
61199566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
61209566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &marker));
6121f8d5e320SMatthew G. Knepley     }
61228ca92349SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
61239566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING));
6124f8d5e320SMatthew G. Knepley       snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]);
612508401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
6126f8d5e320SMatthew G. Knepley       switch (Nl) {
6127d71ae5a4SJacob Faibussowitsch       case 0:
6128d71ae5a4SJacob Faibussowitsch         snum = 0;
6129d71ae5a4SJacob Faibussowitsch         break;
6130d71ae5a4SJacob Faibussowitsch       case 1:
6131d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0]);
6132d71ae5a4SJacob Faibussowitsch         break;
6133d71ae5a4SJacob Faibussowitsch       case 2:
6134d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1]);
6135d71ae5a4SJacob Faibussowitsch         break;
6136d71ae5a4SJacob Faibussowitsch       case 3:
6137d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1], &val[2]);
6138d71ae5a4SJacob Faibussowitsch         break;
6139d71ae5a4SJacob Faibussowitsch       default:
6140d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl);
6141f8d5e320SMatthew G. Knepley       }
614208401ef6SPierre Jolivet       PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
61438ca92349SMatthew G. Knepley       for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d];
61449566063dSJacob Faibussowitsch       for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l]));
61458ca92349SMatthew G. Knepley     }
61468ca92349SMatthew G. Knepley   }
61479566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
61489566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
61499566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
61509566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
61518ca92349SMatthew G. Knepley   if (interpolate) {
61528ca92349SMatthew G. Knepley     DM      idm;
61538ca92349SMatthew G. Knepley     DMLabel bdlabel;
61548ca92349SMatthew G. Knepley 
61559566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
61569566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
61578ca92349SMatthew G. Knepley     *dm = idm;
61588ca92349SMatthew G. Knepley 
6159f8d5e320SMatthew G. Knepley     if (!Nl) {
61609566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
61619566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &bdlabel));
61629566063dSJacob Faibussowitsch       PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel));
61639566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelComplete(*dm, bdlabel));
61648ca92349SMatthew G. Knepley     }
6165f8d5e320SMatthew G. Knepley   }
61663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
61678ca92349SMatthew G. Knepley }
61688ca92349SMatthew G. Knepley 
6169cc4c1da9SBarry Smith /*@
6170a1cb98faSBarry Smith   DMPlexCreateFromFile - This takes a filename and produces a `DM`
6171a1cb98faSBarry Smith 
6172a1cb98faSBarry Smith   Collective
6173ca522641SMatthew G. Knepley 
6174ca522641SMatthew G. Knepley   Input Parameters:
6175ca522641SMatthew G. Knepley + comm        - The communicator
6176ca522641SMatthew G. Knepley . filename    - A file name
6177a1cb98faSBarry Smith . plexname    - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats
6178ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
6179ca522641SMatthew G. Knepley 
6180ca522641SMatthew G. Knepley   Output Parameter:
6181a1cb98faSBarry Smith . dm - The `DM`
6182ca522641SMatthew G. Knepley 
6183a1cb98faSBarry Smith   Options Database Key:
6184a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5
618502ef0d99SVaclav Hapla 
618637fdd005SBarry Smith   Use `-dm_plex_create_ prefix` to pass options to the internal `PetscViewer`, e.g.
6187bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective
6188bca97951SVaclav Hapla 
6189ca522641SMatthew G. Knepley   Level: beginner
6190ca522641SMatthew G. Knepley 
6191a1cb98faSBarry Smith   Notes:
6192a1cb98faSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
6193a1cb98faSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
6194a1cb98faSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
6195a1cb98faSBarry Smith   The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally
6196a1cb98faSBarry Smith   calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats.
6197a1cb98faSBarry Smith 
61981cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()`
6199ca522641SMatthew G. Knepley @*/
6200d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm)
6201d71ae5a4SJacob Faibussowitsch {
6202ef3a5affSJacob Faibussowitsch   const char  extGmsh[]      = ".msh";
6203ef3a5affSJacob Faibussowitsch   const char  extGmsh2[]     = ".msh2";
6204ef3a5affSJacob Faibussowitsch   const char  extGmsh4[]     = ".msh4";
6205ef3a5affSJacob Faibussowitsch   const char  extCGNS[]      = ".cgns";
6206ef3a5affSJacob Faibussowitsch   const char  extExodus[]    = ".exo";
6207ef3a5affSJacob Faibussowitsch   const char  extExodus_e[]  = ".e";
6208ef3a5affSJacob Faibussowitsch   const char  extGenesis[]   = ".gen";
6209ef3a5affSJacob Faibussowitsch   const char  extFluent[]    = ".cas";
6210ef3a5affSJacob Faibussowitsch   const char  extHDF5[]      = ".h5";
62116f2c871aSStefano Zampini   const char  extXDMFHDF5[]  = ".xdmf.h5";
6212ef3a5affSJacob Faibussowitsch   const char  extPLY[]       = ".ply";
6213ef3a5affSJacob Faibussowitsch   const char  extEGADSLite[] = ".egadslite";
6214ef3a5affSJacob Faibussowitsch   const char  extEGADS[]     = ".egads";
6215ef3a5affSJacob Faibussowitsch   const char  extIGES[]      = ".igs";
6216ef3a5affSJacob Faibussowitsch   const char  extSTEP[]      = ".stp";
6217ef3a5affSJacob Faibussowitsch   const char  extCV[]        = ".dat";
6218ca522641SMatthew G. Knepley   size_t      len;
62196afe31f6SMartin Diehl   PetscBool   isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isPLY, isEGADSLite, isEGADS, isIGES, isSTEP, isCV, isXDMFHDF5;
6220ca522641SMatthew G. Knepley   PetscMPIInt rank;
6221ca522641SMatthew G. Knepley 
6222ca522641SMatthew G. Knepley   PetscFunctionBegin;
62234f572ea9SToby Isaac   PetscAssertPointer(filename, 2);
62244f572ea9SToby Isaac   if (plexname) PetscAssertPointer(plexname, 3);
62254f572ea9SToby Isaac   PetscAssertPointer(dm, 5);
62269566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
62279566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0));
62289566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
62299566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(filename, &len));
623028b400f6SJacob Faibussowitsch   PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path");
6231ef3a5affSJacob Faibussowitsch 
62329371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \
62339371c9d4SSatish Balay   do { \
6234274aaeaaSJacob Faibussowitsch     PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \
6235274aaeaaSJacob Faibussowitsch     /* don't count the null-terminator at the end */ \
6236274aaeaaSJacob Faibussowitsch     const size_t ext_len = sizeof(extension__) - 1; \
6237274aaeaaSJacob Faibussowitsch     if (len < ext_len) { \
6238ef3a5affSJacob Faibussowitsch       is_extension__ = PETSC_FALSE; \
6239ef3a5affSJacob Faibussowitsch     } else { \
6240274aaeaaSJacob Faibussowitsch       PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \
6241ef3a5affSJacob Faibussowitsch     } \
6242ef3a5affSJacob Faibussowitsch   } while (0)
6243ef3a5affSJacob Faibussowitsch 
6244ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh, isGmsh);
6245ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh2, isGmsh2);
6246ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh4, isGmsh4);
6247ef3a5affSJacob Faibussowitsch   CheckExtension(extCGNS, isCGNS);
6248ef3a5affSJacob Faibussowitsch   CheckExtension(extExodus, isExodus);
6249ef3a5affSJacob Faibussowitsch   if (!isExodus) CheckExtension(extExodus_e, isExodus);
6250ef3a5affSJacob Faibussowitsch   CheckExtension(extGenesis, isGenesis);
6251ef3a5affSJacob Faibussowitsch   CheckExtension(extFluent, isFluent);
6252ef3a5affSJacob Faibussowitsch   CheckExtension(extHDF5, isHDF5);
6253ef3a5affSJacob Faibussowitsch   CheckExtension(extPLY, isPLY);
6254ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADSLite, isEGADSLite);
6255ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADS, isEGADS);
6256ef3a5affSJacob Faibussowitsch   CheckExtension(extIGES, isIGES);
6257ef3a5affSJacob Faibussowitsch   CheckExtension(extSTEP, isSTEP);
6258ef3a5affSJacob Faibussowitsch   CheckExtension(extCV, isCV);
62596f2c871aSStefano Zampini   CheckExtension(extXDMFHDF5, isXDMFHDF5);
6260ef3a5affSJacob Faibussowitsch 
6261ef3a5affSJacob Faibussowitsch #undef CheckExtension
6262ef3a5affSJacob Faibussowitsch 
6263de78e4feSLisandro Dalcin   if (isGmsh || isGmsh2 || isGmsh4) {
62649566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm));
6265ca522641SMatthew G. Knepley   } else if (isCGNS) {
62669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm));
626790c68965SMatthew G. Knepley   } else if (isExodus || isGenesis) {
62689566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm));
62692f0bd6dcSMichael Lange   } else if (isFluent) {
62709566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm));
6271cc2f8f65SMatthew G. Knepley   } else if (isHDF5) {
6272cc2f8f65SMatthew G. Knepley     PetscViewer viewer;
6273cc2f8f65SMatthew G. Knepley 
627443b242b4SVaclav 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 */
62756f2c871aSStefano Zampini     PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &isXDMFHDF5, NULL));
62769566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(comm, &viewer));
62779566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5));
62789566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_"));
62799566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetFromOptions(viewer));
62809566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
62819566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(viewer, filename));
6282cd7e8a5eSksagiyam 
62839566063dSJacob Faibussowitsch     PetscCall(DMCreate(comm, dm));
6284f4f49eeaSPierre Jolivet     PetscCall(PetscObjectSetName((PetscObject)*dm, plexname));
62859566063dSJacob Faibussowitsch     PetscCall(DMSetType(*dm, DMPLEX));
62866f2c871aSStefano Zampini     if (isXDMFHDF5) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF));
62879566063dSJacob Faibussowitsch     PetscCall(DMLoad(*dm, viewer));
62886f2c871aSStefano Zampini     if (isXDMFHDF5) PetscCall(PetscViewerPopFormat(viewer));
62899566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
62905fd9971aSMatthew G. Knepley 
62915fd9971aSMatthew G. Knepley     if (interpolate) {
62925fd9971aSMatthew G. Knepley       DM idm;
62935fd9971aSMatthew G. Knepley 
62949566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm));
62959566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
62965fd9971aSMatthew G. Knepley       *dm = idm;
62975fd9971aSMatthew G. Knepley     }
6298f2801cd6SMatthew G. Knepley   } else if (isPLY) {
62999566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm));
6300c1cad2e7SMatthew G. Knepley   } else if (isEGADSLite || isEGADS || isIGES || isSTEP) {
63019566063dSJacob Faibussowitsch     if (isEGADSLite) PetscCall(DMPlexCreateEGADSLiteFromFile(comm, filename, dm));
63029566063dSJacob Faibussowitsch     else PetscCall(DMPlexCreateEGADSFromFile(comm, filename, dm));
63037bee2925SMatthew Knepley     if (!interpolate) {
63047bee2925SMatthew Knepley       DM udm;
63057bee2925SMatthew Knepley 
63069566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(*dm, &udm));
63079566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
63087bee2925SMatthew Knepley       *dm = udm;
63097bee2925SMatthew Knepley     }
63108ca92349SMatthew G. Knepley   } else if (isCV) {
63119566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm));
631298921bdaSJacob Faibussowitsch   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename);
63139566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(plexname, &len));
6314f4f49eeaSPierre Jolivet   if (len) PetscCall(PetscObjectSetName((PetscObject)*dm, plexname));
63159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0));
63163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6317ca522641SMatthew G. Knepley }
631812b8a6daSStefano Zampini 
6319cc4c1da9SBarry Smith /*@
63209f6c5813SMatthew G. Knepley   DMPlexCreateEphemeral - This takes a `DMPlexTransform` and a base `DMPlex` and produces an ephemeral `DM`, meaning one that is created on the fly in response to queries.
63219f6c5813SMatthew G. Knepley 
63220528010dSStefano Zampini   Input Parameters:
63230528010dSStefano Zampini + tr     - The `DMPlexTransform`
63240528010dSStefano Zampini - prefix - An options prefix, or NULL
63259f6c5813SMatthew G. Knepley 
63269f6c5813SMatthew G. Knepley   Output Parameter:
63279f6c5813SMatthew G. Knepley . dm - The `DM`
63289f6c5813SMatthew G. Knepley 
63299f6c5813SMatthew G. Knepley   Level: beginner
63309f6c5813SMatthew G. Knepley 
633120f4b53cSBarry Smith   Notes:
633220f4b53cSBarry Smith   An emphemeral mesh is one that is not stored concretely, as in the default `DMPLEX` implementation, but rather is produced on the fly in response to queries, using information from the transform and the base mesh.
633320f4b53cSBarry Smith 
63349f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
63359f6c5813SMatthew G. Knepley @*/
63360528010dSStefano Zampini PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, const char prefix[], DM *dm)
63379f6c5813SMatthew G. Knepley {
63380528010dSStefano Zampini   DM           bdm, bcdm, cdm;
63390528010dSStefano Zampini   Vec          coordinates, coordinatesNew;
63400528010dSStefano Zampini   PetscSection cs;
6341817b2c36SMatthew G. Knepley   PetscInt     cdim, Nl;
63429f6c5813SMatthew G. Knepley 
63439f6c5813SMatthew G. Knepley   PetscFunctionBegin;
63449f6c5813SMatthew G. Knepley   PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm));
63459f6c5813SMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
63460528010dSStefano Zampini   ((DM_Plex *)(*dm)->data)->interpolated = DMPLEX_INTERPOLATED_FULL;
63470528010dSStefano Zampini   // Handle coordinates
63480528010dSStefano Zampini   PetscCall(DMPlexTransformGetDM(tr, &bdm));
6349817b2c36SMatthew G. Knepley   PetscCall(DMPlexTransformSetDimensions(tr, bdm, *dm));
6350817b2c36SMatthew G. Knepley   PetscCall(DMGetCoordinateDim(*dm, &cdim));
63510528010dSStefano Zampini   PetscCall(DMGetCoordinateDM(bdm, &bcdm));
63520528010dSStefano Zampini   PetscCall(DMGetCoordinateDM(*dm, &cdm));
63530528010dSStefano Zampini   PetscCall(DMCopyDisc(bcdm, cdm));
63540528010dSStefano Zampini   PetscCall(DMGetLocalSection(cdm, &cs));
63550528010dSStefano Zampini   PetscCall(PetscSectionSetNumFields(cs, 1));
63560528010dSStefano Zampini   PetscCall(PetscSectionSetFieldComponents(cs, 0, cdim));
63570528010dSStefano Zampini   PetscCall(DMGetCoordinatesLocal(bdm, &coordinates));
63580528010dSStefano Zampini   PetscCall(VecDuplicate(coordinates, &coordinatesNew));
63590528010dSStefano Zampini   PetscCall(VecCopy(coordinates, coordinatesNew));
63600528010dSStefano Zampini   PetscCall(DMSetCoordinatesLocal(*dm, coordinatesNew));
63610528010dSStefano Zampini   PetscCall(VecDestroy(&coordinatesNew));
63629f6c5813SMatthew G. Knepley 
63639f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)tr));
63649f6c5813SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr));
63659f6c5813SMatthew G. Knepley   ((DM_Plex *)(*dm)->data)->tr = tr;
63660528010dSStefano Zampini   PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE));
63670528010dSStefano Zampini   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix));
63680528010dSStefano Zampini   PetscCall(DMSetFromOptions(*dm));
63699f6c5813SMatthew G. Knepley 
63709f6c5813SMatthew G. Knepley   PetscCall(DMGetNumLabels(bdm, &Nl));
63719f6c5813SMatthew G. Knepley   for (PetscInt l = 0; l < Nl; ++l) {
63729f6c5813SMatthew G. Knepley     DMLabel     label, labelNew;
63739f6c5813SMatthew G. Knepley     const char *lname;
63749f6c5813SMatthew G. Knepley     PetscBool   isDepth, isCellType;
63759f6c5813SMatthew G. Knepley 
63769f6c5813SMatthew G. Knepley     PetscCall(DMGetLabelName(bdm, l, &lname));
63779f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "depth", &isDepth));
63789f6c5813SMatthew G. Knepley     if (isDepth) continue;
63799f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "celltype", &isCellType));
63809f6c5813SMatthew G. Knepley     if (isCellType) continue;
63819f6c5813SMatthew G. Knepley     PetscCall(DMCreateLabel(*dm, lname));
63829f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(bdm, lname, &label));
63839f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(*dm, lname, &labelNew));
63849f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL));
63859f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetLabel(labelNew, label));
63869f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetTransform(labelNew, tr));
63879f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetUp(labelNew));
63889f6c5813SMatthew G. Knepley   }
63893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63909f6c5813SMatthew G. Knepley }
6391