xref: /petsc/src/dm/impls/plex/plexcreate.c (revision 4c712d99815f8840d51416f1873ff454771de425)
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 
205552b385SBrandon PETSC_EXTERN PetscErrorCode DMPlexCheckEGADS_Private(DM dm)
215552b385SBrandon {
225552b385SBrandon   PetscObject modelObj;
235552b385SBrandon 
245552b385SBrandon   PetscFunctionBegin;
255552b385SBrandon   PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", &modelObj));
265552b385SBrandon   PetscCheck(modelObj, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Input DM must have attached EGADS Geometry Model");
275552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
285552b385SBrandon }
295552b385SBrandon 
305552b385SBrandon static PetscErrorCode DMPlexCopyContext_Private(DM dmin, const char name[], DM dmout)
315552b385SBrandon {
325552b385SBrandon   PetscObject obj;
335552b385SBrandon 
345552b385SBrandon   PetscFunctionBegin;
355552b385SBrandon   PetscCall(PetscObjectQuery((PetscObject)dmin, name, &obj));
365552b385SBrandon   if (obj) PetscCall(PetscObjectCompose((PetscObject)dmout, name, obj));
375552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
385552b385SBrandon }
395552b385SBrandon 
405552b385SBrandon static PetscErrorCode DMPlexSwapContext_Private(DM dmA, const char name[], DM dmB)
415552b385SBrandon {
425552b385SBrandon   PetscObject objA, objB;
435552b385SBrandon 
445552b385SBrandon   PetscFunctionBegin;
455552b385SBrandon   PetscCall(PetscObjectQuery((PetscObject)dmA, name, &objA));
465552b385SBrandon   PetscCall(PetscObjectQuery((PetscObject)dmB, name, &objB));
475552b385SBrandon   PetscCall(PetscObjectReference(objA));
485552b385SBrandon   PetscCall(PetscObjectReference(objB));
495552b385SBrandon   PetscCall(PetscObjectCompose((PetscObject)dmA, name, objB));
505552b385SBrandon   PetscCall(PetscObjectCompose((PetscObject)dmB, name, objA));
515552b385SBrandon   PetscCall(PetscObjectDereference(objA));
525552b385SBrandon   PetscCall(PetscObjectDereference(objB));
535552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
545552b385SBrandon }
555552b385SBrandon 
565552b385SBrandon PetscErrorCode DMPlexCopyEGADSInfo_Internal(DM dmin, DM dmout)
575552b385SBrandon {
585552b385SBrandon   PetscFunctionBegin;
595552b385SBrandon   PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Model", dmout));
605552b385SBrandon   PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Context", dmout));
615552b385SBrandon   PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Model", dmout));
625552b385SBrandon   PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Context", dmout));
635552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
645552b385SBrandon }
655552b385SBrandon 
665552b385SBrandon static PetscErrorCode DMPlexSwapEGADSInfo_Private(DM dmA, DM dmB)
675552b385SBrandon {
685552b385SBrandon   PetscFunctionBegin;
695552b385SBrandon   PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Model", dmB));
705552b385SBrandon   PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Context", dmB));
715552b385SBrandon   PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Model", dmB));
725552b385SBrandon   PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Context", dmB));
735552b385SBrandon   PetscFunctionReturn(PETSC_SUCCESS);
745552b385SBrandon }
755552b385SBrandon 
76e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */
77d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout)
78d71ae5a4SJacob Faibussowitsch {
794fb89dddSMatthew G. Knepley   const PetscReal     *maxCell, *Lstart, *L;
8012a88998SMatthew G. Knepley   VecType              vecType;
8112a88998SMatthew G. Knepley   MatType              matType;
82129f447cSJames Wright   PetscBool            dist, useCeed, balance_partition;
83adc21957SMatthew G. Knepley   DMReorderDefaultFlag reorder;
84e600fa54SMatthew G. Knepley 
85e600fa54SMatthew G. Knepley   PetscFunctionBegin;
86835f2295SStefano Zampini   if (dmin == dmout) PetscFunctionReturn(PETSC_SUCCESS);
8712a88998SMatthew G. Knepley   PetscCall(DMGetVecType(dmin, &vecType));
8812a88998SMatthew G. Knepley   PetscCall(DMSetVecType(dmout, vecType));
8912a88998SMatthew G. Knepley   PetscCall(DMGetMatType(dmin, &matType));
9012a88998SMatthew G. Knepley   PetscCall(DMSetMatType(dmout, matType));
91e600fa54SMatthew G. Knepley   if (copyPeriodicity) {
924fb89dddSMatthew G. Knepley     PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L));
934fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L));
943d0e8ed9SDavid Salac     PetscCall(DMLocalizeCoordinates(dmout));
95e600fa54SMatthew G. Knepley   }
969566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dmin, &dist));
979566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeSetDefault(dmout, dist));
986bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dmin, &reorder));
996bc1bd01Sksagiyam   PetscCall(DMPlexReorderSetDefault(dmout, reorder));
1005962854dSMatthew G. Knepley   PetscCall(DMPlexGetUseCeed(dmin, &useCeed));
1015962854dSMatthew G. Knepley   PetscCall(DMPlexSetUseCeed(dmout, useCeed));
102129f447cSJames Wright   PetscCall(DMPlexGetPartitionBalance(dmin, &balance_partition));
103129f447cSJames Wright   PetscCall(DMPlexSetPartitionBalance(dmout, balance_partition));
104e600fa54SMatthew G. Knepley   ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation;
1055962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printSetValues  = ((DM_Plex *)dmin->data)->printSetValues;
1065962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printFEM        = ((DM_Plex *)dmin->data)->printFEM;
1075962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printFVM        = ((DM_Plex *)dmin->data)->printFVM;
1085962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printL2         = ((DM_Plex *)dmin->data)->printL2;
1095962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printLocate     = ((DM_Plex *)dmin->data)->printLocate;
110a77a5016SMatthew G. Knepley   ((DM_Plex *)dmout->data)->printProject    = ((DM_Plex *)dmin->data)->printProject;
1115962854dSMatthew G. Knepley   ((DM_Plex *)dmout->data)->printTol        = ((DM_Plex *)dmin->data)->printTol;
1121baa6e33SBarry Smith   if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0));
1135552b385SBrandon   PetscCall(DMPlexCopyEGADSInfo_Internal(dmin, dmout));
1143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
115e600fa54SMatthew G. Knepley }
116e600fa54SMatthew G. Knepley 
1179318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm
1189318fe57SMatthew G. Knepley    - Share the DM_Plex structure
1199318fe57SMatthew G. Knepley    - Share the coordinates
1209318fe57SMatthew G. Knepley    - Share the SF
1219318fe57SMatthew G. Knepley */
122d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm)
123d71ae5a4SJacob Faibussowitsch {
1249318fe57SMatthew G. Knepley   PetscSF          sf;
1259318fe57SMatthew G. Knepley   DM               dmNew = *ndm, coordDM, coarseDM;
1269318fe57SMatthew G. Knepley   Vec              coords;
1272192575eSBarry Smith   PetscPointFn    *coordFunc;
1284fb89dddSMatthew G. Knepley   const PetscReal *maxCell, *Lstart, *L;
1299318fe57SMatthew G. Knepley   PetscInt         dim, cdim;
130e535cce4SJames Wright   PetscBool        use_natural;
1319318fe57SMatthew G. Knepley 
1329318fe57SMatthew G. Knepley   PetscFunctionBegin;
1339318fe57SMatthew G. Knepley   if (dm == dmNew) {
1349566063dSJacob Faibussowitsch     PetscCall(DMDestroy(ndm));
1353ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1369318fe57SMatthew G. Knepley   }
1379318fe57SMatthew G. Knepley   dm->setupcalled = dmNew->setupcalled;
138d0812dedSMatthew G. Knepley   if (!dm->hdr.name) {
139d0812dedSMatthew G. Knepley     const char *name;
140d0812dedSMatthew G. Knepley 
141d0812dedSMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)*ndm, &name));
142d0812dedSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, name));
143d0812dedSMatthew G. Knepley   }
1443674be70SMatthew G. Knepley   {
1453674be70SMatthew G. Knepley     PetscInt ndim;
1463674be70SMatthew G. Knepley 
1473674be70SMatthew G. Knepley     // If topological dimensions are the same, we retain the old coordinate map,
1483674be70SMatthew G. Knepley     //   otherwise we overwrite with the new one
1493674be70SMatthew G. Knepley     PetscCall(DMGetDimension(dm, &dim));
1503674be70SMatthew G. Knepley     PetscCall(DMGetDimension(dmNew, &ndim));
1513674be70SMatthew G. Knepley     PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc));
1523674be70SMatthew G. Knepley     if (dim == ndim) PetscCall(DMPlexSetCoordinateMap(dmNew, coordFunc));
1533674be70SMatthew G. Knepley   }
1549566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dmNew, &dim));
1559566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
1569566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmNew, &cdim));
1579566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
1589566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmNew, &sf));
1599566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sf));
1609566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmNew, &coordDM));
1619566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmNew, &coords));
1629566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dm, coordDM));
1639566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coords));
1646858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM));
1656858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords));
1666858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dm, coordDM));
1676858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dm, coords));
1689318fe57SMatthew G. Knepley   /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */
1696858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&dm->coordinates[0].field));
1706858538eSMatthew G. Knepley   dm->coordinates[0].field = dmNew->coordinates[0].field;
1714fb89dddSMatthew G. Knepley   PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L));
1724fb89dddSMatthew G. Knepley   PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
173e535cce4SJames Wright   PetscCall(DMGetNaturalSF(dmNew, &sf));
174e535cce4SJames Wright   PetscCall(DMSetNaturalSF(dm, sf));
175e535cce4SJames Wright   PetscCall(DMGetUseNatural(dmNew, &use_natural));
176e535cce4SJames Wright   PetscCall(DMSetUseNatural(dm, use_natural));
1779566063dSJacob Faibussowitsch   PetscCall(DMDestroy_Plex(dm));
1789566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
1799318fe57SMatthew G. Knepley   dm->data = dmNew->data;
1809318fe57SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->refct++;
1811fca310dSJames Wright   {
1821fca310dSJames Wright     PetscInt       num_face_sfs;
1831fca310dSJames Wright     const PetscSF *sfs;
1841fca310dSJames Wright     PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &sfs));
1851fca310dSJames Wright     PetscCall(DMPlexSetIsoperiodicFaceSF(dm, num_face_sfs, (PetscSF *)sfs)); // for the compose function effect on dm
1861fca310dSJames Wright   }
1879566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(dm));
1889566063dSJacob Faibussowitsch   PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL));
1899566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmNew, &coarseDM));
1909566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dm, coarseDM));
1915552b385SBrandon   PetscCall(DMPlexCopyEGADSInfo_Internal(dmNew, dm));
1929566063dSJacob Faibussowitsch   PetscCall(DMDestroy(ndm));
1933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1949318fe57SMatthew G. Knepley }
1959318fe57SMatthew G. Knepley 
1969318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew
1979318fe57SMatthew G. Knepley    - Swap the DM_Plex structure
1989318fe57SMatthew G. Knepley    - Swap the coordinates
1999318fe57SMatthew G. Knepley    - Swap the point PetscSF
2009318fe57SMatthew G. Knepley */
201d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB)
202d71ae5a4SJacob Faibussowitsch {
2039318fe57SMatthew G. Knepley   DM          coordDMA, coordDMB;
2049318fe57SMatthew G. Knepley   Vec         coordsA, coordsB;
2059318fe57SMatthew G. Knepley   PetscSF     sfA, sfB;
2069318fe57SMatthew G. Knepley   DMField     fieldTmp;
2079318fe57SMatthew G. Knepley   void       *tmp;
2089318fe57SMatthew G. Knepley   DMLabelLink listTmp;
2099318fe57SMatthew G. Knepley   DMLabel     depthTmp;
2109318fe57SMatthew G. Knepley   PetscInt    tmpI;
2119318fe57SMatthew G. Knepley 
2129318fe57SMatthew G. Knepley   PetscFunctionBegin;
2133ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
2149566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmA, &sfA));
2159566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmB, &sfB));
2169566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sfA));
2179566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmA, sfB));
2189566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmB, sfA));
2199566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)sfA));
2209318fe57SMatthew G. Knepley 
2219566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmA, &coordDMA));
2229566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmB, &coordDMB));
2239566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordDMA));
2249566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmA, coordDMB));
2259566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmB, coordDMA));
2269566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
2279318fe57SMatthew G. Knepley 
2289566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordsA));
2299566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmB, &coordsB));
2309566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordsA));
2319566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmA, coordsB));
2329566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordsA));
2339566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordsA));
2349318fe57SMatthew G. Knepley 
2356858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA));
2366858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB));
2376858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordDMA));
2386858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmA, coordDMB));
2396858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmB, coordDMA));
2406858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
2416858538eSMatthew G. Knepley 
2426858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA));
2436858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB));
2446858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordsA));
2456858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB));
2466858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA));
2476858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordsA));
2486858538eSMatthew G. Knepley 
2495552b385SBrandon   PetscCall(DMPlexSwapEGADSInfo_Private(dmA, dmB));
2505552b385SBrandon 
2516858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[0].field;
2526858538eSMatthew G. Knepley   dmA->coordinates[0].field = dmB->coordinates[0].field;
2536858538eSMatthew G. Knepley   dmB->coordinates[0].field = fieldTmp;
2546858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[1].field;
2556858538eSMatthew G. Knepley   dmA->coordinates[1].field = dmB->coordinates[1].field;
2566858538eSMatthew G. Knepley   dmB->coordinates[1].field = fieldTmp;
2579318fe57SMatthew G. Knepley   tmp                       = dmA->data;
2589318fe57SMatthew G. Knepley   dmA->data                 = dmB->data;
2599318fe57SMatthew G. Knepley   dmB->data                 = tmp;
2609318fe57SMatthew G. Knepley   listTmp                   = dmA->labels;
2619318fe57SMatthew G. Knepley   dmA->labels               = dmB->labels;
2629318fe57SMatthew G. Knepley   dmB->labels               = listTmp;
2639318fe57SMatthew G. Knepley   depthTmp                  = dmA->depthLabel;
2649318fe57SMatthew G. Knepley   dmA->depthLabel           = dmB->depthLabel;
2659318fe57SMatthew G. Knepley   dmB->depthLabel           = depthTmp;
2669318fe57SMatthew G. Knepley   depthTmp                  = dmA->celltypeLabel;
2679318fe57SMatthew G. Knepley   dmA->celltypeLabel        = dmB->celltypeLabel;
2689318fe57SMatthew G. Knepley   dmB->celltypeLabel        = depthTmp;
2699318fe57SMatthew G. Knepley   tmpI                      = dmA->levelup;
2709318fe57SMatthew G. Knepley   dmA->levelup              = dmB->levelup;
2719318fe57SMatthew G. Knepley   dmB->levelup              = tmpI;
2723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2739318fe57SMatthew G. Knepley }
2749318fe57SMatthew G. Knepley 
2753431e603SJed Brown PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm)
276d71ae5a4SJacob Faibussowitsch {
2779318fe57SMatthew G. Knepley   DM idm;
2789318fe57SMatthew G. Knepley 
2799318fe57SMatthew G. Knepley   PetscFunctionBegin;
2809566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolate(dm, &idm));
2819566063dSJacob Faibussowitsch   PetscCall(DMPlexCopyCoordinates(dm, idm));
28269d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &idm));
2833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2849318fe57SMatthew G. Knepley }
2859318fe57SMatthew G. Knepley 
2869318fe57SMatthew G. Knepley /*@C
2879318fe57SMatthew G. Knepley   DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates
2889318fe57SMatthew G. Knepley 
28920f4b53cSBarry Smith   Collective
2909318fe57SMatthew G. Knepley 
2919318fe57SMatthew G. Knepley   Input Parameters:
29260225df5SJacob Faibussowitsch + dm        - The `DMPLEX`
29320f4b53cSBarry Smith . degree    - The degree of the finite element or `PETSC_DECIDE`
294*4c712d99Sksagiyam . localized - Flag to create a localized (DG) coordinate space
295e44f6aebSMatthew G. Knepley . project   - Flag to project current coordinates into the space
2969318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface
2979318fe57SMatthew G. Knepley 
2989318fe57SMatthew G. Knepley   Level: advanced
2999318fe57SMatthew G. Knepley 
3002192575eSBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPointFn`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()`
3019318fe57SMatthew G. Knepley @*/
302*4c712d99Sksagiyam PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscBool localized, PetscBool project, PetscPointFn *coordFunc)
303d71ae5a4SJacob Faibussowitsch {
304e44f6aebSMatthew G. Knepley   PetscFE  fe = NULL;
3059318fe57SMatthew G. Knepley   DM       cdm;
306ac9d17c7SMatthew G. Knepley   PetscInt dim, cdim, dE, qorder, height;
3079318fe57SMatthew G. Knepley 
308e44f6aebSMatthew G. Knepley   PetscFunctionBegin;
3099566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
310ac9d17c7SMatthew G. Knepley   cdim = dim;
3119566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
3129318fe57SMatthew G. Knepley   qorder = degree;
313e44f6aebSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
314509b31aaSMatthew G. Knepley   if (!coordFunc) PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc));
315d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)cdm);
316dc431b0cSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0));
317ac9d17c7SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_coordinate_dim", "Set the coordinate dimension", "DMPlexCreateCoordinateSpace", cdim, &cdim, NULL, dim));
318d0609cedSBarry Smith   PetscOptionsEnd();
3191df12153SMatthew G. Knepley   PetscCall(DMPlexGetVTKCellHeight(dm, &height));
320ac9d17c7SMatthew G. Knepley   if (cdim > dim) {
321ac9d17c7SMatthew G. Knepley     DM           cdm;
322ac9d17c7SMatthew G. Knepley     PetscSection cs, csNew;
323ac9d17c7SMatthew G. Knepley     Vec          coordinates, coordinatesNew;
324ac9d17c7SMatthew G. Knepley     VecType      vectype;
325ac9d17c7SMatthew G. Knepley     IS           idx;
326ac9d17c7SMatthew G. Knepley     PetscInt    *indices;
327ac9d17c7SMatthew G. Knepley     PetscInt     bs, n;
328ac9d17c7SMatthew G. Knepley 
329ac9d17c7SMatthew G. Knepley     // Recreate coordinate section
330ac9d17c7SMatthew G. Knepley     {
331ac9d17c7SMatthew G. Knepley       const char *fieldName = NULL, *compName = NULL;
332ac9d17c7SMatthew G. Knepley       PetscInt    Nc, pStart, pEnd;
333ac9d17c7SMatthew G. Knepley 
334ac9d17c7SMatthew G. Knepley       PetscCall(DMGetCoordinateDM(dm, &cdm));
335ac9d17c7SMatthew G. Knepley       PetscCall(DMGetLocalSection(cdm, &cs));
336ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cs), &csNew));
337ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetNumFields(csNew, 1));
338ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionGetFieldName(cs, 0, &fieldName));
339ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetFieldName(csNew, 0, fieldName));
340ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionGetFieldComponents(cs, 0, &Nc));
341ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetFieldComponents(csNew, 0, cdim));
342ac9d17c7SMatthew G. Knepley       for (PetscInt c = 0; c < Nc; ++c) {
343ac9d17c7SMatthew G. Knepley         PetscCall(PetscSectionGetComponentName(cs, 0, c, &compName));
344ac9d17c7SMatthew G. Knepley         PetscCall(PetscSectionSetComponentName(csNew, 0, c, compName));
345ac9d17c7SMatthew G. Knepley       }
346ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionGetChart(cs, &pStart, &pEnd));
347ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetChart(csNew, pStart, pEnd));
348ac9d17c7SMatthew G. Knepley       for (PetscInt p = pStart; p < pEnd; ++p) {
349530e699aSMatthew G. Knepley         PetscInt dof;
350530e699aSMatthew G. Knepley 
351530e699aSMatthew G. Knepley         PetscCall(PetscSectionGetDof(cs, p, &dof));
352530e699aSMatthew G. Knepley         if (dof) {
353ac9d17c7SMatthew G. Knepley           PetscCall(PetscSectionSetDof(csNew, p, cdim));
354ac9d17c7SMatthew G. Knepley           PetscCall(PetscSectionSetFieldDof(csNew, p, 0, cdim));
355ac9d17c7SMatthew G. Knepley         }
356530e699aSMatthew G. Knepley       }
357ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetUp(csNew));
358ac9d17c7SMatthew G. Knepley     }
359ac9d17c7SMatthew G. Knepley     PetscCall(DMSetLocalSection(cdm, csNew));
360ac9d17c7SMatthew G. Knepley     PetscCall(PetscSectionDestroy(&csNew));
361530e699aSMatthew G. Knepley     // Reset coordinate dimension for coordinate DM
362530e699aSMatthew G. Knepley     PetscCall(DMSetCoordinateDim(cdm, cdim));
363530e699aSMatthew G. Knepley     PetscCall(DMSetCoordinateField(cdm, NULL));
364ac9d17c7SMatthew G. Knepley     // Inject coordinates into higher dimension
365ac9d17c7SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
366ac9d17c7SMatthew G. Knepley     PetscCall(VecGetBlockSize(coordinates, &bs));
367ac9d17c7SMatthew G. Knepley     PetscCheck(bs == dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension");
368ac9d17c7SMatthew G. Knepley     PetscCall(VecCreate(PetscObjectComm((PetscObject)coordinates), &coordinatesNew));
369ac9d17c7SMatthew G. Knepley     PetscCall(VecGetType(coordinates, &vectype));
370ac9d17c7SMatthew G. Knepley     PetscCall(VecSetType(coordinatesNew, vectype));
371ac9d17c7SMatthew G. Knepley     PetscCall(VecGetLocalSize(coordinates, &n));
372ac9d17c7SMatthew G. Knepley     PetscCheck(!(n % bs), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension");
373ac9d17c7SMatthew G. Knepley     n /= bs;
374ac9d17c7SMatthew G. Knepley     PetscCall(VecSetSizes(coordinatesNew, n * cdim, PETSC_DETERMINE));
375ac9d17c7SMatthew G. Knepley     PetscCall(VecSetUp(coordinatesNew));
376ac9d17c7SMatthew G. Knepley     PetscCall(PetscMalloc1(n * bs, &indices));
377ac9d17c7SMatthew G. Knepley     for (PetscInt i = 0; i < n; ++i)
378ac9d17c7SMatthew G. Knepley       for (PetscInt b = 0; b < bs; ++b) indices[i * bs + b] = i * cdim + b;
379ac9d17c7SMatthew G. Knepley     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n * bs, indices, PETSC_OWN_POINTER, &idx));
380ac9d17c7SMatthew G. Knepley     PetscCall(VecISCopy(coordinatesNew, idx, SCATTER_FORWARD, coordinates));
381ac9d17c7SMatthew G. Knepley     PetscCall(ISDestroy(&idx));
382ac9d17c7SMatthew G. Knepley     PetscCall(DMSetCoordinatesLocal(dm, coordinatesNew));
383ac9d17c7SMatthew G. Knepley     PetscCall(VecDestroy(&coordinatesNew));
384ac9d17c7SMatthew G. Knepley     PetscCall(DMSetCoordinateDim(dm, cdim));
385ac9d17c7SMatthew G. Knepley     {
386ac9d17c7SMatthew G. Knepley       PetscInt gn;
387ac9d17c7SMatthew G. Knepley 
388ac9d17c7SMatthew G. Knepley       PetscCall(DMGetCoordinates(dm, &coordinatesNew));
389ac9d17c7SMatthew G. Knepley       PetscCall(VecGetLocalSize(coordinatesNew, &gn));
390ac9d17c7SMatthew G. Knepley       PetscCheck(gn == n * cdim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Global coordinate size %" PetscInt_FMT " != %" PetscInt_FMT "local coordinate size", gn, n * cdim);
391ac9d17c7SMatthew G. Knepley     }
392ac9d17c7SMatthew G. Knepley     dE      = cdim;
393530e699aSMatthew G. Knepley     project = PETSC_FALSE;
394ac9d17c7SMatthew G. Knepley   }
395e44f6aebSMatthew G. Knepley   if (degree >= 0) {
396e44f6aebSMatthew G. Knepley     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
397e44f6aebSMatthew G. Knepley     PetscInt       cStart, cEnd, gct;
398dc431b0cSMatthew G. Knepley 
3991df12153SMatthew G. Knepley     PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd));
400dc431b0cSMatthew G. Knepley     if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct));
401e44f6aebSMatthew G. Knepley     gct = (PetscInt)ct;
402462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &gct, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm)));
403e44f6aebSMatthew G. Knepley     ct = (DMPolytopeType)gct;
404e44f6aebSMatthew G. Knepley     // Work around current bug in PetscDualSpaceSetUp_Lagrange()
405e44f6aebSMatthew G. Knepley     //   Can be seen in plex_tutorials-ex10_1
406*4c712d99Sksagiyam     if (ct != DM_POLYTOPE_SEG_PRISM_TENSOR && ct != DM_POLYTOPE_TRI_PRISM_TENSOR && ct != DM_POLYTOPE_QUAD_PRISM_TENSOR) {
407*4c712d99Sksagiyam       PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe));
408*4c712d99Sksagiyam       if (localized) {
409*4c712d99Sksagiyam         PetscFE dgfe = NULL;
410*4c712d99Sksagiyam 
411*4c712d99Sksagiyam         PetscCall(PetscFECreateBrokenElement(fe, &dgfe));
412*4c712d99Sksagiyam         PetscCall(PetscFEDestroy(&fe));
413*4c712d99Sksagiyam         fe = dgfe;
4144f9ab2b4SJed Brown       }
415*4c712d99Sksagiyam     }
416*4c712d99Sksagiyam   }
417*4c712d99Sksagiyam   PetscCall(DMSetCoordinateDisc(dm, fe, localized, project));
4189566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
4193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4209318fe57SMatthew G. Knepley }
4219318fe57SMatthew G. Knepley 
4221df5d5c5SMatthew G. Knepley /*@
4231df5d5c5SMatthew G. Knepley   DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement.
4241df5d5c5SMatthew G. Knepley 
425d083f849SBarry Smith   Collective
4261df5d5c5SMatthew G. Knepley 
4271df5d5c5SMatthew G. Knepley   Input Parameters:
428a1cb98faSBarry Smith + comm            - The communicator for the `DM` object
4291df5d5c5SMatthew G. Knepley . dim             - The spatial dimension
4301df5d5c5SMatthew G. Knepley . simplex         - Flag for simplicial cells, otherwise they are tensor product cells
4311df5d5c5SMatthew G. Knepley . interpolate     - Flag to create intermediate mesh pieces (edges, faces)
4321df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell
4331df5d5c5SMatthew G. Knepley 
4341df5d5c5SMatthew G. Knepley   Output Parameter:
43560225df5SJacob Faibussowitsch . newdm - The `DM` object
4361df5d5c5SMatthew G. Knepley 
4371df5d5c5SMatthew G. Knepley   Level: beginner
4381df5d5c5SMatthew G. Knepley 
4391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()`
4401df5d5c5SMatthew G. Knepley @*/
441d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm)
442d71ae5a4SJacob Faibussowitsch {
4431df5d5c5SMatthew G. Knepley   DM          dm;
4441df5d5c5SMatthew G. Knepley   PetscMPIInt rank;
4451df5d5c5SMatthew G. Knepley 
4461df5d5c5SMatthew G. Knepley   PetscFunctionBegin;
4479566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, &dm));
4489566063dSJacob Faibussowitsch   PetscCall(DMSetType(dm, DMPLEX));
4499566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
45046139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
4519566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
452ce78fa2fSMatthew G. Knepley   switch (dim) {
453ce78fa2fSMatthew G. Knepley   case 2:
4549566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular"));
4559566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral"));
456ce78fa2fSMatthew G. Knepley     break;
457ce78fa2fSMatthew G. Knepley   case 3:
4589566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral"));
4599566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral"));
460ce78fa2fSMatthew G. Knepley     break;
461d71ae5a4SJacob Faibussowitsch   default:
462d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
463ce78fa2fSMatthew G. Knepley   }
4641df5d5c5SMatthew G. Knepley   if (rank) {
4651df5d5c5SMatthew G. Knepley     PetscInt numPoints[2] = {0, 0};
4669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL));
4671df5d5c5SMatthew G. Knepley   } else {
4681df5d5c5SMatthew G. Knepley     switch (dim) {
4691df5d5c5SMatthew G. Knepley     case 2:
4701df5d5c5SMatthew G. Knepley       if (simplex) {
4711df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {4, 2};
4721df5d5c5SMatthew G. Knepley         PetscInt    coneSize[6]         = {3, 3, 0, 0, 0, 0};
4731df5d5c5SMatthew G. Knepley         PetscInt    cones[6]            = {2, 3, 4, 5, 4, 3};
4741df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
4751df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[8]     = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5};
4761df5d5c5SMatthew G. Knepley 
4779566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
4781df5d5c5SMatthew G. Knepley       } else {
4791df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {6, 2};
4801df5d5c5SMatthew G. Knepley         PetscInt    coneSize[8]         = {4, 4, 0, 0, 0, 0, 0, 0};
4811df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {2, 3, 4, 5, 3, 6, 7, 4};
4821df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
4831df5d5c5SMatthew 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};
4841df5d5c5SMatthew G. Knepley 
4859566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
4861df5d5c5SMatthew G. Knepley       }
4871df5d5c5SMatthew G. Knepley       break;
4881df5d5c5SMatthew G. Knepley     case 3:
4891df5d5c5SMatthew G. Knepley       if (simplex) {
4901df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {5, 2};
4911df5d5c5SMatthew G. Knepley         PetscInt    coneSize[7]         = {4, 4, 0, 0, 0, 0, 0};
4921df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {4, 3, 5, 2, 5, 3, 4, 6};
4931df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
4941df5d5c5SMatthew 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};
4951df5d5c5SMatthew G. Knepley 
4969566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
4971df5d5c5SMatthew G. Knepley       } else {
4981df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]         = {12, 2};
4991df5d5c5SMatthew G. Knepley         PetscInt    coneSize[14]         = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
5001df5d5c5SMatthew G. Knepley         PetscInt    cones[16]            = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8};
5011df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
5029371c9d4SSatish 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};
5031df5d5c5SMatthew G. Knepley 
5049566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
5051df5d5c5SMatthew G. Knepley       }
5061df5d5c5SMatthew G. Knepley       break;
507d71ae5a4SJacob Faibussowitsch     default:
508d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
5091df5d5c5SMatthew G. Knepley     }
5101df5d5c5SMatthew G. Knepley   }
51146139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
5121df5d5c5SMatthew G. Knepley   *newdm = dm;
5131df5d5c5SMatthew G. Knepley   if (refinementLimit > 0.0) {
5141df5d5c5SMatthew G. Knepley     DM          rdm;
5151df5d5c5SMatthew G. Knepley     const char *name;
5161df5d5c5SMatthew G. Knepley 
5179566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE));
5189566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit));
5199566063dSJacob Faibussowitsch     PetscCall(DMRefine(*newdm, comm, &rdm));
5209566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)*newdm, &name));
5219566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)rdm, name));
5229566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
5231df5d5c5SMatthew G. Knepley     *newdm = rdm;
5241df5d5c5SMatthew G. Knepley   }
5251df5d5c5SMatthew G. Knepley   if (interpolate) {
5265fd9971aSMatthew G. Knepley     DM idm;
5271df5d5c5SMatthew G. Knepley 
5289566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*newdm, &idm));
5299566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
5301df5d5c5SMatthew G. Knepley     *newdm = idm;
5311df5d5c5SMatthew G. Knepley   }
5323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5331df5d5c5SMatthew G. Knepley }
5341df5d5c5SMatthew G. Knepley 
535d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
536d71ae5a4SJacob Faibussowitsch {
5379318fe57SMatthew G. Knepley   const PetscInt numVertices    = 2;
5389318fe57SMatthew G. Knepley   PetscInt       markerRight    = 1;
5399318fe57SMatthew G. Knepley   PetscInt       markerLeft     = 1;
5409318fe57SMatthew G. Knepley   PetscBool      markerSeparate = PETSC_FALSE;
5419318fe57SMatthew G. Knepley   Vec            coordinates;
5429318fe57SMatthew G. Knepley   PetscSection   coordSection;
5439318fe57SMatthew G. Knepley   PetscScalar   *coords;
5449318fe57SMatthew G. Knepley   PetscInt       coordSize;
5459318fe57SMatthew G. Knepley   PetscMPIInt    rank;
5469318fe57SMatthew G. Knepley   PetscInt       cdim = 1, v;
547552f7358SJed Brown 
5489318fe57SMatthew G. Knepley   PetscFunctionBegin;
5499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
5509318fe57SMatthew G. Knepley   if (markerSeparate) {
5519318fe57SMatthew G. Knepley     markerRight = 2;
5529318fe57SMatthew G. Knepley     markerLeft  = 1;
5539318fe57SMatthew G. Knepley   }
5549566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
555c5853193SPierre Jolivet   if (rank == 0) {
5569566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numVertices));
5579566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
5589566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft));
5599566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight));
5609318fe57SMatthew G. Knepley   }
5619566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
5629566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
5639318fe57SMatthew G. Knepley   /* Build coordinates */
5649566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
5659566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
5669566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
5679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, 0, numVertices));
5689566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
5699318fe57SMatthew G. Knepley   for (v = 0; v < numVertices; ++v) {
5709566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
5719566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
5729318fe57SMatthew G. Knepley   }
5739566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
5749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
5759566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
5769566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
5779566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
5789566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
5799566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
5809566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
5819318fe57SMatthew G. Knepley   coords[0] = lower[0];
5829318fe57SMatthew G. Knepley   coords[1] = upper[0];
5839566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
5849566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
5859566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
5863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5879318fe57SMatthew G. Knepley }
58826492d91SMatthew G. Knepley 
589d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
590d71ae5a4SJacob Faibussowitsch {
5911df21d24SMatthew G. Knepley   const PetscInt numVertices    = (edges[0] + 1) * (edges[1] + 1);
5921df21d24SMatthew G. Knepley   const PetscInt numEdges       = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1];
593552f7358SJed Brown   PetscInt       markerTop      = 1;
594552f7358SJed Brown   PetscInt       markerBottom   = 1;
595552f7358SJed Brown   PetscInt       markerRight    = 1;
596552f7358SJed Brown   PetscInt       markerLeft     = 1;
597552f7358SJed Brown   PetscBool      markerSeparate = PETSC_FALSE;
598552f7358SJed Brown   Vec            coordinates;
599552f7358SJed Brown   PetscSection   coordSection;
600552f7358SJed Brown   PetscScalar   *coords;
601552f7358SJed Brown   PetscInt       coordSize;
602552f7358SJed Brown   PetscMPIInt    rank;
603552f7358SJed Brown   PetscInt       v, vx, vy;
604552f7358SJed Brown 
605552f7358SJed Brown   PetscFunctionBegin;
6069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
607552f7358SJed Brown   if (markerSeparate) {
6081df21d24SMatthew G. Knepley     markerTop    = 3;
6091df21d24SMatthew G. Knepley     markerBottom = 1;
6101df21d24SMatthew G. Knepley     markerRight  = 2;
6111df21d24SMatthew G. Knepley     markerLeft   = 4;
612552f7358SJed Brown   }
6139566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
614dd400576SPatrick Sanan   if (rank == 0) {
615552f7358SJed Brown     PetscInt e, ex, ey;
616552f7358SJed Brown 
6179566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices));
61848a46eb9SPierre Jolivet     for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
6199566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
620552f7358SJed Brown     for (vx = 0; vx <= edges[0]; vx++) {
621552f7358SJed Brown       for (ey = 0; ey < edges[1]; ey++) {
622552f7358SJed Brown         PetscInt edge   = vx * edges[1] + ey + edges[0] * (edges[1] + 1);
623552f7358SJed Brown         PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges;
624da80777bSKarl Rupp         PetscInt cone[2];
625552f7358SJed Brown 
6269371c9d4SSatish Balay         cone[0] = vertex;
6279371c9d4SSatish Balay         cone[1] = vertex + edges[0] + 1;
6289566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
629552f7358SJed Brown         if (vx == edges[0]) {
6309566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
6319566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
632552f7358SJed Brown           if (ey == edges[1] - 1) {
6339566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
6349566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight));
635552f7358SJed Brown           }
636552f7358SJed Brown         } else if (vx == 0) {
6379566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
6389566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
639552f7358SJed Brown           if (ey == edges[1] - 1) {
6409566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
6419566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft));
642552f7358SJed Brown           }
643552f7358SJed Brown         }
644552f7358SJed Brown       }
645552f7358SJed Brown     }
646552f7358SJed Brown     for (vy = 0; vy <= edges[1]; vy++) {
647552f7358SJed Brown       for (ex = 0; ex < edges[0]; ex++) {
648552f7358SJed Brown         PetscInt edge   = vy * edges[0] + ex;
649552f7358SJed Brown         PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges;
650da80777bSKarl Rupp         PetscInt cone[2];
651552f7358SJed Brown 
6529371c9d4SSatish Balay         cone[0] = vertex;
6539371c9d4SSatish Balay         cone[1] = vertex + 1;
6549566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
655552f7358SJed Brown         if (vy == edges[1]) {
6569566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
6579566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
658552f7358SJed Brown           if (ex == edges[0] - 1) {
6599566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
6609566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop));
661552f7358SJed Brown           }
662552f7358SJed Brown         } else if (vy == 0) {
6639566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
6649566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
665552f7358SJed Brown           if (ex == edges[0] - 1) {
6669566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
6679566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom));
668552f7358SJed Brown           }
669552f7358SJed Brown         }
670552f7358SJed Brown       }
671552f7358SJed Brown     }
672552f7358SJed Brown   }
6739566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
6749566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
675552f7358SJed Brown   /* Build coordinates */
6769566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 2));
6779566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
6789566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
6799566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices));
6809566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2));
681552f7358SJed Brown   for (v = numEdges; v < numEdges + numVertices; ++v) {
6829566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 2));
6839566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2));
684552f7358SJed Brown   }
6859566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
6869566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
6879566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
6889566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
6899566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
6909566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 2));
6919566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
6929566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
693552f7358SJed Brown   for (vy = 0; vy <= edges[1]; ++vy) {
694552f7358SJed Brown     for (vx = 0; vx <= edges[0]; ++vx) {
695552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx;
696552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy;
697552f7358SJed Brown     }
698552f7358SJed Brown   }
6999566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
7009566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
7019566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
7023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
703552f7358SJed Brown }
704552f7358SJed Brown 
705d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[])
706d71ae5a4SJacob Faibussowitsch {
7079e8abbc3SMichael Lange   PetscInt     vertices[3], numVertices;
7087b59f5a9SMichael Lange   PetscInt     numFaces       = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2];
709c2df9bbfSMatthew G. Knepley   PetscInt     markerTop      = 1;
710c2df9bbfSMatthew G. Knepley   PetscInt     markerBottom   = 1;
711c2df9bbfSMatthew G. Knepley   PetscInt     markerFront    = 1;
712c2df9bbfSMatthew G. Knepley   PetscInt     markerBack     = 1;
713c2df9bbfSMatthew G. Knepley   PetscInt     markerRight    = 1;
714c2df9bbfSMatthew G. Knepley   PetscInt     markerLeft     = 1;
715c2df9bbfSMatthew G. Knepley   PetscBool    markerSeparate = PETSC_FALSE;
716552f7358SJed Brown   Vec          coordinates;
717552f7358SJed Brown   PetscSection coordSection;
718552f7358SJed Brown   PetscScalar *coords;
719552f7358SJed Brown   PetscInt     coordSize;
720552f7358SJed Brown   PetscMPIInt  rank;
721552f7358SJed Brown   PetscInt     v, vx, vy, vz;
7227b59f5a9SMichael Lange   PetscInt     voffset, iface = 0, cone[4];
723552f7358SJed Brown 
724552f7358SJed Brown   PetscFunctionBegin;
7251dca8a05SBarry 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");
7269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
727c2df9bbfSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
728c2df9bbfSMatthew G. Knepley   if (markerSeparate) {
729c2df9bbfSMatthew G. Knepley     markerBottom = 1;
730c2df9bbfSMatthew G. Knepley     markerTop    = 2;
731c2df9bbfSMatthew G. Knepley     markerFront  = 3;
732c2df9bbfSMatthew G. Knepley     markerBack   = 4;
733c2df9bbfSMatthew G. Knepley     markerRight  = 5;
734c2df9bbfSMatthew G. Knepley     markerLeft   = 6;
735c2df9bbfSMatthew G. Knepley   }
7369371c9d4SSatish Balay   vertices[0] = faces[0] + 1;
7379371c9d4SSatish Balay   vertices[1] = faces[1] + 1;
7389371c9d4SSatish Balay   vertices[2] = faces[2] + 1;
7399e8abbc3SMichael Lange   numVertices = vertices[0] * vertices[1] * vertices[2];
740dd400576SPatrick Sanan   if (rank == 0) {
741552f7358SJed Brown     PetscInt f;
742552f7358SJed Brown 
7439566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices));
74448a46eb9SPierre Jolivet     for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
7459566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
7467b59f5a9SMichael Lange 
7477b59f5a9SMichael Lange     /* Side 0 (Top) */
7487b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
7497b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
7507b59f5a9SMichael Lange         voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx;
7519371c9d4SSatish Balay         cone[0] = voffset;
7529371c9d4SSatish Balay         cone[1] = voffset + 1;
7539371c9d4SSatish Balay         cone[2] = voffset + vertices[0] + 1;
7549371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
7559566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
756c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop));
757c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop));
758c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop));
759c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop));
760c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop));
7617b59f5a9SMichael Lange         iface++;
762552f7358SJed Brown       }
763552f7358SJed Brown     }
7647b59f5a9SMichael Lange 
7657b59f5a9SMichael Lange     /* Side 1 (Bottom) */
7667b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
7677b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
7687b59f5a9SMichael Lange         voffset = numFaces + vy * (faces[0] + 1) + vx;
7699371c9d4SSatish Balay         cone[0] = voffset + 1;
7709371c9d4SSatish Balay         cone[1] = voffset;
7719371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
7729371c9d4SSatish Balay         cone[3] = voffset + vertices[0] + 1;
7739566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
774c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom));
775c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom));
776c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom));
777c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom));
778c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom));
7797b59f5a9SMichael Lange         iface++;
780552f7358SJed Brown       }
781552f7358SJed Brown     }
7827b59f5a9SMichael Lange 
7837b59f5a9SMichael Lange     /* Side 2 (Front) */
7847b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
7857b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
7867b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vx;
7879371c9d4SSatish Balay         cone[0] = voffset;
7889371c9d4SSatish Balay         cone[1] = voffset + 1;
7899371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + 1;
7909371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1];
7919566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
792c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront));
793c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront));
794c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront));
795c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront));
796c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront));
7977b59f5a9SMichael Lange         iface++;
798552f7358SJed Brown       }
7997b59f5a9SMichael Lange     }
8007b59f5a9SMichael Lange 
8017b59f5a9SMichael Lange     /* Side 3 (Back) */
8027b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
8037b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
8047b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx;
8059371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
8069371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1] + 1;
8079371c9d4SSatish Balay         cone[2] = voffset + 1;
8089371c9d4SSatish Balay         cone[3] = voffset;
8099566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
810c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack));
811c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack));
812c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack));
813c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack));
814c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack));
8157b59f5a9SMichael Lange         iface++;
8167b59f5a9SMichael Lange       }
8177b59f5a9SMichael Lange     }
8187b59f5a9SMichael Lange 
8197b59f5a9SMichael Lange     /* Side 4 (Left) */
8207b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
8217b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
8227b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0];
8239371c9d4SSatish Balay         cone[0] = voffset;
8249371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1];
8259371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + vertices[0];
8269371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
8279566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
828c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft));
829c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft));
830c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft));
831c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft));
832c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft));
8337b59f5a9SMichael Lange         iface++;
8347b59f5a9SMichael Lange       }
8357b59f5a9SMichael Lange     }
8367b59f5a9SMichael Lange 
8377b59f5a9SMichael Lange     /* Side 5 (Right) */
8387b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
8397b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
840aab5bcd8SJed Brown         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0];
8419371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
8429371c9d4SSatish Balay         cone[1] = voffset;
8439371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
8449371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1] + vertices[0];
8459566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
846c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight));
847c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight));
848c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight));
849c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight));
850c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight));
8517b59f5a9SMichael Lange         iface++;
8527b59f5a9SMichael Lange       }
853552f7358SJed Brown     }
854552f7358SJed Brown   }
8559566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
8569566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
857552f7358SJed Brown   /* Build coordinates */
8589566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 3));
8599566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
8609566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
8619566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices));
8629566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3));
863552f7358SJed Brown   for (v = numFaces; v < numFaces + numVertices; ++v) {
8649566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 3));
8659566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3));
866552f7358SJed Brown   }
8679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
8689566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
8699566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
8709566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
8719566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
8729566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 3));
8739566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
8749566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
875552f7358SJed Brown   for (vz = 0; vz <= faces[2]; ++vz) {
876552f7358SJed Brown     for (vy = 0; vy <= faces[1]; ++vy) {
877552f7358SJed Brown       for (vx = 0; vx <= faces[0]; ++vx) {
878552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx;
879552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy;
880552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz;
881552f7358SJed Brown       }
882552f7358SJed Brown     }
883552f7358SJed Brown   }
8849566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
8859566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
8869566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
8873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
888552f7358SJed Brown }
889552f7358SJed Brown 
890d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate)
891d71ae5a4SJacob Faibussowitsch {
8929318fe57SMatthew G. Knepley   PetscFunctionBegin;
8939318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
89446139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
8959566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim - 1));
8969566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim));
8979318fe57SMatthew G. Knepley   switch (dim) {
898d71ae5a4SJacob Faibussowitsch   case 1:
899d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces));
900d71ae5a4SJacob Faibussowitsch     break;
901d71ae5a4SJacob Faibussowitsch   case 2:
902d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces));
903d71ae5a4SJacob Faibussowitsch     break;
904d71ae5a4SJacob Faibussowitsch   case 3:
905d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces));
906d71ae5a4SJacob Faibussowitsch     break;
907d71ae5a4SJacob Faibussowitsch   default:
908d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim);
9099318fe57SMatthew G. Knepley   }
91046139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
9119566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
9123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9139318fe57SMatthew G. Knepley }
9149318fe57SMatthew G. Knepley 
9159318fe57SMatthew G. Knepley /*@C
9169318fe57SMatthew G. Knepley   DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra).
9179318fe57SMatthew G. Knepley 
9189318fe57SMatthew G. Knepley   Collective
9199318fe57SMatthew G. Knepley 
9209318fe57SMatthew G. Knepley   Input Parameters:
921a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
92220f4b53cSBarry Smith . dim         - The spatial dimension of the box, so the resulting mesh is has dimension `dim`-1
92320f4b53cSBarry Smith . faces       - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
92420f4b53cSBarry Smith . lower       - The lower left corner, or `NULL` for (0, 0, 0)
92520f4b53cSBarry Smith . upper       - The upper right corner, or `NULL` for (1, 1, 1)
9269318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
9279318fe57SMatthew G. Knepley 
9289318fe57SMatthew G. Knepley   Output Parameter:
929a1cb98faSBarry Smith . dm - The `DM` object
9309318fe57SMatthew G. Knepley 
9319318fe57SMatthew G. Knepley   Level: beginner
9329318fe57SMatthew G. Knepley 
9331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()`
9349318fe57SMatthew G. Knepley @*/
935d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm)
936d71ae5a4SJacob Faibussowitsch {
9379318fe57SMatthew G. Knepley   PetscInt  fac[3] = {1, 1, 1};
9389318fe57SMatthew G. Knepley   PetscReal low[3] = {0, 0, 0};
9399318fe57SMatthew G. Knepley   PetscReal upp[3] = {1, 1, 1};
9409318fe57SMatthew G. Knepley 
9419318fe57SMatthew G. Knepley   PetscFunctionBegin;
9429566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
9439566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
9449566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate));
9453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9469318fe57SMatthew G. Knepley }
9479318fe57SMatthew G. Knepley 
948d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd)
949d71ae5a4SJacob Faibussowitsch {
950fdbf62faSLisandro Dalcin   PetscInt     i, fStart, fEnd, numCells = 0, numVerts = 0;
951fdbf62faSLisandro Dalcin   PetscInt     numPoints[2], *coneSize, *cones, *coneOrientations;
952fdbf62faSLisandro Dalcin   PetscScalar *vertexCoords;
953fdbf62faSLisandro Dalcin   PetscReal    L, maxCell;
954fdbf62faSLisandro Dalcin   PetscBool    markerSeparate = PETSC_FALSE;
955fdbf62faSLisandro Dalcin   PetscInt     markerLeft = 1, faceMarkerLeft = 1;
956fdbf62faSLisandro Dalcin   PetscInt     markerRight = 1, faceMarkerRight = 2;
957fdbf62faSLisandro Dalcin   PetscBool    wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE;
958fdbf62faSLisandro Dalcin   PetscMPIInt  rank;
959fdbf62faSLisandro Dalcin 
960fdbf62faSLisandro Dalcin   PetscFunctionBegin;
9614f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
962fdbf62faSLisandro Dalcin 
9639566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, 1));
9649566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
9659566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
966fdbf62faSLisandro Dalcin 
9679566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
968dd400576SPatrick Sanan   if (rank == 0) numCells = segments;
969dd400576SPatrick Sanan   if (rank == 0) numVerts = segments + (wrap ? 0 : 1);
970fdbf62faSLisandro Dalcin 
9719371c9d4SSatish Balay   numPoints[0] = numVerts;
9729371c9d4SSatish Balay   numPoints[1] = numCells;
9739566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords));
9749566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts));
975ad540459SPierre Jolivet   for (i = 0; i < numCells; ++i) coneSize[i] = 2;
976ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0;
9779371c9d4SSatish Balay   for (i = 0; i < numCells; ++i) {
9789371c9d4SSatish Balay     cones[2 * i]     = numCells + i % numVerts;
9799371c9d4SSatish Balay     cones[2 * i + 1] = numCells + (i + 1) % numVerts;
9809371c9d4SSatish Balay   }
981ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells);
9829566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
9839566063dSJacob Faibussowitsch   PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords));
984fdbf62faSLisandro Dalcin 
9859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
9869371c9d4SSatish Balay   if (markerSeparate) {
9879371c9d4SSatish Balay     markerLeft  = faceMarkerLeft;
9889371c9d4SSatish Balay     markerRight = faceMarkerRight;
9899371c9d4SSatish Balay   }
990dd400576SPatrick Sanan   if (!wrap && rank == 0) {
9919566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
9929566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft));
9939566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight));
9949566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft));
9959566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight));
996fdbf62faSLisandro Dalcin   }
997fdbf62faSLisandro Dalcin   if (wrap) {
998fdbf62faSLisandro Dalcin     L       = upper - lower;
999fdbf62faSLisandro Dalcin     maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments));
10004fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L));
1001fdbf62faSLisandro Dalcin   }
10029566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
10033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1004fdbf62faSLisandro Dalcin }
1005fdbf62faSLisandro Dalcin 
10064054ae39SJames Wright // Creates "Face Sets" label based on the standard box labeling conventions
1007d7d2d1d2SJames Wright static PetscErrorCode DMPlexSetBoxLabel_Internal(DM dm, const DMBoundaryType periodicity[])
10084054ae39SJames Wright {
10096ff49feeSJames Wright   DM              cdm;
10106ff49feeSJames Wright   PetscSection    csection;
10116ff49feeSJames Wright   Vec             coordinates;
10124054ae39SJames Wright   DMLabel         label;
10136ff49feeSJames Wright   IS              faces_is;
10142b4f33d9SJames Wright   PetscInt        dim, num_face = 0;
10154054ae39SJames Wright   const PetscInt *faces;
10164054ae39SJames Wright   PetscInt        faceMarkerBottom, faceMarkerTop, faceMarkerFront, faceMarkerBack, faceMarkerRight, faceMarkerLeft;
10174054ae39SJames Wright 
10184054ae39SJames Wright   PetscFunctionBeginUser;
10194054ae39SJames Wright   PetscCall(DMGetDimension(dm, &dim));
1020d7c1f440SPierre 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);
10214054ae39SJames Wright   // Get Face Sets label
10224054ae39SJames Wright   PetscCall(DMGetLabel(dm, "Face Sets", &label));
10234054ae39SJames Wright   if (label) {
10244054ae39SJames Wright     PetscCall(DMLabelReset(label));
10254054ae39SJames Wright   } else {
10264054ae39SJames Wright     PetscCall(DMCreateLabel(dm, "Face Sets"));
10274054ae39SJames Wright     PetscCall(DMGetLabel(dm, "Face Sets", &label));
10284054ae39SJames Wright   }
10294054ae39SJames Wright   PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label));
10306ff49feeSJames Wright   PetscCall(DMGetStratumIS(dm, "Face Sets", 1, &faces_is));
10314054ae39SJames Wright 
10324054ae39SJames Wright   switch (dim) {
10334054ae39SJames Wright   case 2:
10344054ae39SJames Wright     faceMarkerTop    = 3;
10354054ae39SJames Wright     faceMarkerBottom = 1;
10364054ae39SJames Wright     faceMarkerRight  = 2;
10374054ae39SJames Wright     faceMarkerLeft   = 4;
10384054ae39SJames Wright     break;
10394054ae39SJames Wright   case 3:
10404054ae39SJames Wright     faceMarkerBottom = 1;
10414054ae39SJames Wright     faceMarkerTop    = 2;
10424054ae39SJames Wright     faceMarkerFront  = 3;
10434054ae39SJames Wright     faceMarkerBack   = 4;
10444054ae39SJames Wright     faceMarkerRight  = 5;
10454054ae39SJames Wright     faceMarkerLeft   = 6;
10464054ae39SJames Wright     break;
10474054ae39SJames Wright   default:
10484054ae39SJames Wright     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
10494054ae39SJames Wright   }
10504054ae39SJames Wright 
10512b4f33d9SJames Wright   if (faces_is) PetscCall(ISGetLocalSize(faces_is, &num_face));
10522b4f33d9SJames Wright   if (faces_is) PetscCall(ISGetIndices(faces_is, &faces));
10536ff49feeSJames Wright   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
10546ff49feeSJames Wright   PetscCall(DMGetCoordinateDM(dm, &cdm));
10556ff49feeSJames Wright   PetscCall(DMGetLocalSection(cdm, &csection));
10564054ae39SJames Wright   for (PetscInt f = 0; f < num_face; ++f) {
10576ff49feeSJames Wright     PetscScalar *coords = NULL;
10586ff49feeSJames Wright     PetscInt     face = faces[f], flip = 1, label_value = -1, coords_size;
10594054ae39SJames Wright 
10604054ae39SJames Wright     { // Determine if orientation of face is flipped
10614054ae39SJames Wright       PetscInt        num_cells_support, num_faces, start = -1;
10624054ae39SJames Wright       const PetscInt *orients, *cell_faces, *cells;
10634054ae39SJames Wright 
10644054ae39SJames Wright       PetscCall(DMPlexGetSupport(dm, face, &cells));
10654054ae39SJames Wright       PetscCall(DMPlexGetSupportSize(dm, face, &num_cells_support));
10664054ae39SJames 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);
10674054ae39SJames Wright       PetscCall(DMPlexGetCone(dm, cells[0], &cell_faces));
10684054ae39SJames Wright       PetscCall(DMPlexGetConeSize(dm, cells[0], &num_faces));
10694054ae39SJames Wright       for (PetscInt i = 0; i < num_faces; i++) {
10704054ae39SJames Wright         if (cell_faces[i] == face) start = i;
10714054ae39SJames Wright       }
10724054ae39SJames Wright       PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Could not find face %" PetscInt_FMT " in cone of its support", face);
10734054ae39SJames Wright       PetscCall(DMPlexGetConeOrientation(dm, cells[0], &orients));
10744054ae39SJames Wright       if (orients[start] < 0) flip = -1;
10754054ae39SJames Wright     }
10764054ae39SJames Wright 
10776ff49feeSJames Wright     // Cannot use DMPlexComputeCellGeometryFVM() for high-order geometry, so must calculate normal vectors manually
10786ff49feeSJames Wright     // Use the vertices (depth 0) of coordinate DM to calculate normal vector
10796ff49feeSJames Wright     PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords));
10804054ae39SJames Wright     switch (dim) {
10814054ae39SJames Wright     case 2: {
10826ff49feeSJames Wright       PetscScalar vec[2];
10836ff49feeSJames Wright 
10846ff49feeSJames Wright       for (PetscInt d = 0; d < dim; ++d) vec[d] = flip * (PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]));
10856ff49feeSJames Wright       PetscScalar normal[] = {vec[1], -vec[0]};
10866ff49feeSJames Wright       if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) {
10876ff49feeSJames Wright         label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft;
10884054ae39SJames Wright       } else {
10896ff49feeSJames Wright         label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerTop : faceMarkerBottom;
10904054ae39SJames Wright       }
10914054ae39SJames Wright     } break;
10924054ae39SJames Wright     case 3: {
10936ff49feeSJames Wright       PetscScalar vec1[3], vec2[3], normal[3];
10946ff49feeSJames Wright 
10956ff49feeSJames Wright       for (PetscInt d = 0; d < dim; ++d) {
10966ff49feeSJames Wright         vec1[d] = PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]);
10976ff49feeSJames Wright         vec2[d] = PetscRealPart(coords[2 * dim + d]) - PetscRealPart(coords[1 * dim + d]);
10986ff49feeSJames Wright       }
10996ff49feeSJames Wright 
11006ff49feeSJames Wright       // Calculate normal vector via cross-product
11016ff49feeSJames Wright       normal[0] = flip * ((vec1[1] * vec2[2]) - (vec1[2] * vec2[1]));
11026ff49feeSJames Wright       normal[1] = flip * ((vec1[2] * vec2[0]) - (vec1[0] * vec2[2]));
11036ff49feeSJames Wright       normal[2] = flip * ((vec1[0] * vec2[1]) - (vec1[1] * vec2[0]));
11046ff49feeSJames Wright 
11056ff49feeSJames Wright       if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) {
11066ff49feeSJames Wright         if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[2])) {
11076ff49feeSJames Wright           label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft;
11084054ae39SJames Wright         } else {
11096ff49feeSJames Wright           label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom;
11104054ae39SJames Wright         }
11114054ae39SJames Wright       } else {
11126ff49feeSJames Wright         if (PetscAbsScalar(normal[1]) > PetscAbsScalar(normal[2])) {
11136ff49feeSJames Wright           label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerBack : faceMarkerFront;
11144054ae39SJames Wright         } else {
11156ff49feeSJames Wright           label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom;
11164054ae39SJames Wright         }
11174054ae39SJames Wright       }
11184054ae39SJames Wright     } break;
11194054ae39SJames Wright     }
11204054ae39SJames Wright 
11214054ae39SJames Wright     PetscInt previous_label_value; // always 1 due to DMPlexMarkBoundaryFaces call above
11224054ae39SJames Wright     PetscCall(DMGetLabelValue(dm, "Face Sets", face, &previous_label_value));
11234054ae39SJames Wright     PetscCall(DMClearLabelValue(dm, "Face Sets", face, previous_label_value));
11244054ae39SJames Wright     PetscCall(DMSetLabelValue(dm, "Face Sets", face, label_value));
11256ff49feeSJames Wright     PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords));
11264054ae39SJames Wright   }
11272b4f33d9SJames Wright   if (faces_is) PetscCall(ISRestoreIndices(faces_is, &faces));
11286ff49feeSJames Wright   PetscCall(ISDestroy(&faces_is));
1129d7d2d1d2SJames Wright 
1130d7d2d1d2SJames Wright   // Create Isoperiodic SF from newly-created face labels
1131d7d2d1d2SJames Wright   PetscSF     periodicsfs[3];
1132d7d2d1d2SJames Wright   PetscInt    periodic_sf_index  = 0;
1133d7d2d1d2SJames Wright   PetscScalar transform[3][4][4] = {{{0.}}};
1134d7d2d1d2SJames Wright   for (PetscInt d = 0; d < dim; d++) {
1135d7d2d1d2SJames Wright     IS              donor_is, periodic_is;
1136d7d2d1d2SJames Wright     const PetscInt *donor_faces = NULL, *periodic_faces = NULL;
1137d7d2d1d2SJames Wright     PetscInt        num_donor = 0, num_periodic = 0;
1138d7d2d1d2SJames Wright     PetscSF         centroidsf;
1139d7d2d1d2SJames Wright     PetscReal       donor_to_periodic_distance;
1140d7d2d1d2SJames Wright     const PetscInt  face_pairings[2][3][2] = {
1141d7d2d1d2SJames Wright       // 2D face pairings, {donor, periodic}
1142d7d2d1d2SJames Wright       {{4, 2}, {1, 3}},
1143d7d2d1d2SJames Wright       // 3D face pairings
1144d7d2d1d2SJames Wright       {{5, 6}, {3, 4}, {1, 2}}
1145d7d2d1d2SJames Wright     };
1146d7d2d1d2SJames Wright 
1147d7d2d1d2SJames Wright     if (periodicity[d] != DM_BOUNDARY_PERIODIC) continue;
1148d7d2d1d2SJames Wright     {
1149d7d2d1d2SJames Wright       // Compute centroidsf, which is the mapping from donor faces to periodic faces
1150d7d2d1d2SJames Wright       // Matches the centroid of the faces together, ignoring the periodic direction component (which should not match between donor and periodic face)
1151d7d2d1d2SJames Wright       PetscInt     coords_size, centroid_comps = dim - 1;
1152d7d2d1d2SJames Wright       PetscScalar *coords = NULL;
1153d7d2d1d2SJames Wright       PetscReal   *donor_centroids, *periodic_centroids;
1154d7d2d1d2SJames Wright       PetscReal    loc_periodic[2] = {PETSC_MIN_REAL, PETSC_MIN_REAL}, loc_periodic_global[2]; // Location of donor (0) and periodic (1) faces in periodic direction
1155d7d2d1d2SJames Wright 
1156d7d2d1d2SJames Wright       PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][0], &donor_is));
1157d7d2d1d2SJames Wright       PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][1], &periodic_is));
1158d7d2d1d2SJames Wright       if (donor_is) {
1159d7d2d1d2SJames Wright         PetscCall(ISGetLocalSize(donor_is, &num_donor));
1160d7d2d1d2SJames Wright         PetscCall(ISGetIndices(donor_is, &donor_faces));
1161d7d2d1d2SJames Wright       }
1162d7d2d1d2SJames Wright       if (periodic_is) {
1163d7d2d1d2SJames Wright         PetscCall(ISGetLocalSize(periodic_is, &num_periodic));
1164d7d2d1d2SJames Wright         PetscCall(ISGetIndices(periodic_is, &periodic_faces));
1165d7d2d1d2SJames Wright       }
1166d7d2d1d2SJames Wright       PetscCall(PetscCalloc2(num_donor * centroid_comps, &donor_centroids, num_periodic * centroid_comps, &periodic_centroids));
1167d7d2d1d2SJames Wright       for (PetscInt f = 0; f < num_donor; f++) {
1168d7d2d1d2SJames Wright         PetscInt face = donor_faces[f], num_coords;
1169d7d2d1d2SJames Wright         PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords));
1170d7d2d1d2SJames Wright         num_coords = coords_size / dim;
1171d7d2d1d2SJames Wright         for (PetscInt c = 0; c < num_coords; c++) {
1172d7d2d1d2SJames Wright           PetscInt comp_index = 0;
1173d7d2d1d2SJames Wright           loc_periodic[0]     = PetscRealPart(coords[c * dim + d]);
1174d7d2d1d2SJames Wright           for (PetscInt i = 0; i < dim; i++) {
1175d7d2d1d2SJames Wright             if (i == d) continue; // Periodic direction not used for centroid calculation
1176d7d2d1d2SJames Wright             donor_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords;
1177d7d2d1d2SJames Wright             comp_index++;
1178d7d2d1d2SJames Wright           }
1179d7d2d1d2SJames Wright         }
1180d7d2d1d2SJames Wright         PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords));
1181d7d2d1d2SJames Wright       }
1182d7d2d1d2SJames Wright 
1183d7d2d1d2SJames Wright       for (PetscInt f = 0; f < num_periodic; f++) {
1184d7d2d1d2SJames Wright         PetscInt face = periodic_faces[f], num_coords;
1185d7d2d1d2SJames Wright         PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords));
1186d7d2d1d2SJames Wright         num_coords = coords_size / dim;
1187d7d2d1d2SJames Wright         for (PetscInt c = 0; c < num_coords; c++) {
1188d7d2d1d2SJames Wright           PetscInt comp_index = 0;
1189d7d2d1d2SJames Wright           loc_periodic[1]     = PetscRealPart(coords[c * dim + d]);
1190d7d2d1d2SJames Wright           for (PetscInt i = 0; i < dim; i++) {
1191d7d2d1d2SJames Wright             if (i == d) continue; // Periodic direction not used for centroid calculation
1192d7d2d1d2SJames Wright             periodic_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords;
1193d7d2d1d2SJames Wright             comp_index++;
1194d7d2d1d2SJames Wright           }
1195d7d2d1d2SJames Wright         }
1196d7d2d1d2SJames Wright         PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords));
1197d7d2d1d2SJames Wright       }
1198d7d2d1d2SJames Wright       PetscCallMPI(MPIU_Allreduce(loc_periodic, loc_periodic_global, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm)));
1199d7d2d1d2SJames Wright       donor_to_periodic_distance = loc_periodic_global[1] - loc_periodic_global[0];
1200d7d2d1d2SJames Wright 
1201d7d2d1d2SJames Wright       PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &centroidsf));
1202d7d2d1d2SJames Wright       PetscCall(PetscSFSetGraphFromCoordinates(centroidsf, num_donor, num_periodic, centroid_comps, 1e-10, donor_centroids, periodic_centroids));
1203d7d2d1d2SJames Wright       PetscCall(PetscSFViewFromOptions(centroidsf, NULL, "-dm_plex_box_label_centroid_sf_view"));
1204d7d2d1d2SJames Wright       PetscCall(PetscFree2(donor_centroids, periodic_centroids));
1205d7d2d1d2SJames Wright     }
1206d7d2d1d2SJames Wright 
1207d7d2d1d2SJames Wright     { // Create Isoperiodic SF using centroidsSF
1208d7d2d1d2SJames Wright       PetscInt           pStart, pEnd;
1209d7d2d1d2SJames Wright       PetscInt          *leaf_faces;
1210d7d2d1d2SJames Wright       const PetscSFNode *firemote;
1211d7d2d1d2SJames Wright       PetscSFNode       *isoperiodic_leaves;
1212d7d2d1d2SJames Wright 
1213d7d2d1d2SJames Wright       PetscCall(PetscMalloc1(num_periodic, &leaf_faces));
1214d7d2d1d2SJames Wright       PetscCall(PetscSFBcastBegin(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE));
1215d7d2d1d2SJames Wright       PetscCall(PetscSFBcastEnd(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE));
1216d7d2d1d2SJames Wright 
1217d7d2d1d2SJames Wright       PetscCall(PetscMalloc1(num_periodic, &isoperiodic_leaves));
1218d7d2d1d2SJames Wright       PetscCall(PetscSFGetGraph(centroidsf, NULL, NULL, NULL, &firemote));
1219d7d2d1d2SJames Wright       for (PetscInt l = 0; l < num_periodic; ++l) {
1220d7d2d1d2SJames Wright         isoperiodic_leaves[l].index = leaf_faces[l];
1221d7d2d1d2SJames Wright         isoperiodic_leaves[l].rank  = firemote[l].rank;
1222d7d2d1d2SJames Wright       }
1223d7d2d1d2SJames Wright 
1224d7d2d1d2SJames Wright       PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
1225d7d2d1d2SJames Wright       PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &periodicsfs[periodic_sf_index]));
1226d7d2d1d2SJames Wright       PetscCall(PetscSFSetGraph(periodicsfs[periodic_sf_index], pEnd - pStart, num_periodic, (PetscInt *)periodic_faces, PETSC_COPY_VALUES, isoperiodic_leaves, PETSC_OWN_POINTER));
1227d7d2d1d2SJames Wright       PetscCall(PetscSFViewFromOptions(periodicsfs[periodic_sf_index], NULL, "-dm_plex_box_label_periodic_sf_view"));
1228d7d2d1d2SJames Wright       PetscCall(PetscFree(leaf_faces));
1229d7d2d1d2SJames Wright     }
1230d7d2d1d2SJames Wright 
1231d7d2d1d2SJames Wright     transform[periodic_sf_index][0][0] = 1;
1232d7d2d1d2SJames Wright     transform[periodic_sf_index][1][1] = 1;
1233d7d2d1d2SJames Wright     transform[periodic_sf_index][2][2] = 1;
1234d7d2d1d2SJames Wright     transform[periodic_sf_index][3][3] = 1;
1235d7d2d1d2SJames Wright     transform[periodic_sf_index][d][3] = donor_to_periodic_distance;
1236d7d2d1d2SJames Wright 
1237d7d2d1d2SJames Wright     periodic_sf_index++;
1238d7d2d1d2SJames Wright     PetscCall(PetscSFDestroy(&centroidsf));
1239d7d2d1d2SJames Wright     if (donor_is) {
1240d7d2d1d2SJames Wright       PetscCall(ISRestoreIndices(donor_is, &donor_faces));
1241d7d2d1d2SJames Wright       PetscCall(ISDestroy(&donor_is));
1242d7d2d1d2SJames Wright     }
1243d7d2d1d2SJames Wright     if (periodic_is) {
1244d7d2d1d2SJames Wright       PetscCall(ISRestoreIndices(periodic_is, &periodic_faces));
1245d7d2d1d2SJames Wright       PetscCall(ISDestroy(&periodic_is));
1246d7d2d1d2SJames Wright     }
1247d7d2d1d2SJames Wright     PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][0]));
1248d7d2d1d2SJames Wright     PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][1]));
1249d7d2d1d2SJames Wright   }
1250d7d2d1d2SJames Wright   PetscCall(DMPlexSetIsoperiodicFaceSF(dm, periodic_sf_index, periodicsfs));
1251d7d2d1d2SJames Wright   PetscCall(DMPlexSetIsoperiodicFaceTransform(dm, periodic_sf_index, (const PetscScalar *)transform));
1252d7d2d1d2SJames Wright   for (PetscInt p = 0; p < periodic_sf_index; p++) PetscCall(PetscSFDestroy(&periodicsfs[p]));
1253d7d2d1d2SJames Wright 
1254d7d2d1d2SJames Wright   { // Update coordinate DM with new Face Sets label
1255d7d2d1d2SJames Wright     DM      cdm;
1256d7d2d1d2SJames Wright     DMLabel oldFaceSets, newFaceSets;
1257d7d2d1d2SJames Wright     PetscCall(DMGetCoordinateDM(dm, &cdm));
1258d7d2d1d2SJames Wright     PetscCall(DMGetLabel(cdm, "Face Sets", &oldFaceSets));
1259d7d2d1d2SJames Wright     if (oldFaceSets) PetscCall(DMRemoveLabelBySelf(cdm, &oldFaceSets, PETSC_FALSE));
1260d7d2d1d2SJames Wright     PetscCall(DMLabelDuplicate(label, &newFaceSets));
1261d7d2d1d2SJames Wright     PetscCall(DMAddLabel(cdm, newFaceSets));
1262d7d2d1d2SJames Wright     PetscCall(DMLabelDestroy(&newFaceSets));
1263d7d2d1d2SJames Wright   }
12644054ae39SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
12654054ae39SJames Wright }
12664054ae39SJames Wright 
1267d698cf03SStefano Zampini static PetscErrorCode DMPlexCreateSquareMesh_Simplex_CrissCross(DM dm, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType bd[])
1268d698cf03SStefano Zampini {
1269d698cf03SStefano Zampini   PetscInt       markerTop = 1, faceMarkerTop = 3;
1270d698cf03SStefano Zampini   PetscInt       markerBottom = 1, faceMarkerBottom = 1;
1271d698cf03SStefano Zampini   PetscInt       markerRight = 1, faceMarkerRight = 2;
1272d698cf03SStefano Zampini   PetscInt       markerLeft = 1, faceMarkerLeft = 4;
1273d698cf03SStefano Zampini   PetscBool      markerSeparate = PETSC_FALSE;
1274d698cf03SStefano Zampini   DMBoundaryType bdX = bd[0], bdY = bd[1];
1275d698cf03SStefano Zampini   PetscMPIInt    rank;
1276d698cf03SStefano Zampini 
1277d698cf03SStefano Zampini   PetscFunctionBegin;
1278d698cf03SStefano Zampini   PetscCheck(bdX == DM_BOUNDARY_NONE || bdX == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdX]);
1279d698cf03SStefano Zampini   PetscCheck(bdY == DM_BOUNDARY_NONE || bdY == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdY]);
1280d698cf03SStefano Zampini   PetscCall(DMSetDimension(dm, 2));
1281d698cf03SStefano Zampini   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1282d698cf03SStefano Zampini   PetscCall(DMCreateLabel(dm, "marker"));
1283d698cf03SStefano Zampini   PetscCall(DMCreateLabel(dm, "Face Sets"));
1284d698cf03SStefano Zampini   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
1285d698cf03SStefano Zampini   if (markerSeparate) {
1286d698cf03SStefano Zampini     markerBottom = faceMarkerBottom;
1287d698cf03SStefano Zampini     markerTop    = faceMarkerTop;
1288d698cf03SStefano Zampini     markerRight  = faceMarkerRight;
1289d698cf03SStefano Zampini     markerLeft   = faceMarkerLeft;
1290d698cf03SStefano Zampini   }
1291d698cf03SStefano Zampini   {
1292d698cf03SStefano Zampini     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
1293d698cf03SStefano Zampini     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
1294d698cf03SStefano Zampini     const PetscInt numZEdges    = rank == 0 ? 4 * edges[0] * edges[1] : 0; /* Z-edges are the 4 internal edges per cell */
1295d698cf03SStefano Zampini     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC ? edges[0] : edges[0] + 1) : 0;
1296d698cf03SStefano Zampini     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC ? edges[1] : edges[1] + 1) : 0;
1297d698cf03SStefano Zampini     const PetscInt numZVertices = rank == 0 ? edges[0] * edges[1] : 0;
1298d698cf03SStefano Zampini     const PetscInt numCells     = 4 * numXEdges * numYEdges;
1299d698cf03SStefano Zampini     const PetscInt numTotXEdges = numXEdges * numYVertices;
1300d698cf03SStefano Zampini     const PetscInt numTotYEdges = numYEdges * numXVertices;
1301d698cf03SStefano Zampini     const PetscInt numVertices  = numXVertices * numYVertices + numZVertices;
1302d698cf03SStefano Zampini     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numZEdges;
1303d698cf03SStefano Zampini     const PetscInt firstVertex  = numCells;
1304d698cf03SStefano Zampini     const PetscInt firstXEdge   = numCells + numVertices;
1305d698cf03SStefano Zampini     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
1306d698cf03SStefano Zampini     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
1307d698cf03SStefano Zampini     Vec            coordinates;
1308d698cf03SStefano Zampini     PetscSection   coordSection;
1309d698cf03SStefano Zampini     PetscScalar   *coords;
1310d698cf03SStefano Zampini     PetscInt       coordSize;
1311d698cf03SStefano Zampini     PetscInt       v, vx, vy;
1312d698cf03SStefano Zampini     PetscInt       c, e, ex, ey;
1313d698cf03SStefano Zampini 
1314d698cf03SStefano Zampini     PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVertices));
1315d698cf03SStefano Zampini     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 3));
1316d698cf03SStefano Zampini     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
1317d698cf03SStefano Zampini     PetscCall(DMSetUp(dm));
1318d698cf03SStefano Zampini 
1319d698cf03SStefano Zampini     /* Build cells and Z-edges */
1320d698cf03SStefano Zampini     for (ey = 0; ey < numYEdges; ++ey) {
1321d698cf03SStefano Zampini       for (ex = 0; ex < numXEdges; ++ex) {
1322d698cf03SStefano Zampini         const PetscInt exp1 = (ex + 1) % numXVertices;
1323d698cf03SStefano Zampini         const PetscInt eyp1 = (ey + 1) % numYVertices;
1324d698cf03SStefano Zampini         const PetscInt ez   = firstZEdge + 4 * (ey * numXEdges + ex);
1325d698cf03SStefano Zampini         const PetscInt vc   = firstVertex + numXVertices * numYVertices + ey * numXEdges + ex;
1326d698cf03SStefano Zampini         const PetscInt v0   = firstVertex + ey * numXVertices + ex;
1327d698cf03SStefano Zampini         const PetscInt v1   = firstVertex + ey * numXVertices + exp1;
1328d698cf03SStefano Zampini         const PetscInt v2   = firstVertex + eyp1 * numXVertices + exp1;
1329d698cf03SStefano Zampini         const PetscInt v3   = firstVertex + eyp1 * numXVertices + ex;
1330d698cf03SStefano Zampini         const PetscInt e0   = firstXEdge + ey * numXEdges + ex;
1331d698cf03SStefano Zampini         const PetscInt e1   = firstYEdge + exp1 * numYEdges + ey;
1332d698cf03SStefano Zampini         const PetscInt e2   = firstXEdge + eyp1 * numXEdges + ex;
1333d698cf03SStefano Zampini         const PetscInt e3   = firstYEdge + ex * numYEdges + ey;
1334d698cf03SStefano Zampini 
1335d698cf03SStefano Zampini         const PetscInt cones[] = {ez, e0, ez + 1, ez + 1, e1, ez + 2, ez + 2, e2, ez + 3, ez + 3, e3, ez};
1336d698cf03SStefano Zampini         const PetscInt ornts[] = {-1, 0, 0, -1, 0, 0, -1, -1, 0, -1, -1, 0};
1337d698cf03SStefano Zampini         const PetscInt verts[] = {v0, vc, v1, vc, v2, vc, v3, vc};
1338d698cf03SStefano Zampini 
1339d698cf03SStefano Zampini         for (c = 0; c < 4; c++) {
1340d698cf03SStefano Zampini           PetscInt cell = 4 * (ey * numXEdges + ex) + c;
1341d698cf03SStefano Zampini           PetscInt edge = ez + c;
1342d698cf03SStefano Zampini 
1343d698cf03SStefano Zampini           PetscCall(DMPlexSetCone(dm, cell, cones + 3 * c));
1344d698cf03SStefano Zampini           PetscCall(DMPlexSetConeOrientation(dm, cell, ornts + 3 * c));
1345d698cf03SStefano Zampini           PetscCall(DMPlexSetCone(dm, edge, verts + 2 * c));
1346d698cf03SStefano Zampini         }
1347d698cf03SStefano Zampini       }
1348d698cf03SStefano Zampini     }
1349d698cf03SStefano Zampini 
1350d698cf03SStefano Zampini     /* Build Y edges*/
1351d698cf03SStefano Zampini     for (vx = 0; vx < numXVertices; vx++) {
1352d698cf03SStefano Zampini       for (ey = 0; ey < numYEdges; ey++) {
1353d698cf03SStefano Zampini         const PetscInt edge   = firstYEdge + vx * numYEdges + ey;
1354d698cf03SStefano Zampini         const PetscInt v0     = firstVertex + ey * numXVertices + vx;
1355d698cf03SStefano Zampini         const PetscInt v1     = firstVertex + ((ey + 1) % numYVertices) * numXVertices + vx;
1356d698cf03SStefano Zampini         const PetscInt cone[] = {v0, v1};
1357d698cf03SStefano Zampini 
1358d698cf03SStefano Zampini         PetscCall(DMPlexSetCone(dm, edge, cone));
1359d698cf03SStefano Zampini         if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
1360d698cf03SStefano Zampini           if (vx == numXVertices - 1) {
1361d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
1362d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1363d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1364d698cf03SStefano Zampini             if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1365d698cf03SStefano Zampini           } else if (vx == 0) {
1366d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
1367d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1368d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1369d698cf03SStefano Zampini             if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
1370d698cf03SStefano Zampini           }
1371d698cf03SStefano Zampini         }
1372d698cf03SStefano Zampini       }
1373d698cf03SStefano Zampini     }
1374d698cf03SStefano Zampini 
1375d698cf03SStefano Zampini     /* Build X edges*/
1376d698cf03SStefano Zampini     for (vy = 0; vy < numYVertices; vy++) {
1377d698cf03SStefano Zampini       for (ex = 0; ex < numXEdges; ex++) {
1378d698cf03SStefano Zampini         const PetscInt edge   = firstXEdge + vy * numXEdges + ex;
1379d698cf03SStefano Zampini         const PetscInt v0     = firstVertex + vy * numXVertices + ex;
1380d698cf03SStefano Zampini         const PetscInt v1     = firstVertex + vy * numXVertices + (ex + 1) % numXVertices;
1381d698cf03SStefano Zampini         const PetscInt cone[] = {v0, v1};
1382d698cf03SStefano Zampini 
1383d698cf03SStefano Zampini         PetscCall(DMPlexSetCone(dm, edge, cone));
1384d698cf03SStefano Zampini         if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
1385d698cf03SStefano Zampini           if (vy == numYVertices - 1) {
1386d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
1387d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1388d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1389d698cf03SStefano Zampini             if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1390d698cf03SStefano Zampini           } else if (vy == 0) {
1391d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
1392d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1393d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1394d698cf03SStefano Zampini             if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
1395d698cf03SStefano Zampini           }
1396d698cf03SStefano Zampini         }
1397d698cf03SStefano Zampini       }
1398d698cf03SStefano Zampini     }
1399d698cf03SStefano Zampini 
1400d698cf03SStefano Zampini     /* Compute support, stratify, and celltype label */
1401d698cf03SStefano Zampini     PetscCall(DMPlexSymmetrize(dm));
1402d698cf03SStefano Zampini     PetscCall(DMPlexStratify(dm));
1403d698cf03SStefano Zampini     PetscCall(DMPlexComputeCellTypes(dm));
1404d698cf03SStefano Zampini 
1405d698cf03SStefano Zampini     /* Build coordinates */
1406d698cf03SStefano Zampini     PetscCall(DMGetCoordinateSection(dm, &coordSection));
1407d698cf03SStefano Zampini     PetscCall(PetscSectionSetNumFields(coordSection, 1));
1408d698cf03SStefano Zampini     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2));
1409d698cf03SStefano Zampini     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
1410d698cf03SStefano Zampini     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
1411d698cf03SStefano Zampini       PetscCall(PetscSectionSetDof(coordSection, v, 2));
1412d698cf03SStefano Zampini       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2));
1413d698cf03SStefano Zampini     }
1414d698cf03SStefano Zampini     PetscCall(PetscSectionSetUp(coordSection));
1415d698cf03SStefano Zampini     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
1416d698cf03SStefano Zampini     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
1417d698cf03SStefano Zampini     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
1418d698cf03SStefano Zampini     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
1419d698cf03SStefano Zampini     PetscCall(VecSetBlockSize(coordinates, 2));
1420d698cf03SStefano Zampini     PetscCall(VecSetType(coordinates, VECSTANDARD));
1421d698cf03SStefano Zampini     PetscCall(VecGetArray(coordinates, &coords));
1422d698cf03SStefano Zampini     for (vy = 0; vy < numYVertices; ++vy) {
1423d698cf03SStefano Zampini       for (vx = 0; vx < numXVertices; ++vx) {
1424d698cf03SStefano Zampini         coords[2 * (vy * numXVertices + vx) + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
1425d698cf03SStefano Zampini         coords[2 * (vy * numXVertices + vx) + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
1426d698cf03SStefano Zampini       }
1427d698cf03SStefano Zampini     }
1428d698cf03SStefano Zampini     for (ey = 0; ey < numYEdges; ++ey) {
1429d698cf03SStefano Zampini       for (ex = 0; ex < numXEdges; ++ex) {
1430d698cf03SStefano Zampini         const PetscInt c = ey * numXEdges + ex + numYVertices * numXVertices;
1431d698cf03SStefano Zampini 
1432d698cf03SStefano Zampini         coords[2 * c + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * (ex + 0.5);
1433d698cf03SStefano Zampini         coords[2 * c + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * (ey + 0.5);
1434d698cf03SStefano Zampini       }
1435d698cf03SStefano Zampini     }
1436d698cf03SStefano Zampini     PetscCall(VecRestoreArray(coordinates, &coords));
1437d698cf03SStefano Zampini     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
1438d698cf03SStefano Zampini     PetscCall(VecDestroy(&coordinates));
1439d698cf03SStefano Zampini 
1440d698cf03SStefano Zampini     /* handle periodic BC */
1441d698cf03SStefano Zampini     if (bdX == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_PERIODIC) {
1442d698cf03SStefano Zampini       PetscReal L[2]       = {-1., -1.};
1443d698cf03SStefano Zampini       PetscReal maxCell[2] = {-1., -1.};
1444d698cf03SStefano Zampini 
1445d698cf03SStefano Zampini       for (PetscInt d = 0; d < 2; ++d) {
1446d698cf03SStefano Zampini         if (bd[d] != DM_BOUNDARY_NONE) {
1447d698cf03SStefano Zampini           L[d]       = upper[d] - lower[d];
1448d698cf03SStefano Zampini           maxCell[d] = 1.1 * (L[d] / PetscMax(1, edges[d]));
1449d698cf03SStefano Zampini         }
1450d698cf03SStefano Zampini       }
1451d698cf03SStefano Zampini       PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1452d698cf03SStefano Zampini     }
1453d698cf03SStefano Zampini   }
1454d698cf03SStefano Zampini   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
1455d698cf03SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
1456d698cf03SStefano Zampini }
1457d698cf03SStefano Zampini 
1458d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
1459d71ae5a4SJacob Faibussowitsch {
14609318fe57SMatthew G. Knepley   DM        boundary, vol;
1461c22d3578SMatthew G. Knepley   DMLabel   bdlabel;
1462d698cf03SStefano Zampini   PetscBool crisscross = PETSC_FALSE;
1463d6218766SMatthew G. Knepley 
1464d6218766SMatthew G. Knepley   PetscFunctionBegin;
14654f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
1466d698cf03SStefano Zampini   if (dim == 2) PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_box_crisscross", &crisscross, NULL));
1467d698cf03SStefano Zampini   if (crisscross) {
1468d698cf03SStefano Zampini     PetscCall(DMPlexCreateSquareMesh_Simplex_CrissCross(dm, faces, lower, upper, periodicity));
1469d698cf03SStefano Zampini   } else {
1470c22d3578SMatthew 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");
14719566063dSJacob Faibussowitsch     PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary));
14729566063dSJacob Faibussowitsch     PetscCall(DMSetType(boundary, DMPLEX));
1473d698cf03SStefano Zampini     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)boundary, ((PetscObject)dm)->prefix));
14749566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE));
14759566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol));
1476c22d3578SMatthew G. Knepley     PetscCall(DMGetLabel(vol, "marker", &bdlabel));
1477c22d3578SMatthew G. Knepley     if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel));
14785de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol));
147969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &vol));
1480d698cf03SStefano Zampini     PetscCall(DMDestroy(&boundary));
1481d698cf03SStefano Zampini   }
14824054ae39SJames Wright   if (interpolate) {
14834054ae39SJames Wright     PetscCall(DMPlexInterpolateInPlace_Internal(dm));
1484d7d2d1d2SJames Wright     PetscCall(DMPlexSetBoxLabel_Internal(dm, periodicity));
14854054ae39SJames Wright   }
14863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1487d6218766SMatthew G. Knepley }
1488d6218766SMatthew G. Knepley 
1489d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ)
1490d71ae5a4SJacob Faibussowitsch {
1491ed0e4b50SMatthew G. Knepley   DMLabel     cutLabel  = NULL;
1492f4eb4c5dSMatthew G. Knepley   PetscInt    markerTop = 1, faceMarkerTop = 1;
1493f4eb4c5dSMatthew G. Knepley   PetscInt    markerBottom = 1, faceMarkerBottom = 1;
1494f4eb4c5dSMatthew G. Knepley   PetscInt    markerFront = 1, faceMarkerFront = 1;
1495f4eb4c5dSMatthew G. Knepley   PetscInt    markerBack = 1, faceMarkerBack = 1;
1496f4eb4c5dSMatthew G. Knepley   PetscInt    markerRight = 1, faceMarkerRight = 1;
1497f4eb4c5dSMatthew G. Knepley   PetscInt    markerLeft = 1, faceMarkerLeft = 1;
14983dfda0b1SToby Isaac   PetscInt    dim;
1499d8211ee3SMatthew G. Knepley   PetscBool   markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE;
15003dfda0b1SToby Isaac   PetscMPIInt rank;
15013dfda0b1SToby Isaac 
15023dfda0b1SToby Isaac   PetscFunctionBegin;
15039566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
15049566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
15059566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
15069566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
15079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
15089371c9d4SSatish 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) {
15099371c9d4SSatish Balay     if (cutMarker) {
15109371c9d4SSatish Balay       PetscCall(DMCreateLabel(dm, "periodic_cut"));
15119371c9d4SSatish Balay       PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
15129371c9d4SSatish Balay     }
1513d8211ee3SMatthew G. Knepley   }
15143dfda0b1SToby Isaac   switch (dim) {
15153dfda0b1SToby Isaac   case 2:
1516f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 3;
1517f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
1518f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 2;
1519f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 4;
15203dfda0b1SToby Isaac     break;
15213dfda0b1SToby Isaac   case 3:
1522f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
1523f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 2;
1524f4eb4c5dSMatthew G. Knepley     faceMarkerFront  = 3;
1525f4eb4c5dSMatthew G. Knepley     faceMarkerBack   = 4;
1526f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 5;
1527f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 6;
15283dfda0b1SToby Isaac     break;
1529d71ae5a4SJacob Faibussowitsch   default:
1530d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
15313dfda0b1SToby Isaac   }
15329566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
1533f4eb4c5dSMatthew G. Knepley   if (markerSeparate) {
1534f4eb4c5dSMatthew G. Knepley     markerBottom = faceMarkerBottom;
1535f4eb4c5dSMatthew G. Knepley     markerTop    = faceMarkerTop;
1536f4eb4c5dSMatthew G. Knepley     markerFront  = faceMarkerFront;
1537f4eb4c5dSMatthew G. Knepley     markerBack   = faceMarkerBack;
1538f4eb4c5dSMatthew G. Knepley     markerRight  = faceMarkerRight;
1539f4eb4c5dSMatthew G. Knepley     markerLeft   = faceMarkerLeft;
15403dfda0b1SToby Isaac   }
15413dfda0b1SToby Isaac   {
1542dd400576SPatrick Sanan     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
1543dd400576SPatrick Sanan     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
1544dd400576SPatrick Sanan     const PetscInt numZEdges    = rank == 0 ? edges[2] : 0;
1545dd400576SPatrick Sanan     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0;
1546dd400576SPatrick Sanan     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0;
1547dd400576SPatrick Sanan     const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0;
15483dfda0b1SToby Isaac     const PetscInt numCells     = numXEdges * numYEdges * numZEdges;
15493dfda0b1SToby Isaac     const PetscInt numXFaces    = numYEdges * numZEdges;
15503dfda0b1SToby Isaac     const PetscInt numYFaces    = numXEdges * numZEdges;
15513dfda0b1SToby Isaac     const PetscInt numZFaces    = numXEdges * numYEdges;
15523dfda0b1SToby Isaac     const PetscInt numTotXFaces = numXVertices * numXFaces;
15533dfda0b1SToby Isaac     const PetscInt numTotYFaces = numYVertices * numYFaces;
15543dfda0b1SToby Isaac     const PetscInt numTotZFaces = numZVertices * numZFaces;
15553dfda0b1SToby Isaac     const PetscInt numFaces     = numTotXFaces + numTotYFaces + numTotZFaces;
15563dfda0b1SToby Isaac     const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices;
15573dfda0b1SToby Isaac     const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices;
15583dfda0b1SToby Isaac     const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices;
15593dfda0b1SToby Isaac     const PetscInt numVertices  = numXVertices * numYVertices * numZVertices;
15603dfda0b1SToby Isaac     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numTotZEdges;
15613dfda0b1SToby Isaac     const PetscInt firstVertex  = (dim == 2) ? numFaces : numCells;
15623dfda0b1SToby Isaac     const PetscInt firstXFace   = (dim == 2) ? 0 : numCells + numVertices;
15633dfda0b1SToby Isaac     const PetscInt firstYFace   = firstXFace + numTotXFaces;
15643dfda0b1SToby Isaac     const PetscInt firstZFace   = firstYFace + numTotYFaces;
15653dfda0b1SToby Isaac     const PetscInt firstXEdge   = numCells + numFaces + numVertices;
15663dfda0b1SToby Isaac     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
15673dfda0b1SToby Isaac     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
15683dfda0b1SToby Isaac     Vec            coordinates;
15693dfda0b1SToby Isaac     PetscSection   coordSection;
15703dfda0b1SToby Isaac     PetscScalar   *coords;
15713dfda0b1SToby Isaac     PetscInt       coordSize;
15723dfda0b1SToby Isaac     PetscInt       v, vx, vy, vz;
15733dfda0b1SToby Isaac     PetscInt       c, f, fx, fy, fz, e, ex, ey, ez;
15743dfda0b1SToby Isaac 
15759566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices));
157648a46eb9SPierre Jolivet     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
157748a46eb9SPierre Jolivet     for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
157848a46eb9SPierre Jolivet     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
15799566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
15803dfda0b1SToby Isaac     /* Build cells */
15813dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
15823dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
15833dfda0b1SToby Isaac         for (fx = 0; fx < numXEdges; ++fx) {
15843dfda0b1SToby Isaac           PetscInt cell  = (fz * numYEdges + fy) * numXEdges + fx;
15853dfda0b1SToby Isaac           PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
15863dfda0b1SToby Isaac           PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices);
15873dfda0b1SToby Isaac           PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
15883dfda0b1SToby Isaac           PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices);
15893dfda0b1SToby Isaac           PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
15903dfda0b1SToby Isaac           PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices);
15913dfda0b1SToby Isaac           /* B,  T,  F,  K,  R,  L */
1592b5a892a1SMatthew G. Knepley           PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */
159342206facSLisandro Dalcin           PetscInt cone[6];
15943dfda0b1SToby Isaac 
15953dfda0b1SToby Isaac           /* no boundary twisting in 3D */
15969371c9d4SSatish Balay           cone[0] = faceB;
15979371c9d4SSatish Balay           cone[1] = faceT;
15989371c9d4SSatish Balay           cone[2] = faceF;
15999371c9d4SSatish Balay           cone[3] = faceK;
16009371c9d4SSatish Balay           cone[4] = faceR;
16019371c9d4SSatish Balay           cone[5] = faceL;
16029566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, cell, cone));
16039566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, cell, ornt));
16049566063dSJacob Faibussowitsch           if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
16059566063dSJacob Faibussowitsch           if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
16069566063dSJacob Faibussowitsch           if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
16073dfda0b1SToby Isaac         }
16083dfda0b1SToby Isaac       }
16093dfda0b1SToby Isaac     }
16103dfda0b1SToby Isaac     /* Build x faces */
16113dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
16123dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
16133dfda0b1SToby Isaac         for (fx = 0; fx < numXVertices; ++fx) {
16143dfda0b1SToby Isaac           PetscInt face    = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
16153dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
16163dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz;
16173dfda0b1SToby Isaac           PetscInt edgeB   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
16183dfda0b1SToby Isaac           PetscInt edgeT   = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy;
1619b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
16203dfda0b1SToby Isaac           PetscInt cone[4];
16213dfda0b1SToby Isaac 
16223dfda0b1SToby Isaac           if (dim == 3) {
16233dfda0b1SToby Isaac             /* markers */
16243dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
16253dfda0b1SToby Isaac               if (fx == numXVertices - 1) {
16269566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight));
16279566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerRight));
16289371c9d4SSatish Balay               } else if (fx == 0) {
16299566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft));
16309566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft));
16313dfda0b1SToby Isaac               }
16323dfda0b1SToby Isaac             }
16333dfda0b1SToby Isaac           }
16349371c9d4SSatish Balay           cone[0] = edgeB;
16359371c9d4SSatish Balay           cone[1] = edgeR;
16369371c9d4SSatish Balay           cone[2] = edgeT;
16379371c9d4SSatish Balay           cone[3] = edgeL;
16389566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
16399566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
16403dfda0b1SToby Isaac         }
16413dfda0b1SToby Isaac       }
16423dfda0b1SToby Isaac     }
16433dfda0b1SToby Isaac     /* Build y faces */
16443dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
164542206facSLisandro Dalcin       for (fx = 0; fx < numXEdges; ++fx) {
16463dfda0b1SToby Isaac         for (fy = 0; fy < numYVertices; ++fy) {
16473dfda0b1SToby Isaac           PetscInt face    = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
16483dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
16493dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz;
16503dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
16513dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx;
1652b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
16533dfda0b1SToby Isaac           PetscInt cone[4];
16543dfda0b1SToby Isaac 
16553dfda0b1SToby Isaac           if (dim == 3) {
16563dfda0b1SToby Isaac             /* markers */
16573dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
16583dfda0b1SToby Isaac               if (fy == numYVertices - 1) {
16599566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack));
16609566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBack));
16619371c9d4SSatish Balay               } else if (fy == 0) {
16629566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront));
16639566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerFront));
16643dfda0b1SToby Isaac               }
16653dfda0b1SToby Isaac             }
16663dfda0b1SToby Isaac           }
16679371c9d4SSatish Balay           cone[0] = edgeB;
16689371c9d4SSatish Balay           cone[1] = edgeR;
16699371c9d4SSatish Balay           cone[2] = edgeT;
16709371c9d4SSatish Balay           cone[3] = edgeL;
16719566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
16729566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
16733dfda0b1SToby Isaac         }
16743dfda0b1SToby Isaac       }
16753dfda0b1SToby Isaac     }
16763dfda0b1SToby Isaac     /* Build z faces */
16773dfda0b1SToby Isaac     for (fy = 0; fy < numYEdges; ++fy) {
16783dfda0b1SToby Isaac       for (fx = 0; fx < numXEdges; ++fx) {
16793dfda0b1SToby Isaac         for (fz = 0; fz < numZVertices; fz++) {
16803dfda0b1SToby Isaac           PetscInt face    = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
16813dfda0b1SToby Isaac           PetscInt edgeL   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
16823dfda0b1SToby Isaac           PetscInt edgeR   = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy;
16833dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
16843dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx;
1685b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
16863dfda0b1SToby Isaac           PetscInt cone[4];
16873dfda0b1SToby Isaac 
16883dfda0b1SToby Isaac           if (dim == 2) {
16899371c9d4SSatish Balay             if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) {
16909371c9d4SSatish Balay               edgeR += numYEdges - 1 - 2 * fy;
16919371c9d4SSatish Balay               ornt[1] = -1;
16929371c9d4SSatish Balay             }
16939371c9d4SSatish Balay             if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) {
16949371c9d4SSatish Balay               edgeT += numXEdges - 1 - 2 * fx;
16959371c9d4SSatish Balay               ornt[2] = 0;
16969371c9d4SSatish Balay             }
16979566063dSJacob Faibussowitsch             if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
16989566063dSJacob Faibussowitsch             if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
1699d1c88043SMatthew G. Knepley           } else {
17003dfda0b1SToby Isaac             /* markers */
17013dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
17023dfda0b1SToby Isaac               if (fz == numZVertices - 1) {
17039566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop));
17049566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerTop));
17059371c9d4SSatish Balay               } else if (fz == 0) {
17069566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom));
17079566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom));
17083dfda0b1SToby Isaac               }
17093dfda0b1SToby Isaac             }
17103dfda0b1SToby Isaac           }
17119371c9d4SSatish Balay           cone[0] = edgeB;
17129371c9d4SSatish Balay           cone[1] = edgeR;
17139371c9d4SSatish Balay           cone[2] = edgeT;
17149371c9d4SSatish Balay           cone[3] = edgeL;
17159566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
17169566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
17173dfda0b1SToby Isaac         }
17183dfda0b1SToby Isaac       }
17193dfda0b1SToby Isaac     }
17203dfda0b1SToby Isaac     /* Build Z edges*/
17213dfda0b1SToby Isaac     for (vy = 0; vy < numYVertices; vy++) {
17223dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
17233dfda0b1SToby Isaac         for (ez = 0; ez < numZEdges; ez++) {
17243dfda0b1SToby Isaac           const PetscInt edge    = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez;
17253dfda0b1SToby Isaac           const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx;
17263dfda0b1SToby Isaac           const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx;
17273dfda0b1SToby Isaac           PetscInt       cone[2];
17283dfda0b1SToby Isaac 
17299371c9d4SSatish Balay           cone[0] = vertexB;
17309371c9d4SSatish Balay           cone[1] = vertexT;
1731c2df9bbfSMatthew G. Knepley           PetscCall(DMPlexSetCone(dm, edge, cone));
17323dfda0b1SToby Isaac           if (dim == 3) {
17333dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
17343dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
17359566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1736c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1737c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1738c2df9bbfSMatthew G. Knepley               } else if (vx == 0) {
17399566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1740c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1741c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
17423dfda0b1SToby Isaac               }
17433dfda0b1SToby Isaac             }
17443dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
17453dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
17469566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1747c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1748c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1749c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
17509566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1751c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1752c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
17533dfda0b1SToby Isaac               }
17543dfda0b1SToby Isaac             }
17553dfda0b1SToby Isaac           }
17563dfda0b1SToby Isaac         }
17573dfda0b1SToby Isaac       }
17583dfda0b1SToby Isaac     }
17593dfda0b1SToby Isaac     /* Build Y edges*/
17603dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
17613dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
17623dfda0b1SToby Isaac         for (ey = 0; ey < numYEdges; ey++) {
17633dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx;
17643dfda0b1SToby Isaac           const PetscInt edge    = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey;
17653dfda0b1SToby Isaac           const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx;
17663dfda0b1SToby Isaac           const PetscInt vertexK = firstVertex + nextv;
17673dfda0b1SToby Isaac           PetscInt       cone[2];
17683dfda0b1SToby Isaac 
17699371c9d4SSatish Balay           cone[0] = vertexF;
17709371c9d4SSatish Balay           cone[1] = vertexK;
17719566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
17723dfda0b1SToby Isaac           if (dim == 2) {
17733dfda0b1SToby Isaac             if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
17743dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
17759566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
17769566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
17779566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1778c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1779d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
17809566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
17819566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
17829566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1783c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
17843dfda0b1SToby Isaac               }
1785d8211ee3SMatthew G. Knepley             } else {
17864c67ea77SStefano Zampini               if (vx == 0 && cutLabel) {
17879566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
17889566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1789c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
17903dfda0b1SToby Isaac               }
1791d8211ee3SMatthew G. Knepley             }
1792d8211ee3SMatthew G. Knepley           } else {
17933dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
17943dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
17959566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1796c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1797c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1798d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
17999566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1800c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1801c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
18023dfda0b1SToby Isaac               }
18033dfda0b1SToby Isaac             }
18043dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
18053dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
18069566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1807c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1808c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1809d8211ee3SMatthew G. Knepley               } else if (vz == 0) {
18109566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1811c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1812c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
18133dfda0b1SToby Isaac               }
18143dfda0b1SToby Isaac             }
18153dfda0b1SToby Isaac           }
18163dfda0b1SToby Isaac         }
18173dfda0b1SToby Isaac       }
18183dfda0b1SToby Isaac     }
18193dfda0b1SToby Isaac     /* Build X edges*/
18203dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
18213dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; vy++) {
18223dfda0b1SToby Isaac         for (ex = 0; ex < numXEdges; ex++) {
18233dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices;
18243dfda0b1SToby Isaac           const PetscInt edge    = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex;
18253dfda0b1SToby Isaac           const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex;
18263dfda0b1SToby Isaac           const PetscInt vertexR = firstVertex + nextv;
18273dfda0b1SToby Isaac           PetscInt       cone[2];
18283dfda0b1SToby Isaac 
18299371c9d4SSatish Balay           cone[0] = vertexL;
18309371c9d4SSatish Balay           cone[1] = vertexR;
18319566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
18323dfda0b1SToby Isaac           if (dim == 2) {
18333dfda0b1SToby Isaac             if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
18343dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
18359566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
18369566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
18379566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1838c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1839d8211ee3SMatthew G. Knepley               } else if (vy == 0) {
18409566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
18419566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
18429566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1843c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
18443dfda0b1SToby Isaac               }
1845d8211ee3SMatthew G. Knepley             } else {
18464c67ea77SStefano Zampini               if (vy == 0 && cutLabel) {
18479566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
18489566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1849c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
18503dfda0b1SToby Isaac               }
1851d8211ee3SMatthew G. Knepley             }
1852d8211ee3SMatthew G. Knepley           } else {
18533dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
18543dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
18559566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1856c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1857c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1858c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
18599566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1860c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1861c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
18623dfda0b1SToby Isaac               }
18633dfda0b1SToby Isaac             }
18643dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
18653dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
18669566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1867c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1868c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1869c2df9bbfSMatthew G. Knepley               } else if (vz == 0) {
18709566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1871c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1872c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
18733dfda0b1SToby Isaac               }
18743dfda0b1SToby Isaac             }
18753dfda0b1SToby Isaac           }
18763dfda0b1SToby Isaac         }
18773dfda0b1SToby Isaac       }
18783dfda0b1SToby Isaac     }
18799566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
18809566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
18813dfda0b1SToby Isaac     /* Build coordinates */
18829566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
18839566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
18849566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
18859566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
18863dfda0b1SToby Isaac     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
18879566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
18889566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
18893dfda0b1SToby Isaac     }
18909566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
18919566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
18929566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
18939566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
18949566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
18959566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
18969566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
18979566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
18983dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; ++vz) {
18993dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; ++vy) {
19003dfda0b1SToby Isaac         for (vx = 0; vx < numXVertices; ++vx) {
19013dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
19023dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
1903ad540459SPierre Jolivet           if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz;
19043dfda0b1SToby Isaac         }
19053dfda0b1SToby Isaac       }
19063dfda0b1SToby Isaac     }
19079566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
19089566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
19099566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
19103dfda0b1SToby Isaac   }
19113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19123dfda0b1SToby Isaac }
19133dfda0b1SToby Isaac 
1914d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1915d71ae5a4SJacob Faibussowitsch {
19169318fe57SMatthew G. Knepley   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
19179318fe57SMatthew G. Knepley   PetscInt       fac[3] = {0, 0, 0}, d;
1918552f7358SJed Brown 
1919552f7358SJed Brown   PetscFunctionBegin;
19204f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
19219318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
19229566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
19239371c9d4SSatish Balay   for (d = 0; d < dim; ++d) {
19249371c9d4SSatish Balay     fac[d] = faces[d];
19259371c9d4SSatish Balay     bdt[d] = periodicity[d];
19269371c9d4SSatish Balay   }
19279566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2]));
19289371c9d4SSatish 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))) {
19296858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
19306858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1931552f7358SJed Brown 
19329318fe57SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
19336858538eSMatthew G. Knepley       if (periodicity[d] != DM_BOUNDARY_NONE) {
19349318fe57SMatthew G. Knepley         L[d]       = upper[d] - lower[d];
19359318fe57SMatthew G. Knepley         maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d]));
1936768d5fceSMatthew G. Knepley       }
19376858538eSMatthew G. Knepley     }
19384fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1939768d5fceSMatthew G. Knepley   }
19409566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
19413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19429318fe57SMatthew G. Knepley }
19439318fe57SMatthew G. Knepley 
19445dca41c3SJed 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)
1945d71ae5a4SJacob Faibussowitsch {
19469318fe57SMatthew G. Knepley   PetscFunctionBegin;
194746139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
19485dca41c3SJed Brown   if (shape == DM_SHAPE_ZBOX) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
19496725e60dSJed Brown   else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0]));
19509566063dSJacob Faibussowitsch   else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
19519566063dSJacob Faibussowitsch   else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity));
19529318fe57SMatthew G. Knepley   if (!interpolate && dim > 1 && !simplex) {
1953768d5fceSMatthew G. Knepley     DM udm;
1954768d5fceSMatthew G. Knepley 
19559566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(dm, &udm));
19569566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, udm));
195769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &udm));
1958768d5fceSMatthew G. Knepley   }
195946139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
19603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1961c8c68bd8SToby Isaac }
1962c8c68bd8SToby Isaac 
19635d83a8b1SBarry Smith /*@
1964768d5fceSMatthew G. Knepley   DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra).
1965768d5fceSMatthew G. Knepley 
1966d083f849SBarry Smith   Collective
1967768d5fceSMatthew G. Knepley 
1968768d5fceSMatthew G. Knepley   Input Parameters:
1969a1cb98faSBarry Smith + comm               - The communicator for the `DM` object
1970768d5fceSMatthew G. Knepley . dim                - The spatial dimension
1971a1cb98faSBarry Smith . simplex            - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells
197220f4b53cSBarry Smith . faces              - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
197320f4b53cSBarry Smith . lower              - The lower left corner, or `NULL` for (0, 0, 0)
197420f4b53cSBarry Smith . upper              - The upper right corner, or `NULL` for (1, 1, 1)
197520f4b53cSBarry Smith . periodicity        - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE`
197642108689Sksagiyam . interpolate        - Flag to create intermediate mesh pieces (edges, faces)
197742108689Sksagiyam . localizationHeight - Flag to localize edges and faces in addition to cells; only significant for periodic meshes
197842108689Sksagiyam - sparseLocalize     - Flag to localize coordinates only for cells near the periodic boundary; only significant for periodic meshes
1979768d5fceSMatthew G. Knepley 
1980768d5fceSMatthew G. Knepley   Output Parameter:
1981a1cb98faSBarry Smith . dm - The `DM` object
1982768d5fceSMatthew G. Knepley 
1983768d5fceSMatthew G. Knepley   Level: beginner
1984768d5fceSMatthew G. Knepley 
1985a1cb98faSBarry Smith   Note:
1986a1cb98faSBarry Smith   To customize this mesh using options, use
1987a1cb98faSBarry Smith .vb
1988a1cb98faSBarry Smith   DMCreate(comm, &dm);
1989a1cb98faSBarry Smith   DMSetType(dm, DMPLEX);
1990a1cb98faSBarry Smith   DMSetFromOptions(dm);
1991a1cb98faSBarry Smith .ve
1992a1cb98faSBarry Smith   and use the options in `DMSetFromOptions()`.
1993a1cb98faSBarry Smith 
1994a4e35b19SJacob Faibussowitsch   Here is the numbering returned for 2 faces in each direction for tensor cells\:
1995a1cb98faSBarry Smith .vb
1996a1cb98faSBarry Smith  10---17---11---18----12
1997a1cb98faSBarry Smith   |         |         |
1998a1cb98faSBarry Smith   |         |         |
1999a1cb98faSBarry Smith  20    2   22    3    24
2000a1cb98faSBarry Smith   |         |         |
2001a1cb98faSBarry Smith   |         |         |
2002a1cb98faSBarry Smith   7---15----8---16----9
2003a1cb98faSBarry Smith   |         |         |
2004a1cb98faSBarry Smith   |         |         |
2005a1cb98faSBarry Smith  19    0   21    1   23
2006a1cb98faSBarry Smith   |         |         |
2007a1cb98faSBarry Smith   |         |         |
2008a1cb98faSBarry Smith   4---13----5---14----6
2009a1cb98faSBarry Smith .ve
2010a1cb98faSBarry Smith   and for simplicial cells
2011a1cb98faSBarry Smith .vb
2012a1cb98faSBarry Smith  14----8---15----9----16
2013a1cb98faSBarry Smith   |\     5  |\      7 |
2014a1cb98faSBarry Smith   | \       | \       |
2015a1cb98faSBarry Smith  13   2    14    3    15
2016a1cb98faSBarry Smith   | 4   \   | 6   \   |
2017a1cb98faSBarry Smith   |       \ |       \ |
2018a1cb98faSBarry Smith  11----6---12----7----13
2019a1cb98faSBarry Smith   |\        |\        |
2020a1cb98faSBarry Smith   | \    1  | \     3 |
2021a1cb98faSBarry Smith  10   0    11    1    12
2022a1cb98faSBarry Smith   | 0   \   | 2   \   |
2023a1cb98faSBarry Smith   |       \ |       \ |
2024a1cb98faSBarry Smith   8----4----9----5----10
2025a1cb98faSBarry Smith .ve
2026a1cb98faSBarry Smith 
20271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
2028768d5fceSMatthew G. Knepley @*/
202942108689Sksagiyam 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)
2030d71ae5a4SJacob Faibussowitsch {
20319318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
2032fdbf62faSLisandro Dalcin   PetscReal      low[3] = {0, 0, 0};
2033fdbf62faSLisandro Dalcin   PetscReal      upp[3] = {1, 1, 1};
2034fdbf62faSLisandro Dalcin   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
2035552f7358SJed Brown 
2036768d5fceSMatthew G. Knepley   PetscFunctionBegin;
20379566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
20389566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
20395dca41c3SJed Brown   PetscCall(DMPlexCreateBoxMesh_Internal(*dm, DM_SHAPE_BOX, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate));
204042108689Sksagiyam   if (periodicity) {
204142108689Sksagiyam     DM cdm;
204242108689Sksagiyam 
204342108689Sksagiyam     PetscCall(DMGetCoordinateDM(*dm, &cdm));
204442108689Sksagiyam     PetscCall(DMPlexSetMaxProjectionHeight(cdm, localizationHeight));
204542108689Sksagiyam     PetscCall(DMSetSparseLocalize(*dm, sparseLocalize));
204642108689Sksagiyam     PetscCall(DMLocalizeCoordinates(*dm));
204742108689Sksagiyam   }
20483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20499318fe57SMatthew G. Knepley }
2050fdbf62faSLisandro Dalcin 
2051d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
2052d71ae5a4SJacob Faibussowitsch {
20539318fe57SMatthew G. Knepley   DM       bdm, vol;
20549318fe57SMatthew G. Knepley   PetscInt i;
20559318fe57SMatthew G. Knepley 
20569318fe57SMatthew G. Knepley   PetscFunctionBegin;
20571fcf445aSMatthew G. Knepley   // TODO Now we can support periodicity
205808401ef6SPierre Jolivet   for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported");
20599566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm));
20609566063dSJacob Faibussowitsch   PetscCall(DMSetType(bdm, DMPLEX));
20619566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(bdm, 2));
206246139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, bdm, 0, 0, 0));
20639566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE));
20641fcf445aSMatthew G. Knepley   PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, NULL, NULL, &vol));
206546139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, bdm, 0, 0, 0));
20669566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&bdm));
206769d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
20689318fe57SMatthew G. Knepley   if (lower[2] != 0.0) {
20699318fe57SMatthew G. Knepley     Vec          v;
20709318fe57SMatthew G. Knepley     PetscScalar *x;
20719318fe57SMatthew G. Knepley     PetscInt     cDim, n;
20729318fe57SMatthew G. Knepley 
20739566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &v));
20749566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(v, &cDim));
20759566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(v, &n));
20769566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v, &x));
20779318fe57SMatthew G. Knepley     x += cDim;
20789318fe57SMatthew G. Knepley     for (i = 0; i < n; i += cDim) x[i] += lower[2];
20799566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v, &x));
20809566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, v));
20819318fe57SMatthew G. Knepley   }
20823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2083552f7358SJed Brown }
2084552f7358SJed Brown 
208500dabe28SStefano Zampini /*@
208639f4f5dbSPierre Jolivet   DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tessellating the (x,y) plane and extruding in the third direction using wedge cells.
208700dabe28SStefano Zampini 
2088d083f849SBarry Smith   Collective
208900dabe28SStefano Zampini 
209000dabe28SStefano Zampini   Input Parameters:
2091a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
209220f4b53cSBarry Smith . faces       - Number of faces per dimension, or `NULL` for (1, 1, 1)
209320f4b53cSBarry Smith . lower       - The lower left corner, or `NULL` for (0, 0, 0)
209420f4b53cSBarry Smith . upper       - The upper right corner, or `NULL` for (1, 1, 1)
209520f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE`
2096a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first
209700dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces)
209800dabe28SStefano Zampini 
209900dabe28SStefano Zampini   Output Parameter:
2100a1cb98faSBarry Smith . dm - The `DM` object
210100dabe28SStefano Zampini 
210200dabe28SStefano Zampini   Level: beginner
210300dabe28SStefano Zampini 
21041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
210500dabe28SStefano Zampini @*/
2106d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm)
2107d71ae5a4SJacob Faibussowitsch {
21089318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
210900dabe28SStefano Zampini   PetscReal      low[3] = {0, 0, 0};
211000dabe28SStefano Zampini   PetscReal      upp[3] = {1, 1, 1};
211100dabe28SStefano Zampini   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
211200dabe28SStefano Zampini 
211300dabe28SStefano Zampini   PetscFunctionBegin;
21149566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
21159566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
21169566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt));
2117d410b0cfSMatthew G. Knepley   if (!interpolate) {
2118d410b0cfSMatthew G. Knepley     DM udm;
211900dabe28SStefano Zampini 
21209566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(*dm, &udm));
212169d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(*dm, &udm));
212200dabe28SStefano Zampini   }
21237ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
21243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
212500dabe28SStefano Zampini }
212600dabe28SStefano Zampini 
2127cfb853baSMatthew G. Knepley /*
2128cfb853baSMatthew 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.
2129cfb853baSMatthew G. Knepley 
2130cfb853baSMatthew G. Knepley   Input Parameters:
2131cfb853baSMatthew G. Knepley + len - The length of the tuple
2132cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max)
2133cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition
2134cfb853baSMatthew G. Knepley 
2135cfb853baSMatthew G. Knepley   Output Parameter:
213620f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max`
2137cfb853baSMatthew G. Knepley 
2138cfb853baSMatthew G. Knepley   Level: developer
2139cfb853baSMatthew G. Knepley 
214020f4b53cSBarry Smith   Note:
214120f4b53cSBarry Smith   Ordering is lexicographic with lowest index as least significant in ordering.
214220f4b53cSBarry 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}.
214320f4b53cSBarry Smith 
2144cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal()
2145cfb853baSMatthew G. Knepley */
2146cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[])
2147cfb853baSMatthew G. Knepley {
2148cfb853baSMatthew G. Knepley   PetscInt i;
2149cfb853baSMatthew G. Knepley 
2150cfb853baSMatthew G. Knepley   PetscFunctionBegin;
2151cfb853baSMatthew G. Knepley   for (i = 0; i < len; ++i) {
2152cfb853baSMatthew G. Knepley     if (tup[i] < max[i] - 1) {
2153cfb853baSMatthew G. Knepley       break;
2154cfb853baSMatthew G. Knepley     } else {
2155cfb853baSMatthew G. Knepley       tup[i] = 0;
2156cfb853baSMatthew G. Knepley     }
2157cfb853baSMatthew G. Knepley   }
2158cfb853baSMatthew G. Knepley   if (i == len) tup[i - 1] = max[i - 1];
2159cfb853baSMatthew G. Knepley   else ++tup[i];
21603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2161cfb853baSMatthew G. Knepley }
2162cfb853baSMatthew G. Knepley 
2163cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[])
2164cfb853baSMatthew G. Knepley {
21658d2ec52aSSatish Balay   PetscInt idx = tup[len - 1];
2166cfb853baSMatthew G. Knepley 
21678d2ec52aSSatish Balay   for (PetscInt i = len - 2; i >= 0; --i) {
2168cfb853baSMatthew G. Knepley     idx *= max[i];
2169cfb853baSMatthew G. Knepley     idx += tup[i];
2170cfb853baSMatthew G. Knepley   }
2171cfb853baSMatthew G. Knepley   return idx;
2172cfb853baSMatthew G. Knepley }
2173cfb853baSMatthew G. Knepley 
21748d2ec52aSSatish Balay static void IndexToTuple_Private(PetscInt len, const PetscInt max[], PetscInt idx, PetscInt tup[])
2175cfb853baSMatthew G. Knepley {
21768d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
21778d2ec52aSSatish Balay     tup[i] = idx % max[i];
21788d2ec52aSSatish Balay     idx    = (idx - tup[i]) / max[i];
21798d2ec52aSSatish Balay   }
21808d2ec52aSSatish Balay }
21818d2ec52aSSatish Balay 
21828d2ec52aSSatish Balay static void TupleToRanks_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt tup[], PetscInt ranks[])
21838d2ec52aSSatish Balay {
21848d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
21858d2ec52aSSatish Balay     const PetscInt div = max[i] / procs[i];
21868d2ec52aSSatish Balay     const PetscInt rem = max[i] % procs[i];
21878d2ec52aSSatish Balay     const PetscInt idx = (tup[i] < 0 ? max[i] + tup[i] : tup[i]) % max[i];
21888d2ec52aSSatish Balay 
21898d2ec52aSSatish Balay     if (idx < rem * (div + 1)) ranks[i] = idx / (div + 1);
21908d2ec52aSSatish Balay     else ranks[i] = rem + (idx - rem * (div + 1)) / div;
21918d2ec52aSSatish Balay   }
21928d2ec52aSSatish Balay }
21938d2ec52aSSatish Balay 
21948d2ec52aSSatish Balay static void RanksToSizes_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt ranks[], PetscInt sizes[])
21958d2ec52aSSatish Balay {
21968d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
21978d2ec52aSSatish Balay     const PetscInt div = max[i] / procs[i];
21988d2ec52aSSatish Balay     const PetscInt rem = max[i] % procs[i];
21998d2ec52aSSatish Balay 
22008d2ec52aSSatish Balay     sizes[i] = ranks[i] < rem ? div + 1 : div;
22018d2ec52aSSatish Balay   }
22028d2ec52aSSatish Balay }
22038d2ec52aSSatish Balay 
22048d2ec52aSSatish Balay /*
22058d2ec52aSSatish Balay   In serial, the mesh is completely periodic. In parallel, we will include a layer of ghost vertices around the patch, so our edges will not wrap around in parallel. This will instead be handled by the SF.
22068d2ec52aSSatish Balay 
22078d2ec52aSSatish Balay   The cone for all edges will always be complete. Even in the presence of boundaries, we will keep all support sizes constant. When an edge would not exist in the support, we will create one to wrap back periodically. This allows for uniform stencils, and that edge will not be used for computation.
22088d2ec52aSSatish Balay 
22098d2ec52aSSatish Balay   All point which do not attain the vertex lower or upper bound in any dimension are owned, the rest are leaves owned by another process and present in the SF.
2210dfe9cfe5SMatthew Knepley 
2211dfe9cfe5SMatthew Knepley   Parallel Layout:
2212dfe9cfe5SMatthew Knepley 
2213dfe9cfe5SMatthew Knepley   We create a cubic process grid of dimension P^{1/d} on each side. The IndexToTuple_Private() function maps the global rank to the local rank in each dimension. We divide edges using the PETSc distribution rule in each dimension, and then add overlap. TupleToRanks_Private() returns the local rank in ech dimension for a tuple. RanksToSizes_Private() gives the size in each dimension for the domain with those local ranks.
22148d2ec52aSSatish Balay */
22158d2ec52aSSatish Balay static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], PetscInt overlap, const DMBoundaryType bd[])
22168d2ec52aSSatish Balay {
22178d2ec52aSSatish Balay   const PetscInt debug = ((DM_Plex *)dm->data)->printAdj;
22188d2ec52aSSatish Balay   PetscSF        sf;
2219cfb853baSMatthew G. Knepley   Vec            coordinates;
2220cfb853baSMatthew G. Knepley   PetscSection   coordSection;
2221cfb853baSMatthew G. Knepley   DMLabel        cutLabel    = NULL;
2222cfb853baSMatthew G. Knepley   PetscBool      cutMarker   = PETSC_FALSE;
2223cfb853baSMatthew G. Knepley   PetscBool      periodic    = PETSC_FALSE;
22248d2ec52aSSatish Balay   PetscInt       numCells    = 1;
22258d2ec52aSSatish Balay   PetscInt       numVertices = 1;
22268d2ec52aSSatish Balay   PetscSFNode   *remotes;
2227cfb853baSMatthew G. Knepley   PetscScalar   *coords;
22288d2ec52aSSatish Balay   PetscInt      *procs;     // The number of processes along each dimension
22298d2ec52aSSatish Balay   PetscInt      *lrank;     // Rank in each dimension, lrank[d] \in [0, procs[d])
22308d2ec52aSSatish Balay   PetscInt      *ledges;    // The number of edges along each dimension for this process
22318d2ec52aSSatish Balay   PetscInt      *vstart;    // The first vertex along each dimension on this processes
22328d2ec52aSSatish Balay   PetscInt      *vertices;  // The number of vertices along each dimension on this process
22338d2ec52aSSatish Balay   PetscInt      *rvert;     // The global (not local) vertex number along each dimension
22348d2ec52aSSatish Balay   PetscInt      *rrank;     // The rank along each dimension for the process owning rvert[]
22358d2ec52aSSatish Balay   PetscInt      *rvertices; // The number of vertices along each dimension for the process rrank[]
22368d2ec52aSSatish Balay   PetscInt      *vert, *vtmp, *supp, cone[2], *leaves;
22378d2ec52aSSatish Balay   PetscInt       cell = 0, coordSize, Nl = 0, Nl2 = 0;
22388d2ec52aSSatish Balay   PetscMPIInt    rank, size;
22398d2ec52aSSatish Balay   MPI_Comm       comm;
2240cfb853baSMatthew G. Knepley 
2241cfb853baSMatthew G. Knepley   PetscFunctionBegin;
22428d2ec52aSSatish Balay   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
22438d2ec52aSSatish Balay   PetscCallMPI(MPI_Comm_rank(comm, &rank));
22448d2ec52aSSatish Balay   PetscCallMPI(MPI_Comm_size(comm, &size));
2245cfb853baSMatthew G. Knepley   PetscCall(DMSetDimension(dm, dim));
22468d2ec52aSSatish Balay   PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
22478d2ec52aSSatish Balay   PetscCall(PetscCalloc4(dim, &procs, dim, &lrank, dim, &rrank, 2 * dim, &supp));
22488d2ec52aSSatish Balay   PetscCall(PetscCalloc7(dim, &ledges, dim, &vertices, dim, &rvertices, dim, &vert, dim, &rvert, dim, &vstart, dim, &vtmp));
2249cfb853baSMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "marker"));
2250cfb853baSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
22518d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE;
2252cfb853baSMatthew G. Knepley   if (periodic && cutMarker) {
2253cfb853baSMatthew G. Knepley     PetscCall(DMCreateLabel(dm, "periodic_cut"));
2254cfb853baSMatthew G. Knepley     PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
2255cfb853baSMatthew G. Knepley   }
22568d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, comm, PETSC_ERR_SUP, "Hypercubic mesh must be periodic now");
22578d2ec52aSSatish Balay   overlap = overlap == PETSC_DETERMINE ? 1 : overlap;
22588d2ec52aSSatish Balay   PetscCheck(overlap >= 1, comm, PETSC_ERR_SUP, "Overlap %" PetscInt_FMT " must be greater than 0", overlap);
22598d2ec52aSSatish Balay   if (size > 1) {
22608d2ec52aSSatish Balay     PetscInt Npr = 1;
22618d2ec52aSSatish Balay 
22628d2ec52aSSatish Balay     // Make process grid
22638d2ec52aSSatish Balay     if (debug) PetscCall(PetscPrintf(comm, "Process grid:"));
22648d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
22658d2ec52aSSatish Balay       procs[d] = PetscRintReal(PetscPowReal(size, 1. / dim));
22668d2ec52aSSatish Balay       Npr *= procs[d];
22678d2ec52aSSatish Balay       if (debug) PetscCall(PetscPrintf(comm, " %" PetscInt_FMT, procs[d]));
22688d2ec52aSSatish Balay     }
22698d2ec52aSSatish Balay     if (debug) PetscCall(PetscPrintf(comm, "\n"));
22708d2ec52aSSatish Balay     PetscCheck(Npr == size, comm, PETSC_ERR_PLIB, "Process grid size %" PetscInt_FMT " != %d comm size", Npr, size);
22718d2ec52aSSatish Balay     IndexToTuple_Private(dim, procs, rank, lrank);
22728d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
22738d2ec52aSSatish Balay       ledges[d] = edges[d] / procs[d] + (edges[d] % procs[d] > lrank[d] ? 1 : 0);
22748d2ec52aSSatish Balay       vstart[d] = 0;
22758d2ec52aSSatish Balay       for (PetscInt r = 0; r < lrank[d]; ++r) vstart[d] += edges[d] / procs[d] + (edges[d] % procs[d] > r ? 1 : 0);
22768d2ec52aSSatish Balay       vstart[d] -= overlap; // For halo
22778d2ec52aSSatish Balay     }
22788d2ec52aSSatish Balay   } else {
22798d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
22808d2ec52aSSatish Balay       procs[d]  = 1;
22818d2ec52aSSatish Balay       ledges[d] = edges[d];
22828d2ec52aSSatish Balay     }
22838d2ec52aSSatish Balay   }
22848d2ec52aSSatish Balay   // Calculate local patch size
22858d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) {
22868d2ec52aSSatish Balay     vertices[d] = ledges[d] + (procs[d] > 1 ? 2 * overlap : 0);
2287cfb853baSMatthew G. Knepley     numVertices *= vertices[d];
2288cfb853baSMatthew G. Knepley   }
2289cfb853baSMatthew G. Knepley   numCells = numVertices * dim;
2290cfb853baSMatthew G. Knepley   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
22918d2ec52aSSatish Balay   for (PetscInt c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2));
22928d2ec52aSSatish Balay   for (PetscInt v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim));
2293cfb853baSMatthew G. Knepley   PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */
2294cfb853baSMatthew G. Knepley   /* Build cell cones and vertex supports */
2295cfb853baSMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "celltype"));
22968d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Topology for rank %d:\n", rank));
2297cfb853baSMatthew G. Knepley   while (vert[dim - 1] < vertices[dim - 1]) {
2298cfb853baSMatthew G. Knepley     const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells;
2299cfb853baSMatthew G. Knepley     PetscInt       s      = 0;
23008d2ec52aSSatish Balay     PetscBool      leaf   = PETSC_FALSE;
2301cfb853baSMatthew G. Knepley 
23028d2ec52aSSatish Balay     if (debug) {
23038d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex));
23048d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d]));
23058d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "\n"));
23068d2ec52aSSatish Balay     }
2307cfb853baSMatthew G. Knepley     PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT));
23088d2ec52aSSatish Balay     // Define edge cones
23098d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
23108d2ec52aSSatish Balay       for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e];
2311cfb853baSMatthew G. Knepley       vtmp[d] = (vert[d] + 1) % vertices[d];
2312cfb853baSMatthew G. Knepley       cone[0] = vertex;
2313cfb853baSMatthew G. Knepley       cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells;
23148d2ec52aSSatish Balay       if (debug) {
23158d2ec52aSSatish Balay         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ":", cone[1]));
23168d2ec52aSSatish Balay         for (PetscInt e = 0; e < dim; ++e) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vtmp[e]));
23178d2ec52aSSatish Balay         PetscCall(PetscSynchronizedPrintf(comm, "\n"));
23188d2ec52aSSatish Balay       }
2319cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetCone(dm, cell, cone));
2320cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT));
23218d2ec52aSSatish Balay       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1]));
2322cfb853baSMatthew G. Knepley       ++cell;
23238d2ec52aSSatish Balay       // Shared vertices are any in the first or last overlap layers
23248d2ec52aSSatish Balay       if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE;
2325cfb853baSMatthew G. Knepley     }
23268d2ec52aSSatish Balay     if (size > 1 && leaf) ++Nl;
23278d2ec52aSSatish Balay     // Define vertex supports
23288d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
23298d2ec52aSSatish Balay       for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e];
2330cfb853baSMatthew G. Knepley       vtmp[d]   = (vert[d] + vertices[d] - 1) % vertices[d];
2331cfb853baSMatthew G. Knepley       supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d;
2332cfb853baSMatthew G. Knepley       supp[s++] = (vertex - numCells) * dim + d;
2333cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetSupport(dm, vertex, supp));
2334cfb853baSMatthew G. Knepley     }
2335cfb853baSMatthew G. Knepley     PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert));
2336cfb853baSMatthew G. Knepley   }
23378d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
2338cfb853baSMatthew G. Knepley   PetscCall(DMPlexStratify(dm));
23398d2ec52aSSatish Balay   // Allocate for SF
23408d2ec52aSSatish Balay   PetscCall(PetscMalloc1(Nl, &leaves));
23418d2ec52aSSatish Balay   PetscCall(PetscMalloc1(Nl, &remotes));
23428d2ec52aSSatish Balay   // Build coordinates
2343cfb853baSMatthew G. Knepley   PetscCall(DMGetCoordinateSection(dm, &coordSection));
2344cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetNumFields(coordSection, 1));
2345cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
2346cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
23478d2ec52aSSatish Balay   for (PetscInt v = numCells; v < numCells + numVertices; ++v) {
2348cfb853baSMatthew G. Knepley     PetscCall(PetscSectionSetDof(coordSection, v, dim));
2349cfb853baSMatthew G. Knepley     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
2350cfb853baSMatthew G. Knepley   }
2351cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetUp(coordSection));
2352cfb853baSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
23538d2ec52aSSatish Balay   PetscCall(VecCreate(comm, &coordinates));
2354cfb853baSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
2355cfb853baSMatthew G. Knepley   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
2356cfb853baSMatthew G. Knepley   PetscCall(VecSetBlockSize(coordinates, dim));
2357cfb853baSMatthew G. Knepley   PetscCall(VecSetType(coordinates, VECSTANDARD));
2358cfb853baSMatthew G. Knepley   PetscCall(VecGetArray(coordinates, &coords));
23598d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Geometry for rank %d:\n", rank));
23608d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) vert[d] = 0;
2361cfb853baSMatthew G. Knepley   while (vert[dim - 1] < vertices[dim - 1]) {
2362cfb853baSMatthew G. Knepley     const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert);
23638d2ec52aSSatish Balay     PetscBool      leaf   = PETSC_FALSE;
2364cfb853baSMatthew G. Knepley 
23658d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
23668d2ec52aSSatish Balay       coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / edges[d]) * (vert[d] + vstart[d]);
23678d2ec52aSSatish Balay       if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE;
23688d2ec52aSSatish Balay     }
23698d2ec52aSSatish Balay     if (size > 1 && leaf) {
23708d2ec52aSSatish Balay       PetscInt rnumCells = 1;
23718d2ec52aSSatish Balay 
23728d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) rvert[d] = vert[d] + vstart[d];
23738d2ec52aSSatish Balay       TupleToRanks_Private(dim, edges, procs, rvert, rrank);
23748d2ec52aSSatish Balay       leaves[Nl2]       = vertex + numCells;
23758d2ec52aSSatish Balay       remotes[Nl2].rank = TupleToIndex_Private(dim, procs, rrank);
23768d2ec52aSSatish Balay       RanksToSizes_Private(dim, edges, procs, rrank, rvertices);
23778d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) {
23788d2ec52aSSatish Balay         rvertices[d] += 2 * overlap; // Add halo
23798d2ec52aSSatish Balay         rnumCells *= rvertices[d];
23808d2ec52aSSatish Balay       }
23818d2ec52aSSatish Balay       rnumCells *= dim;
23828d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) {
23838d2ec52aSSatish Balay         const PetscInt diff = rrank[d] - lrank[d];
23848d2ec52aSSatish Balay 
23858d2ec52aSSatish Balay         if (!diff) rvert[d] = vert[d];                                     // Vertex is local
23868d2ec52aSSatish Balay         else if (rvert[d] < 0) rvert[d] = rvertices[d] - 1 + rvert[d];     // Wrap around at the bottom
23878d2ec52aSSatish Balay         else if (rvert[d] >= edges[d]) rvert[d] = rvert[d] - edges[d] + 1; // Wrap around at the top
23888d2ec52aSSatish Balay         else if (diff == -1) rvert[d] = rvertices[d] - 1 + (vert[d] - overlap);
23898d2ec52aSSatish Balay         else if (diff == 1) rvert[d] = (vertices[d] - vert[d] - 1) + overlap;
23908d2ec52aSSatish Balay         else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Process distance %" PetscInt_FMT " in direction %" PetscInt_FMT " should not be possible", diff, d);
23918d2ec52aSSatish Balay       }
23928d2ec52aSSatish Balay       remotes[Nl2].index = TupleToIndex_Private(dim, rvertices, rvert) + rnumCells;
23938d2ec52aSSatish Balay       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Shared Vertex %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", leaves[Nl2], remotes[Nl2].rank, remotes[Nl2].index));
23948d2ec52aSSatish Balay       ++Nl2;
23958d2ec52aSSatish Balay     }
23968d2ec52aSSatish Balay     if (debug) {
23978d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex));
23988d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d] + vstart[d]));
23998d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %g", (double)PetscRealPart(coords[vertex * dim + d])));
24008d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "\n"));
24018d2ec52aSSatish Balay     }
2402cfb853baSMatthew G. Knepley     PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert));
2403cfb853baSMatthew G. Knepley   }
24048d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
2405cfb853baSMatthew G. Knepley   PetscCall(VecRestoreArray(coordinates, &coords));
2406cfb853baSMatthew G. Knepley   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
2407cfb853baSMatthew G. Knepley   PetscCall(VecDestroy(&coordinates));
24088d2ec52aSSatish Balay   // Build SF
24098d2ec52aSSatish Balay   PetscCheck(Nl == Nl2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Initial number of leaves %" PetscInt_FMT " != %" PetscInt_FMT " final number", Nl, Nl2);
24108d2ec52aSSatish Balay   PetscCall(DMGetPointSF(dm, &sf));
24118d2ec52aSSatish Balay   PetscCall(PetscSFSetGraph(sf, numCells + numVertices, Nl, leaves, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER));
24128d2ec52aSSatish Balay   if (debug) PetscCall(PetscSFView(sf, PETSC_VIEWER_STDOUT_WORLD));
2413cfb853baSMatthew G. Knepley   //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper));
2414cfb853baSMatthew G. Knepley   // Attach the extent
2415cfb853baSMatthew G. Knepley   {
2416cfb853baSMatthew G. Knepley     PetscContainer c;
24178d2ec52aSSatish Balay     PetscInt      *extent, *lextent;
2418cfb853baSMatthew G. Knepley 
2419cfb853baSMatthew G. Knepley     PetscCall(PetscMalloc1(dim, &extent));
24208d2ec52aSSatish Balay     PetscCall(PetscMalloc1(dim, &lextent));
24218d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
24228d2ec52aSSatish Balay       extent[d]  = edges[d];
24238d2ec52aSSatish Balay       lextent[d] = ledges[d];
24248d2ec52aSSatish Balay     }
2425cfb853baSMatthew G. Knepley     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c));
242649abdd8aSBarry Smith     PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault));
2427cfb853baSMatthew G. Knepley     PetscCall(PetscContainerSetPointer(c, extent));
2428cfb853baSMatthew G. Knepley     PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c));
2429cfb853baSMatthew G. Knepley     PetscCall(PetscContainerDestroy(&c));
24308d2ec52aSSatish Balay     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c));
24318d2ec52aSSatish Balay     PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault));
24328d2ec52aSSatish Balay     PetscCall(PetscContainerSetPointer(c, lextent));
24338d2ec52aSSatish Balay     PetscCall(PetscObjectCompose((PetscObject)dm, "_lextent", (PetscObject)c));
24348d2ec52aSSatish Balay     PetscCall(PetscContainerDestroy(&c));
2435cfb853baSMatthew G. Knepley   }
24368d2ec52aSSatish Balay   PetscCall(PetscFree4(procs, lrank, rrank, supp));
24378d2ec52aSSatish Balay   PetscCall(PetscFree7(ledges, vertices, rvertices, vert, rvert, vstart, vtmp));
24383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2439cfb853baSMatthew G. Knepley }
2440cfb853baSMatthew G. Knepley 
2441cfb853baSMatthew G. Knepley /*@C
2442aaa8cc7dSPierre Jolivet   DMPlexCreateHypercubicMesh - Creates a periodic mesh on the tensor product of unit intervals using only vertices and edges.
2443cfb853baSMatthew G. Knepley 
2444cfb853baSMatthew G. Knepley   Collective
2445cfb853baSMatthew G. Knepley 
2446cfb853baSMatthew G. Knepley   Input Parameters:
24478d2ec52aSSatish Balay + comm    - The communicator for the `DM` object
2448cfb853baSMatthew G. Knepley . dim     - The spatial dimension
244920f4b53cSBarry Smith . edges   - Number of edges per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
245020f4b53cSBarry Smith . lower   - The lower left corner, or `NULL` for (0, 0, 0)
24518d2ec52aSSatish Balay . upper   - The upper right corner, or `NULL` for (1, 1, 1)
24528d2ec52aSSatish Balay - overlap - The number of vertices in each direction to include in the overlap (default is 1)
2453cfb853baSMatthew G. Knepley 
2454cfb853baSMatthew G. Knepley   Output Parameter:
2455cfb853baSMatthew G. Knepley . dm - The DM object
2456cfb853baSMatthew G. Knepley 
245720f4b53cSBarry Smith   Level: beginner
245820f4b53cSBarry Smith 
245920f4b53cSBarry Smith   Note:
246020f4b53cSBarry Smith   If you want to customize this mesh using options, you just need to
246120f4b53cSBarry Smith .vb
246220f4b53cSBarry Smith   DMCreate(comm, &dm);
246320f4b53cSBarry Smith   DMSetType(dm, DMPLEX);
246420f4b53cSBarry Smith   DMSetFromOptions(dm);
246520f4b53cSBarry Smith .ve
246620f4b53cSBarry Smith   and use the options on the `DMSetFromOptions()` page.
2467cfb853baSMatthew G. Knepley 
2468cfb853baSMatthew G. Knepley   The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively,
246920f4b53cSBarry Smith .vb
247020f4b53cSBarry Smith  18--0-19--2-20--4-18
247120f4b53cSBarry Smith   |     |     |     |
247220f4b53cSBarry Smith  13    15    17    13
247320f4b53cSBarry Smith   |     |     |     |
247420f4b53cSBarry Smith  24-12-25-14-26-16-24
247520f4b53cSBarry Smith   |     |     |     |
247620f4b53cSBarry Smith   7     9    11     7
247720f4b53cSBarry Smith   |     |     |     |
247820f4b53cSBarry Smith  21--6-22--8-23-10-21
247920f4b53cSBarry Smith   |     |     |     |
248020f4b53cSBarry Smith   1     3     5     1
248120f4b53cSBarry Smith   |     |     |     |
248220f4b53cSBarry Smith  18--0-19--2-20--4-18
248320f4b53cSBarry Smith .ve
2484cfb853baSMatthew G. Knepley 
248576fbde31SPierre Jolivet .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
2486cfb853baSMatthew G. Knepley @*/
24878d2ec52aSSatish Balay PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], PetscInt overlap, DM *dm)
2488cfb853baSMatthew G. Knepley {
2489cfb853baSMatthew G. Knepley   PetscInt       *edg;
2490cfb853baSMatthew G. Knepley   PetscReal      *low, *upp;
2491cfb853baSMatthew G. Knepley   DMBoundaryType *bdt;
2492cfb853baSMatthew G. Knepley   PetscInt        d;
2493cfb853baSMatthew G. Knepley 
2494cfb853baSMatthew G. Knepley   PetscFunctionBegin;
2495cfb853baSMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
2496cfb853baSMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
2497cfb853baSMatthew G. Knepley   PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt));
2498cfb853baSMatthew G. Knepley   for (d = 0; d < dim; ++d) {
2499cfb853baSMatthew G. Knepley     edg[d] = edges ? edges[d] : 1;
2500cfb853baSMatthew G. Knepley     low[d] = lower ? lower[d] : 0.;
2501cfb853baSMatthew G. Knepley     upp[d] = upper ? upper[d] : 1.;
2502cfb853baSMatthew G. Knepley     bdt[d] = DM_BOUNDARY_PERIODIC;
2503cfb853baSMatthew G. Knepley   }
25048d2ec52aSSatish Balay   PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, overlap, bdt));
2505cfb853baSMatthew G. Knepley   PetscCall(PetscFree4(edg, low, upp, bdt));
25063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2507cfb853baSMatthew G. Knepley }
2508cfb853baSMatthew G. Knepley 
2509cc4c1da9SBarry Smith /*@
2510a1cb98faSBarry Smith   DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database.
2511a9074c1eSMatthew G. Knepley 
251220f4b53cSBarry Smith   Logically Collective
2513a9074c1eSMatthew G. Knepley 
2514a9074c1eSMatthew G. Knepley   Input Parameters:
251520f4b53cSBarry Smith + dm     - the `DM` context
2516a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names
2517a9074c1eSMatthew G. Knepley 
2518a1cb98faSBarry Smith   Level: advanced
2519a1cb98faSBarry Smith 
2520a1cb98faSBarry Smith   Note:
2521a9074c1eSMatthew G. Knepley   A hyphen (-) must NOT be given at the beginning of the prefix name.
2522a9074c1eSMatthew G. Knepley   The first character of all runtime options is AUTOMATICALLY the hyphen.
2523a9074c1eSMatthew G. Knepley 
25241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()`
2525a9074c1eSMatthew G. Knepley @*/
2526d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[])
2527d71ae5a4SJacob Faibussowitsch {
2528a9074c1eSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
2529a9074c1eSMatthew G. Knepley 
2530a9074c1eSMatthew G. Knepley   PetscFunctionBegin;
2531a9074c1eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
25329566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
25339566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix));
25343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2535a9074c1eSMatthew G. Knepley }
2536a9074c1eSMatthew G. Knepley 
25379318fe57SMatthew G. Knepley /* Remap geometry to cylinder
253861a622f3SMatthew G. Knepley    TODO: This only works for a single refinement, then it is broken
253961a622f3SMatthew G. Knepley 
25409318fe57SMatthew G. Knepley      Interior square: Linear interpolation is correct
25419318fe57SMatthew G. Knepley      The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing
25429318fe57SMatthew G. Knepley      such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance
25430510c589SMatthew G. Knepley 
25449318fe57SMatthew G. Knepley        phi     = arctan(y/x)
25459318fe57SMatthew G. Knepley        d_close = sqrt(1/8 + 1/4 sin^2(phi))
25469318fe57SMatthew G. Knepley        d_far   = sqrt(1/2 + sin^2(phi))
25470510c589SMatthew G. Knepley 
25489318fe57SMatthew G. Knepley      so we remap them using
25490510c589SMatthew G. Knepley 
25509318fe57SMatthew G. Knepley        x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close)
25519318fe57SMatthew G. Knepley        y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close)
25520510c589SMatthew G. Knepley 
25539318fe57SMatthew G. Knepley      If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y.
25549318fe57SMatthew G. Knepley */
2555d71ae5a4SJacob 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[])
2556d71ae5a4SJacob Faibussowitsch {
25579318fe57SMatthew G. Knepley   const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
25589318fe57SMatthew G. Knepley   const PetscReal ds2 = 0.5 * dis;
255922cc497dSMatthew G. Knepley 
25609318fe57SMatthew G. Knepley   if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) {
25619318fe57SMatthew G. Knepley     f0[0] = u[0];
25629318fe57SMatthew G. Knepley     f0[1] = u[1];
25639318fe57SMatthew G. Knepley   } else {
25649318fe57SMatthew G. Knepley     PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc;
25650510c589SMatthew G. Knepley 
25669318fe57SMatthew G. Knepley     x    = PetscRealPart(u[0]);
25679318fe57SMatthew G. Knepley     y    = PetscRealPart(u[1]);
25689318fe57SMatthew G. Knepley     phi  = PetscAtan2Real(y, x);
25699318fe57SMatthew G. Knepley     sinp = PetscSinReal(phi);
25709318fe57SMatthew G. Knepley     cosp = PetscCosReal(phi);
25719318fe57SMatthew G. Knepley     if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) {
25729318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / sinp);
25739318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / sinp);
25749318fe57SMatthew G. Knepley       xc = ds2 * x / PetscAbsReal(y);
25759318fe57SMatthew G. Knepley       yc = ds2 * PetscSignReal(y);
25769318fe57SMatthew G. Knepley     } else {
25779318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / cosp);
25789318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / cosp);
25799318fe57SMatthew G. Knepley       xc = ds2 * PetscSignReal(x);
25809318fe57SMatthew G. Knepley       yc = ds2 * y / PetscAbsReal(x);
25819318fe57SMatthew G. Knepley     }
25829318fe57SMatthew G. Knepley     f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc);
25839318fe57SMatthew G. Knepley     f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc);
25849318fe57SMatthew G. Knepley   }
25859318fe57SMatthew G. Knepley   f0[2] = u[2];
25869318fe57SMatthew G. Knepley }
25870510c589SMatthew G. Knepley 
258849704ca5SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ, PetscInt Nr)
2589d71ae5a4SJacob Faibussowitsch {
25900510c589SMatthew G. Knepley   const PetscInt dim = 3;
25919318fe57SMatthew G. Knepley   PetscInt       numCells, numVertices;
2592d8c47e87SMatthew G. Knepley   PetscMPIInt    rank;
25930510c589SMatthew G. Knepley 
25940510c589SMatthew G. Knepley   PetscFunctionBegin;
259546139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
25969566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
25979566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
25980510c589SMatthew G. Knepley   /* Create topology */
25990510c589SMatthew G. Knepley   {
26000510c589SMatthew G. Knepley     PetscInt cone[8], c;
26010510c589SMatthew G. Knepley 
2602dd400576SPatrick Sanan     numCells    = rank == 0 ? 5 : 0;
2603dd400576SPatrick Sanan     numVertices = rank == 0 ? 16 : 0;
2604006a8963SMatthew G. Knepley     if (periodicZ == DM_BOUNDARY_PERIODIC) {
2605ae8bcbbbSMatthew G. Knepley       numCells *= 3;
2606dd400576SPatrick Sanan       numVertices = rank == 0 ? 24 : 0;
2607006a8963SMatthew G. Knepley     }
26089566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
26099566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8));
26109566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
2611dd400576SPatrick Sanan     if (rank == 0) {
2612006a8963SMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
26139371c9d4SSatish Balay         cone[0] = 15;
26149371c9d4SSatish Balay         cone[1] = 18;
26159371c9d4SSatish Balay         cone[2] = 17;
26169371c9d4SSatish Balay         cone[3] = 16;
26179371c9d4SSatish Balay         cone[4] = 31;
26189371c9d4SSatish Balay         cone[5] = 32;
26199371c9d4SSatish Balay         cone[6] = 33;
26209371c9d4SSatish Balay         cone[7] = 34;
26219566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
26229371c9d4SSatish Balay         cone[0] = 16;
26239371c9d4SSatish Balay         cone[1] = 17;
26249371c9d4SSatish Balay         cone[2] = 24;
26259371c9d4SSatish Balay         cone[3] = 23;
26269371c9d4SSatish Balay         cone[4] = 32;
26279371c9d4SSatish Balay         cone[5] = 36;
26289371c9d4SSatish Balay         cone[6] = 37;
26299371c9d4SSatish Balay         cone[7] = 33; /* 22 25 26 21 */
26309566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
26319371c9d4SSatish Balay         cone[0] = 18;
26329371c9d4SSatish Balay         cone[1] = 27;
26339371c9d4SSatish Balay         cone[2] = 24;
26349371c9d4SSatish Balay         cone[3] = 17;
26359371c9d4SSatish Balay         cone[4] = 34;
26369371c9d4SSatish Balay         cone[5] = 33;
26379371c9d4SSatish Balay         cone[6] = 37;
26389371c9d4SSatish Balay         cone[7] = 38;
26399566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
26409371c9d4SSatish Balay         cone[0] = 29;
26419371c9d4SSatish Balay         cone[1] = 27;
26429371c9d4SSatish Balay         cone[2] = 18;
26439371c9d4SSatish Balay         cone[3] = 15;
26449371c9d4SSatish Balay         cone[4] = 35;
26459371c9d4SSatish Balay         cone[5] = 31;
26469371c9d4SSatish Balay         cone[6] = 34;
26479371c9d4SSatish Balay         cone[7] = 38;
26489566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
26499371c9d4SSatish Balay         cone[0] = 29;
26509371c9d4SSatish Balay         cone[1] = 15;
26519371c9d4SSatish Balay         cone[2] = 16;
26529371c9d4SSatish Balay         cone[3] = 23;
26539371c9d4SSatish Balay         cone[4] = 35;
26549371c9d4SSatish Balay         cone[5] = 36;
26559371c9d4SSatish Balay         cone[6] = 32;
26569371c9d4SSatish Balay         cone[7] = 31;
26579566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
2658006a8963SMatthew G. Knepley 
26599371c9d4SSatish Balay         cone[0] = 31;
26609371c9d4SSatish Balay         cone[1] = 34;
26619371c9d4SSatish Balay         cone[2] = 33;
26629371c9d4SSatish Balay         cone[3] = 32;
26639371c9d4SSatish Balay         cone[4] = 19;
26649371c9d4SSatish Balay         cone[5] = 22;
26659371c9d4SSatish Balay         cone[6] = 21;
26669371c9d4SSatish Balay         cone[7] = 20;
26679566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
26689371c9d4SSatish Balay         cone[0] = 32;
26699371c9d4SSatish Balay         cone[1] = 33;
26709371c9d4SSatish Balay         cone[2] = 37;
26719371c9d4SSatish Balay         cone[3] = 36;
26729371c9d4SSatish Balay         cone[4] = 22;
26739371c9d4SSatish Balay         cone[5] = 25;
26749371c9d4SSatish Balay         cone[6] = 26;
26759371c9d4SSatish Balay         cone[7] = 21;
26769566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 6, cone));
26779371c9d4SSatish Balay         cone[0] = 34;
26789371c9d4SSatish Balay         cone[1] = 38;
26799371c9d4SSatish Balay         cone[2] = 37;
26809371c9d4SSatish Balay         cone[3] = 33;
26819371c9d4SSatish Balay         cone[4] = 20;
26829371c9d4SSatish Balay         cone[5] = 21;
26839371c9d4SSatish Balay         cone[6] = 26;
26849371c9d4SSatish Balay         cone[7] = 28;
26859566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 7, cone));
26869371c9d4SSatish Balay         cone[0] = 35;
26879371c9d4SSatish Balay         cone[1] = 38;
26889371c9d4SSatish Balay         cone[2] = 34;
26899371c9d4SSatish Balay         cone[3] = 31;
26909371c9d4SSatish Balay         cone[4] = 30;
26919371c9d4SSatish Balay         cone[5] = 19;
26929371c9d4SSatish Balay         cone[6] = 20;
26939371c9d4SSatish Balay         cone[7] = 28;
26949566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 8, cone));
26959371c9d4SSatish Balay         cone[0] = 35;
26969371c9d4SSatish Balay         cone[1] = 31;
26979371c9d4SSatish Balay         cone[2] = 32;
26989371c9d4SSatish Balay         cone[3] = 36;
26999371c9d4SSatish Balay         cone[4] = 30;
27009371c9d4SSatish Balay         cone[5] = 25;
27019371c9d4SSatish Balay         cone[6] = 22;
27029371c9d4SSatish Balay         cone[7] = 19;
27039566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 9, cone));
2704ae8bcbbbSMatthew G. Knepley 
27059371c9d4SSatish Balay         cone[0] = 19;
27069371c9d4SSatish Balay         cone[1] = 20;
27079371c9d4SSatish Balay         cone[2] = 21;
27089371c9d4SSatish Balay         cone[3] = 22;
27099371c9d4SSatish Balay         cone[4] = 15;
27109371c9d4SSatish Balay         cone[5] = 16;
27119371c9d4SSatish Balay         cone[6] = 17;
27129371c9d4SSatish Balay         cone[7] = 18;
27139566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 10, cone));
27149371c9d4SSatish Balay         cone[0] = 22;
27159371c9d4SSatish Balay         cone[1] = 21;
27169371c9d4SSatish Balay         cone[2] = 26;
27179371c9d4SSatish Balay         cone[3] = 25;
27189371c9d4SSatish Balay         cone[4] = 16;
27199371c9d4SSatish Balay         cone[5] = 23;
27209371c9d4SSatish Balay         cone[6] = 24;
27219371c9d4SSatish Balay         cone[7] = 17;
27229566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 11, cone));
27239371c9d4SSatish Balay         cone[0] = 20;
27249371c9d4SSatish Balay         cone[1] = 28;
27259371c9d4SSatish Balay         cone[2] = 26;
27269371c9d4SSatish Balay         cone[3] = 21;
27279371c9d4SSatish Balay         cone[4] = 18;
27289371c9d4SSatish Balay         cone[5] = 17;
27299371c9d4SSatish Balay         cone[6] = 24;
27309371c9d4SSatish Balay         cone[7] = 27;
27319566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 12, cone));
27329371c9d4SSatish Balay         cone[0] = 30;
27339371c9d4SSatish Balay         cone[1] = 28;
27349371c9d4SSatish Balay         cone[2] = 20;
27359371c9d4SSatish Balay         cone[3] = 19;
27369371c9d4SSatish Balay         cone[4] = 29;
27379371c9d4SSatish Balay         cone[5] = 15;
27389371c9d4SSatish Balay         cone[6] = 18;
27399371c9d4SSatish Balay         cone[7] = 27;
27409566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 13, cone));
27419371c9d4SSatish Balay         cone[0] = 30;
27429371c9d4SSatish Balay         cone[1] = 19;
27439371c9d4SSatish Balay         cone[2] = 22;
27449371c9d4SSatish Balay         cone[3] = 25;
27459371c9d4SSatish Balay         cone[4] = 29;
27469371c9d4SSatish Balay         cone[5] = 23;
27479371c9d4SSatish Balay         cone[6] = 16;
27489371c9d4SSatish Balay         cone[7] = 15;
27499566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
2750006a8963SMatthew G. Knepley       } else {
27519371c9d4SSatish Balay         cone[0] = 5;
27529371c9d4SSatish Balay         cone[1] = 8;
27539371c9d4SSatish Balay         cone[2] = 7;
27549371c9d4SSatish Balay         cone[3] = 6;
27559371c9d4SSatish Balay         cone[4] = 9;
27569371c9d4SSatish Balay         cone[5] = 12;
27579371c9d4SSatish Balay         cone[6] = 11;
27589371c9d4SSatish Balay         cone[7] = 10;
27599566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
27609371c9d4SSatish Balay         cone[0] = 6;
27619371c9d4SSatish Balay         cone[1] = 7;
27629371c9d4SSatish Balay         cone[2] = 14;
27639371c9d4SSatish Balay         cone[3] = 13;
27649371c9d4SSatish Balay         cone[4] = 12;
27659371c9d4SSatish Balay         cone[5] = 15;
27669371c9d4SSatish Balay         cone[6] = 16;
27679371c9d4SSatish Balay         cone[7] = 11;
27689566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
27699371c9d4SSatish Balay         cone[0] = 8;
27709371c9d4SSatish Balay         cone[1] = 17;
27719371c9d4SSatish Balay         cone[2] = 14;
27729371c9d4SSatish Balay         cone[3] = 7;
27739371c9d4SSatish Balay         cone[4] = 10;
27749371c9d4SSatish Balay         cone[5] = 11;
27759371c9d4SSatish Balay         cone[6] = 16;
27769371c9d4SSatish Balay         cone[7] = 18;
27779566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
27789371c9d4SSatish Balay         cone[0] = 19;
27799371c9d4SSatish Balay         cone[1] = 17;
27809371c9d4SSatish Balay         cone[2] = 8;
27819371c9d4SSatish Balay         cone[3] = 5;
27829371c9d4SSatish Balay         cone[4] = 20;
27839371c9d4SSatish Balay         cone[5] = 9;
27849371c9d4SSatish Balay         cone[6] = 10;
27859371c9d4SSatish Balay         cone[7] = 18;
27869566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
27879371c9d4SSatish Balay         cone[0] = 19;
27889371c9d4SSatish Balay         cone[1] = 5;
27899371c9d4SSatish Balay         cone[2] = 6;
27909371c9d4SSatish Balay         cone[3] = 13;
27919371c9d4SSatish Balay         cone[4] = 20;
27929371c9d4SSatish Balay         cone[5] = 15;
27939371c9d4SSatish Balay         cone[6] = 12;
27949371c9d4SSatish Balay         cone[7] = 9;
27959566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
2796006a8963SMatthew G. Knepley       }
2797d8c47e87SMatthew G. Knepley     }
27989566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
27999566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
28000510c589SMatthew G. Knepley   }
2801dbc1dc17SMatthew G. Knepley   /* Create cube geometry */
28020510c589SMatthew G. Knepley   {
28030510c589SMatthew G. Knepley     Vec             coordinates;
28040510c589SMatthew G. Knepley     PetscSection    coordSection;
28050510c589SMatthew G. Knepley     PetscScalar    *coords;
28060510c589SMatthew G. Knepley     PetscInt        coordSize, v;
28070510c589SMatthew G. Knepley     const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
28080510c589SMatthew G. Knepley     const PetscReal ds2 = dis / 2.0;
28090510c589SMatthew G. Knepley 
28100510c589SMatthew G. Knepley     /* Build coordinates */
28119566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
28129566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
28139566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
28149566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
28150510c589SMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
28169566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
28179566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
28180510c589SMatthew G. Knepley     }
28199566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
28209566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
28219566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
28229566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
28239566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
28249566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
28259566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
28269566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
2827dd400576SPatrick Sanan     if (rank == 0) {
28289371c9d4SSatish Balay       coords[0 * dim + 0]  = -ds2;
28299371c9d4SSatish Balay       coords[0 * dim + 1]  = -ds2;
28309371c9d4SSatish Balay       coords[0 * dim + 2]  = 0.0;
28319371c9d4SSatish Balay       coords[1 * dim + 0]  = ds2;
28329371c9d4SSatish Balay       coords[1 * dim + 1]  = -ds2;
28339371c9d4SSatish Balay       coords[1 * dim + 2]  = 0.0;
28349371c9d4SSatish Balay       coords[2 * dim + 0]  = ds2;
28359371c9d4SSatish Balay       coords[2 * dim + 1]  = ds2;
28369371c9d4SSatish Balay       coords[2 * dim + 2]  = 0.0;
28379371c9d4SSatish Balay       coords[3 * dim + 0]  = -ds2;
28389371c9d4SSatish Balay       coords[3 * dim + 1]  = ds2;
28399371c9d4SSatish Balay       coords[3 * dim + 2]  = 0.0;
28409371c9d4SSatish Balay       coords[4 * dim + 0]  = -ds2;
28419371c9d4SSatish Balay       coords[4 * dim + 1]  = -ds2;
28429371c9d4SSatish Balay       coords[4 * dim + 2]  = 1.0;
28439371c9d4SSatish Balay       coords[5 * dim + 0]  = -ds2;
28449371c9d4SSatish Balay       coords[5 * dim + 1]  = ds2;
28459371c9d4SSatish Balay       coords[5 * dim + 2]  = 1.0;
28469371c9d4SSatish Balay       coords[6 * dim + 0]  = ds2;
28479371c9d4SSatish Balay       coords[6 * dim + 1]  = ds2;
28489371c9d4SSatish Balay       coords[6 * dim + 2]  = 1.0;
28499371c9d4SSatish Balay       coords[7 * dim + 0]  = ds2;
28509371c9d4SSatish Balay       coords[7 * dim + 1]  = -ds2;
28519371c9d4SSatish Balay       coords[7 * dim + 2]  = 1.0;
28529371c9d4SSatish Balay       coords[8 * dim + 0]  = dis;
28539371c9d4SSatish Balay       coords[8 * dim + 1]  = -dis;
28549371c9d4SSatish Balay       coords[8 * dim + 2]  = 0.0;
28559371c9d4SSatish Balay       coords[9 * dim + 0]  = dis;
28569371c9d4SSatish Balay       coords[9 * dim + 1]  = dis;
28579371c9d4SSatish Balay       coords[9 * dim + 2]  = 0.0;
28589371c9d4SSatish Balay       coords[10 * dim + 0] = dis;
28599371c9d4SSatish Balay       coords[10 * dim + 1] = -dis;
28609371c9d4SSatish Balay       coords[10 * dim + 2] = 1.0;
28619371c9d4SSatish Balay       coords[11 * dim + 0] = dis;
28629371c9d4SSatish Balay       coords[11 * dim + 1] = dis;
28639371c9d4SSatish Balay       coords[11 * dim + 2] = 1.0;
28649371c9d4SSatish Balay       coords[12 * dim + 0] = -dis;
28659371c9d4SSatish Balay       coords[12 * dim + 1] = dis;
28669371c9d4SSatish Balay       coords[12 * dim + 2] = 0.0;
28679371c9d4SSatish Balay       coords[13 * dim + 0] = -dis;
28689371c9d4SSatish Balay       coords[13 * dim + 1] = dis;
28699371c9d4SSatish Balay       coords[13 * dim + 2] = 1.0;
28709371c9d4SSatish Balay       coords[14 * dim + 0] = -dis;
28719371c9d4SSatish Balay       coords[14 * dim + 1] = -dis;
28729371c9d4SSatish Balay       coords[14 * dim + 2] = 0.0;
28739371c9d4SSatish Balay       coords[15 * dim + 0] = -dis;
28749371c9d4SSatish Balay       coords[15 * dim + 1] = -dis;
28759371c9d4SSatish Balay       coords[15 * dim + 2] = 1.0;
2876ae8bcbbbSMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
28779371c9d4SSatish Balay         /* 15 31 19 */ coords[16 * dim + 0] = -ds2;
28789371c9d4SSatish Balay         coords[16 * dim + 1]                = -ds2;
28799371c9d4SSatish Balay         coords[16 * dim + 2]                = 0.5;
28809371c9d4SSatish Balay         /* 16 32 22 */ coords[17 * dim + 0] = ds2;
28819371c9d4SSatish Balay         coords[17 * dim + 1]                = -ds2;
28829371c9d4SSatish Balay         coords[17 * dim + 2]                = 0.5;
28839371c9d4SSatish Balay         /* 17 33 21 */ coords[18 * dim + 0] = ds2;
28849371c9d4SSatish Balay         coords[18 * dim + 1]                = ds2;
28859371c9d4SSatish Balay         coords[18 * dim + 2]                = 0.5;
28869371c9d4SSatish Balay         /* 18 34 20 */ coords[19 * dim + 0] = -ds2;
28879371c9d4SSatish Balay         coords[19 * dim + 1]                = ds2;
28889371c9d4SSatish Balay         coords[19 * dim + 2]                = 0.5;
28899371c9d4SSatish Balay         /* 29 35 30 */ coords[20 * dim + 0] = -dis;
28909371c9d4SSatish Balay         coords[20 * dim + 1]                = -dis;
28919371c9d4SSatish Balay         coords[20 * dim + 2]                = 0.5;
28929371c9d4SSatish Balay         /* 23 36 25 */ coords[21 * dim + 0] = dis;
28939371c9d4SSatish Balay         coords[21 * dim + 1]                = -dis;
28949371c9d4SSatish Balay         coords[21 * dim + 2]                = 0.5;
28959371c9d4SSatish Balay         /* 24 37 26 */ coords[22 * dim + 0] = dis;
28969371c9d4SSatish Balay         coords[22 * dim + 1]                = dis;
28979371c9d4SSatish Balay         coords[22 * dim + 2]                = 0.5;
28989371c9d4SSatish Balay         /* 27 38 28 */ coords[23 * dim + 0] = -dis;
28999371c9d4SSatish Balay         coords[23 * dim + 1]                = dis;
29009371c9d4SSatish Balay         coords[23 * dim + 2]                = 0.5;
2901ae8bcbbbSMatthew G. Knepley       }
2902d8c47e87SMatthew G. Knepley     }
29039566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
29049566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
29059566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
29060510c589SMatthew G. Knepley   }
2907006a8963SMatthew G. Knepley   /* Create periodicity */
2908006a8963SMatthew G. Knepley   if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) {
29096858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
29106858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
2911006a8963SMatthew G. Knepley     PetscReal lower[3]   = {0.0, 0.0, 0.0};
2912ae8bcbbbSMatthew G. Knepley     PetscReal upper[3]   = {1.0, 1.0, 1.5};
29136858538eSMatthew G. Knepley     PetscInt  numZCells  = 3;
2914006a8963SMatthew G. Knepley 
29156858538eSMatthew G. Knepley     L[2]       = upper[2] - lower[2];
29166858538eSMatthew G. Knepley     maxCell[2] = 1.1 * (L[2] / numZCells);
29174fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
2918006a8963SMatthew G. Knepley   }
2919dbc1dc17SMatthew G. Knepley   {
29209318fe57SMatthew G. Knepley     DM          cdm;
29219318fe57SMatthew G. Knepley     PetscDS     cds;
29229318fe57SMatthew G. Knepley     PetscScalar c[2] = {1.0, 1.0};
2923dbc1dc17SMatthew G. Knepley 
2924*4c712d99Sksagiyam     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE, NULL));
29259566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
29269566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
29279566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 2, c));
2928dbc1dc17SMatthew G. Knepley   }
292946139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
293046139095SJed Brown 
29319318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
29329566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(dm));
293349704ca5SMatthew G. Knepley 
293449704ca5SMatthew G. Knepley   char        oldprefix[PETSC_MAX_PATH_LEN];
293549704ca5SMatthew G. Knepley   const char *prefix;
293649704ca5SMatthew G. Knepley 
293749704ca5SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
293849704ca5SMatthew G. Knepley   PetscCall(PetscStrncpy(oldprefix, prefix, PETSC_MAX_PATH_LEN));
293949704ca5SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, "petsc_cyl_ref_"));
294049704ca5SMatthew G. Knepley   for (PetscInt r = 0; r < PetscMax(0, Nr); ++r) {
294149704ca5SMatthew G. Knepley     DM rdm;
294249704ca5SMatthew G. Knepley 
294349704ca5SMatthew G. Knepley     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
294449704ca5SMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &rdm));
294549704ca5SMatthew G. Knepley   }
294649704ca5SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldprefix));
294749704ca5SMatthew G. Knepley   PetscCall(DMPlexRemapGeometry(dm, 0.0, snapToCylinder));
294849704ca5SMatthew G. Knepley 
294949704ca5SMatthew G. Knepley   DMLabel         bdlabel, edgelabel;
295049704ca5SMatthew G. Knepley   IS              faceIS;
295149704ca5SMatthew G. Knepley   const PetscInt *faces;
295249704ca5SMatthew G. Knepley   PetscInt        Nf;
295349704ca5SMatthew G. Knepley 
295449704ca5SMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "marker"));
295549704ca5SMatthew G. Knepley   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
295649704ca5SMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "generatrix"));
295749704ca5SMatthew G. Knepley   PetscCall(DMGetLabel(dm, "generatrix", &edgelabel));
295849704ca5SMatthew G. Knepley   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
295949704ca5SMatthew G. Knepley   // Remove faces on top and bottom
296049704ca5SMatthew G. Knepley   PetscCall(DMLabelGetStratumIS(bdlabel, 1, &faceIS));
2961ba1b3593SJeremy L Thompson   if (faceIS) {
296249704ca5SMatthew G. Knepley     PetscCall(ISGetLocalSize(faceIS, &Nf));
296349704ca5SMatthew G. Knepley     PetscCall(ISGetIndices(faceIS, &faces));
296449704ca5SMatthew G. Knepley     for (PetscInt f = 0; f < Nf; ++f) {
296549704ca5SMatthew G. Knepley       PetscReal vol, normal[3];
296649704ca5SMatthew G. Knepley 
296749704ca5SMatthew G. Knepley       PetscCall(DMPlexComputeCellGeometryFVM(dm, faces[f], &vol, NULL, normal));
296849704ca5SMatthew G. Knepley       if (PetscAbsReal(normal[2]) < PETSC_SMALL) PetscCall(DMLabelSetValue(edgelabel, faces[f], 1));
296949704ca5SMatthew G. Knepley     }
297049704ca5SMatthew G. Knepley     PetscCall(ISRestoreIndices(faceIS, &faces));
297149704ca5SMatthew G. Knepley     PetscCall(ISDestroy(&faceIS));
2972ba1b3593SJeremy L Thompson   }
297349704ca5SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(dm, bdlabel));
297449704ca5SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(dm, edgelabel));
29753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29760510c589SMatthew G. Knepley }
29770510c589SMatthew G. Knepley 
297824119c2aSMatthew G. Knepley /*@
29799318fe57SMatthew G. Knepley   DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra.
298024119c2aSMatthew G. Knepley 
2981d083f849SBarry Smith   Collective
298224119c2aSMatthew G. Knepley 
298324119c2aSMatthew G. Knepley   Input Parameters:
2984a1cb98faSBarry Smith + comm      - The communicator for the `DM` object
298549704ca5SMatthew G. Knepley . periodicZ - The boundary type for the Z direction
298649704ca5SMatthew G. Knepley - Nr        - The number of refinements to carry out
298724119c2aSMatthew G. Knepley 
298824119c2aSMatthew G. Knepley   Output Parameter:
298920f4b53cSBarry Smith . dm - The `DM` object
299024119c2aSMatthew G. Knepley 
299124119c2aSMatthew G. Knepley   Level: beginner
299224119c2aSMatthew G. Knepley 
2993a1cb98faSBarry Smith   Note:
2994a4e35b19SJacob Faibussowitsch   Here is the output numbering looking from the bottom of the cylinder\:
2995a1cb98faSBarry Smith .vb
2996a1cb98faSBarry Smith        17-----14
2997a1cb98faSBarry Smith         |     |
2998a1cb98faSBarry Smith         |  2  |
2999a1cb98faSBarry Smith         |     |
3000a1cb98faSBarry Smith  17-----8-----7-----14
3001a1cb98faSBarry Smith   |     |     |     |
3002a1cb98faSBarry Smith   |  3  |  0  |  1  |
3003a1cb98faSBarry Smith   |     |     |     |
3004a1cb98faSBarry Smith  19-----5-----6-----13
3005a1cb98faSBarry Smith         |     |
3006a1cb98faSBarry Smith         |  4  |
3007a1cb98faSBarry Smith         |     |
3008a1cb98faSBarry Smith        19-----13
3009a1cb98faSBarry Smith 
3010a1cb98faSBarry Smith  and up through the top
3011a1cb98faSBarry Smith 
3012a1cb98faSBarry Smith        18-----16
3013a1cb98faSBarry Smith         |     |
3014a1cb98faSBarry Smith         |  2  |
3015a1cb98faSBarry Smith         |     |
3016a1cb98faSBarry Smith  18----10----11-----16
3017a1cb98faSBarry Smith   |     |     |     |
3018a1cb98faSBarry Smith   |  3  |  0  |  1  |
3019a1cb98faSBarry Smith   |     |     |     |
3020a1cb98faSBarry Smith  20-----9----12-----15
3021a1cb98faSBarry Smith         |     |
3022a1cb98faSBarry Smith         |  4  |
3023a1cb98faSBarry Smith         |     |
3024a1cb98faSBarry Smith        20-----15
3025a1cb98faSBarry Smith .ve
3026a1cb98faSBarry Smith 
30271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
302824119c2aSMatthew G. Knepley @*/
302949704ca5SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, PetscInt Nr, DM *dm)
3030d71ae5a4SJacob Faibussowitsch {
30319318fe57SMatthew G. Knepley   PetscFunctionBegin;
303249704ca5SMatthew G. Knepley   PetscAssertPointer(dm, 4);
30339566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
30349566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
303549704ca5SMatthew G. Knepley   PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ, Nr));
30363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30379318fe57SMatthew G. Knepley }
30389318fe57SMatthew G. Knepley 
3039d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate)
3040d71ae5a4SJacob Faibussowitsch {
304124119c2aSMatthew G. Knepley   const PetscInt dim = 3;
3042412e9a14SMatthew G. Knepley   PetscInt       numCells, numVertices, v;
30439fe9f049SMatthew G. Knepley   PetscMPIInt    rank;
304424119c2aSMatthew G. Knepley 
304524119c2aSMatthew G. Knepley   PetscFunctionBegin;
304663a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n);
304746139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
30489566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
30499566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
3050412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
30519566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
305224119c2aSMatthew G. Knepley   /* Create topology */
305324119c2aSMatthew G. Knepley   {
305424119c2aSMatthew G. Knepley     PetscInt cone[6], c;
305524119c2aSMatthew G. Knepley 
3056dd400576SPatrick Sanan     numCells    = rank == 0 ? n : 0;
3057dd400576SPatrick Sanan     numVertices = rank == 0 ? 2 * (n + 1) : 0;
30589566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
30599566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
30609566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
306124119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
30629371c9d4SSatish Balay       cone[0] = c + n * 1;
30639371c9d4SSatish Balay       cone[1] = (c + 1) % n + n * 1;
30649371c9d4SSatish Balay       cone[2] = 0 + 3 * n;
30659371c9d4SSatish Balay       cone[3] = c + n * 2;
30669371c9d4SSatish Balay       cone[4] = (c + 1) % n + n * 2;
30679371c9d4SSatish Balay       cone[5] = 1 + 3 * n;
30689566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(dm, c, cone));
30699566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR));
307024119c2aSMatthew G. Knepley     }
30719566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
30729566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
307324119c2aSMatthew G. Knepley   }
307448a46eb9SPierre Jolivet   for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT));
307524119c2aSMatthew G. Knepley   /* Create cylinder geometry */
307624119c2aSMatthew G. Knepley   {
307724119c2aSMatthew G. Knepley     Vec          coordinates;
307824119c2aSMatthew G. Knepley     PetscSection coordSection;
307924119c2aSMatthew G. Knepley     PetscScalar *coords;
3080412e9a14SMatthew G. Knepley     PetscInt     coordSize, c;
308124119c2aSMatthew G. Knepley 
308224119c2aSMatthew G. Knepley     /* Build coordinates */
30839566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
30849566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
30859566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
30869566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
308724119c2aSMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
30889566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
30899566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
309024119c2aSMatthew G. Knepley     }
30919566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
30929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
30939566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
30949566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
30959566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
30969566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
30979566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
30989566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
309924119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
31009371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
31019371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
31029371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 2] = 1.0;
31039371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
31049371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
31059371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 2] = 0.0;
310624119c2aSMatthew G. Knepley     }
3107dd400576SPatrick Sanan     if (rank == 0) {
31089371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 0] = 0.0;
31099371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 1] = 0.0;
31109371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 2] = 1.0;
31119371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 0] = 0.0;
31129371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 1] = 0.0;
31139371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 2] = 0.0;
31149fe9f049SMatthew G. Knepley     }
31159566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
31169566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
31179566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
311824119c2aSMatthew G. Knepley   }
311946139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
31209318fe57SMatthew G. Knepley   /* Interpolate */
31219566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
31223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31239318fe57SMatthew G. Knepley }
31249318fe57SMatthew G. Knepley 
31259318fe57SMatthew G. Knepley /*@
31269318fe57SMatthew G. Knepley   DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges.
31279318fe57SMatthew G. Knepley 
31289318fe57SMatthew G. Knepley   Collective
31299318fe57SMatthew G. Knepley 
31309318fe57SMatthew G. Knepley   Input Parameters:
3131a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
31329318fe57SMatthew G. Knepley . n           - The number of wedges around the origin
31339318fe57SMatthew G. Knepley - interpolate - Create edges and faces
31349318fe57SMatthew G. Knepley 
31359318fe57SMatthew G. Knepley   Output Parameter:
3136a1cb98faSBarry Smith . dm - The `DM` object
31379318fe57SMatthew G. Knepley 
31389318fe57SMatthew G. Knepley   Level: beginner
31399318fe57SMatthew G. Knepley 
31401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
31419318fe57SMatthew G. Knepley @*/
3142d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm)
3143d71ae5a4SJacob Faibussowitsch {
31449318fe57SMatthew G. Knepley   PetscFunctionBegin;
31454f572ea9SToby Isaac   PetscAssertPointer(dm, 4);
31469566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
31479566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
31489566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate));
31493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
315024119c2aSMatthew G. Knepley }
315124119c2aSMatthew G. Knepley 
3152d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
3153d71ae5a4SJacob Faibussowitsch {
315465a81367SMatthew G. Knepley   PetscReal prod = 0.0;
315565a81367SMatthew G. Knepley   PetscInt  i;
315665a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]);
315765a81367SMatthew G. Knepley   return PetscSqrtReal(prod);
315865a81367SMatthew G. Knepley }
3159dd2b43ebSStefano Zampini 
3160d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
3161d71ae5a4SJacob Faibussowitsch {
316265a81367SMatthew G. Knepley   PetscReal prod = 0.0;
316365a81367SMatthew G. Knepley   PetscInt  i;
316465a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += x[i] * y[i];
316565a81367SMatthew G. Knepley   return prod;
316665a81367SMatthew G. Knepley }
316765a81367SMatthew G. Knepley 
316851a74b61SMatthew G. Knepley /* The first constant is the sphere radius */
3169d71ae5a4SJacob 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[])
3170d71ae5a4SJacob Faibussowitsch {
317151a74b61SMatthew G. Knepley   PetscReal r     = PetscRealPart(constants[0]);
317251a74b61SMatthew G. Knepley   PetscReal norm2 = 0.0, fac;
317351a74b61SMatthew G. Knepley   PetscInt  n     = uOff[1] - uOff[0], d;
317451a74b61SMatthew G. Knepley 
317551a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d]));
317651a74b61SMatthew G. Knepley   fac = r / PetscSqrtReal(norm2);
317751a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) f0[d] = u[d] * fac;
317851a74b61SMatthew G. Knepley }
317951a74b61SMatthew G. Knepley 
3180d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R)
3181d71ae5a4SJacob Faibussowitsch {
318265a81367SMatthew G. Knepley   const PetscInt embedDim = dim + 1;
318365a81367SMatthew G. Knepley   PetscSection   coordSection;
318465a81367SMatthew G. Knepley   Vec            coordinates;
318565a81367SMatthew G. Knepley   PetscScalar   *coords;
318665a81367SMatthew G. Knepley   PetscReal     *coordsIn;
318707c565c5SJose E. Roman   PetscInt       numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, e;
318865a81367SMatthew G. Knepley   PetscMPIInt    rank;
318965a81367SMatthew G. Knepley 
319065a81367SMatthew G. Knepley   PetscFunctionBegin;
31919318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, simplex, 3);
319246139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
31939566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
31949566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim + 1));
31959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
319665a81367SMatthew G. Knepley   switch (dim) {
31975c344501SMatthew G. Knepley   case 1:
31985c344501SMatthew G. Knepley     numCells = 16;
31995c344501SMatthew G. Knepley     numVerts = numCells;
32005c344501SMatthew G. Knepley 
32015c344501SMatthew G. Knepley     // Build Topology
32025c344501SMatthew G. Knepley     PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
32035c344501SMatthew G. Knepley     for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
32045c344501SMatthew G. Knepley     PetscCall(DMSetUp(dm));
32055c344501SMatthew G. Knepley     for (PetscInt c = 0; c < numCells; ++c) {
32065c344501SMatthew G. Knepley       PetscInt cone[2];
32075c344501SMatthew G. Knepley 
32085c344501SMatthew G. Knepley       cone[0] = c + numCells;
32095c344501SMatthew G. Knepley       cone[1] = (c + 1) % numVerts + numCells;
32105c344501SMatthew G. Knepley       PetscCall(DMPlexSetCone(dm, c, cone));
32115c344501SMatthew G. Knepley     }
32125c344501SMatthew G. Knepley     PetscCall(DMPlexSymmetrize(dm));
32135c344501SMatthew G. Knepley     PetscCall(DMPlexStratify(dm));
32145c344501SMatthew G. Knepley     PetscCall(PetscMalloc1(numVerts * embedDim, &coordsIn));
32155c344501SMatthew G. Knepley     for (PetscInt v = 0; v < numVerts; ++v) {
32165c344501SMatthew G. Knepley       const PetscReal rad = 2. * PETSC_PI * v / numVerts;
32175c344501SMatthew G. Knepley 
32185c344501SMatthew G. Knepley       coordsIn[v * embedDim + 0] = PetscCosReal(rad);
32195c344501SMatthew G. Knepley       coordsIn[v * embedDim + 1] = PetscSinReal(rad);
32205c344501SMatthew G. Knepley     }
32215c344501SMatthew G. Knepley     break;
322265a81367SMatthew G. Knepley   case 2:
322365a81367SMatthew G. Knepley     if (simplex) {
322451a74b61SMatthew G. Knepley       const PetscReal radius    = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI);
322551a74b61SMatthew G. Knepley       const PetscReal edgeLen   = 2.0 / (1.0 + PETSC_PHI) * (R / radius);
322665a81367SMatthew G. Knepley       const PetscInt  degree    = 5;
322751a74b61SMatthew G. Knepley       PetscReal       vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)};
322865a81367SMatthew G. Knepley       PetscInt        s[3]      = {1, 1, 1};
322965a81367SMatthew G. Knepley       PetscInt        cone[3];
323007c565c5SJose E. Roman       PetscInt       *graph;
323165a81367SMatthew G. Knepley 
32329371c9d4SSatish Balay       vertex[0] *= R / radius;
32339371c9d4SSatish Balay       vertex[1] *= R / radius;
32349371c9d4SSatish Balay       vertex[2] *= R / radius;
3235dd400576SPatrick Sanan       numCells    = rank == 0 ? 20 : 0;
3236dd400576SPatrick Sanan       numVerts    = rank == 0 ? 12 : 0;
323765a81367SMatthew G. Knepley       firstVertex = numCells;
323851a74b61SMatthew G. Knepley       /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of
323965a81367SMatthew G. Knepley 
324065a81367SMatthew G. Knepley            (0, \pm 1/\phi+1, \pm \phi/\phi+1)
324165a81367SMatthew G. Knepley 
324265a81367SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
324351a74b61SMatthew G. Knepley          length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393.
324465a81367SMatthew G. Knepley       */
324565a81367SMatthew G. Knepley       /* Construct vertices */
32469566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3247dd400576SPatrick Sanan       if (rank == 0) {
324807c565c5SJose E. Roman         for (PetscInt p = 0, i = 0; p < embedDim; ++p) {
324965a81367SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
325065a81367SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
325165a81367SMatthew G. Knepley               for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim];
325265a81367SMatthew G. Knepley               ++i;
325365a81367SMatthew G. Knepley             }
325465a81367SMatthew G. Knepley           }
325565a81367SMatthew G. Knepley         }
325645da822fSValeria Barra       }
325765a81367SMatthew G. Knepley       /* Construct graph */
32589566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
325907c565c5SJose E. Roman       for (PetscInt i = 0; i < numVerts; ++i) {
326007c565c5SJose E. Roman         PetscInt k = 0;
326107c565c5SJose E. Roman         for (PetscInt j = 0; j < numVerts; ++j) {
32629371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
32639371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
32649371c9d4SSatish Balay             ++k;
32659371c9d4SSatish Balay           }
326665a81367SMatthew G. Knepley         }
326763a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
326865a81367SMatthew G. Knepley       }
326965a81367SMatthew G. Knepley       /* Build Topology */
32709566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
327107c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
32729566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
327365a81367SMatthew G. Knepley       /* Cells */
327407c565c5SJose E. Roman       for (PetscInt i = 0, c = 0; i < numVerts; ++i) {
327507c565c5SJose E. Roman         for (PetscInt j = 0; j < i; ++j) {
327607c565c5SJose E. Roman           for (PetscInt k = 0; k < j; ++k) {
327765a81367SMatthew G. Knepley             if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) {
32789371c9d4SSatish Balay               cone[0] = firstVertex + i;
32799371c9d4SSatish Balay               cone[1] = firstVertex + j;
32809371c9d4SSatish Balay               cone[2] = firstVertex + k;
328165a81367SMatthew G. Knepley               /* Check orientation */
328265a81367SMatthew G. Knepley               {
32839371c9d4SSatish Balay                 const PetscInt epsilon[3][3][3] = {
32849371c9d4SSatish Balay                   {{0, 0, 0},  {0, 0, 1},  {0, -1, 0}},
32859371c9d4SSatish Balay                   {{0, 0, -1}, {0, 0, 0},  {1, 0, 0} },
32869371c9d4SSatish Balay                   {{0, 1, 0},  {-1, 0, 0}, {0, 0, 0} }
32879371c9d4SSatish Balay                 };
328865a81367SMatthew G. Knepley                 PetscReal normal[3];
328965a81367SMatthew G. Knepley                 PetscInt  e, f;
329065a81367SMatthew G. Knepley 
329165a81367SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) {
329265a81367SMatthew G. Knepley                   normal[d] = 0.0;
329365a81367SMatthew G. Knepley                   for (e = 0; e < embedDim; ++e) {
3294ad540459SPierre 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]);
329565a81367SMatthew G. Knepley                   }
329665a81367SMatthew G. Knepley                 }
32979371c9d4SSatish Balay                 if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
32989371c9d4SSatish Balay                   PetscInt tmp = cone[1];
32999371c9d4SSatish Balay                   cone[1]      = cone[2];
33009371c9d4SSatish Balay                   cone[2]      = tmp;
330165a81367SMatthew G. Knepley                 }
330265a81367SMatthew G. Knepley               }
33039566063dSJacob Faibussowitsch               PetscCall(DMPlexSetCone(dm, c++, cone));
330465a81367SMatthew G. Knepley             }
330565a81367SMatthew G. Knepley           }
330665a81367SMatthew G. Knepley         }
330765a81367SMatthew G. Knepley       }
33089566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
33099566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
33109566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
331165a81367SMatthew G. Knepley     } else {
33122829fed8SMatthew G. Knepley       /*
33132829fed8SMatthew G. Knepley         12-21--13
33142829fed8SMatthew G. Knepley          |     |
33152829fed8SMatthew G. Knepley         25  4  24
33162829fed8SMatthew G. Knepley          |     |
33172829fed8SMatthew G. Knepley   12-25--9-16--8-24--13
33182829fed8SMatthew G. Knepley    |     |     |     |
33192829fed8SMatthew G. Knepley   23  5 17  0 15  3  22
33202829fed8SMatthew G. Knepley    |     |     |     |
33212829fed8SMatthew G. Knepley   10-20--6-14--7-19--11
33222829fed8SMatthew G. Knepley          |     |
33232829fed8SMatthew G. Knepley         20  1  19
33242829fed8SMatthew G. Knepley          |     |
33252829fed8SMatthew G. Knepley         10-18--11
33262829fed8SMatthew G. Knepley          |     |
33272829fed8SMatthew G. Knepley         23  2  22
33282829fed8SMatthew G. Knepley          |     |
33292829fed8SMatthew G. Knepley         12-21--13
33302829fed8SMatthew G. Knepley        */
33312829fed8SMatthew G. Knepley       PetscInt cone[4], ornt[4];
33322829fed8SMatthew G. Knepley 
3333dd400576SPatrick Sanan       numCells    = rank == 0 ? 6 : 0;
3334dd400576SPatrick Sanan       numEdges    = rank == 0 ? 12 : 0;
3335dd400576SPatrick Sanan       numVerts    = rank == 0 ? 8 : 0;
333665a81367SMatthew G. Knepley       firstVertex = numCells;
333765a81367SMatthew G. Knepley       firstEdge   = numCells + numVerts;
33382829fed8SMatthew G. Knepley       /* Build Topology */
33399566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts));
334007c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4));
334148a46eb9SPierre Jolivet       for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
33429566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3343dd400576SPatrick Sanan       if (rank == 0) {
33442829fed8SMatthew G. Knepley         /* Cell 0 */
33459371c9d4SSatish Balay         cone[0] = 14;
33469371c9d4SSatish Balay         cone[1] = 15;
33479371c9d4SSatish Balay         cone[2] = 16;
33489371c9d4SSatish Balay         cone[3] = 17;
33499566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
33509371c9d4SSatish Balay         ornt[0] = 0;
33519371c9d4SSatish Balay         ornt[1] = 0;
33529371c9d4SSatish Balay         ornt[2] = 0;
33539371c9d4SSatish Balay         ornt[3] = 0;
33549566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 0, ornt));
33552829fed8SMatthew G. Knepley         /* Cell 1 */
33569371c9d4SSatish Balay         cone[0] = 18;
33579371c9d4SSatish Balay         cone[1] = 19;
33589371c9d4SSatish Balay         cone[2] = 14;
33599371c9d4SSatish Balay         cone[3] = 20;
33609566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
33619371c9d4SSatish Balay         ornt[0] = 0;
33629371c9d4SSatish Balay         ornt[1] = 0;
33639371c9d4SSatish Balay         ornt[2] = -1;
33649371c9d4SSatish Balay         ornt[3] = 0;
33659566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 1, ornt));
33662829fed8SMatthew G. Knepley         /* Cell 2 */
33679371c9d4SSatish Balay         cone[0] = 21;
33689371c9d4SSatish Balay         cone[1] = 22;
33699371c9d4SSatish Balay         cone[2] = 18;
33709371c9d4SSatish Balay         cone[3] = 23;
33719566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
33729371c9d4SSatish Balay         ornt[0] = 0;
33739371c9d4SSatish Balay         ornt[1] = 0;
33749371c9d4SSatish Balay         ornt[2] = -1;
33759371c9d4SSatish Balay         ornt[3] = 0;
33769566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 2, ornt));
33772829fed8SMatthew G. Knepley         /* Cell 3 */
33789371c9d4SSatish Balay         cone[0] = 19;
33799371c9d4SSatish Balay         cone[1] = 22;
33809371c9d4SSatish Balay         cone[2] = 24;
33819371c9d4SSatish Balay         cone[3] = 15;
33829566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
33839371c9d4SSatish Balay         ornt[0] = -1;
33849371c9d4SSatish Balay         ornt[1] = -1;
33859371c9d4SSatish Balay         ornt[2] = 0;
33869371c9d4SSatish Balay         ornt[3] = -1;
33879566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 3, ornt));
33882829fed8SMatthew G. Knepley         /* Cell 4 */
33899371c9d4SSatish Balay         cone[0] = 16;
33909371c9d4SSatish Balay         cone[1] = 24;
33919371c9d4SSatish Balay         cone[2] = 21;
33929371c9d4SSatish Balay         cone[3] = 25;
33939566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
33949371c9d4SSatish Balay         ornt[0] = -1;
33959371c9d4SSatish Balay         ornt[1] = -1;
33969371c9d4SSatish Balay         ornt[2] = -1;
33979371c9d4SSatish Balay         ornt[3] = 0;
33989566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 4, ornt));
33992829fed8SMatthew G. Knepley         /* Cell 5 */
34009371c9d4SSatish Balay         cone[0] = 20;
34019371c9d4SSatish Balay         cone[1] = 17;
34029371c9d4SSatish Balay         cone[2] = 25;
34039371c9d4SSatish Balay         cone[3] = 23;
34049566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
34059371c9d4SSatish Balay         ornt[0] = -1;
34069371c9d4SSatish Balay         ornt[1] = -1;
34079371c9d4SSatish Balay         ornt[2] = -1;
34089371c9d4SSatish Balay         ornt[3] = -1;
34099566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 5, ornt));
34102829fed8SMatthew G. Knepley         /* Edges */
34119371c9d4SSatish Balay         cone[0] = 6;
34129371c9d4SSatish Balay         cone[1] = 7;
34139566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
34149371c9d4SSatish Balay         cone[0] = 7;
34159371c9d4SSatish Balay         cone[1] = 8;
34169566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 15, cone));
34179371c9d4SSatish Balay         cone[0] = 8;
34189371c9d4SSatish Balay         cone[1] = 9;
34199566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 16, cone));
34209371c9d4SSatish Balay         cone[0] = 9;
34219371c9d4SSatish Balay         cone[1] = 6;
34229566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 17, cone));
34239371c9d4SSatish Balay         cone[0] = 10;
34249371c9d4SSatish Balay         cone[1] = 11;
34259566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 18, cone));
34269371c9d4SSatish Balay         cone[0] = 11;
34279371c9d4SSatish Balay         cone[1] = 7;
34289566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 19, cone));
34299371c9d4SSatish Balay         cone[0] = 6;
34309371c9d4SSatish Balay         cone[1] = 10;
34319566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 20, cone));
34329371c9d4SSatish Balay         cone[0] = 12;
34339371c9d4SSatish Balay         cone[1] = 13;
34349566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 21, cone));
34359371c9d4SSatish Balay         cone[0] = 13;
34369371c9d4SSatish Balay         cone[1] = 11;
34379566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 22, cone));
34389371c9d4SSatish Balay         cone[0] = 10;
34399371c9d4SSatish Balay         cone[1] = 12;
34409566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 23, cone));
34419371c9d4SSatish Balay         cone[0] = 13;
34429371c9d4SSatish Balay         cone[1] = 8;
34439566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 24, cone));
34449371c9d4SSatish Balay         cone[0] = 12;
34459371c9d4SSatish Balay         cone[1] = 9;
34469566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 25, cone));
344745da822fSValeria Barra       }
34489566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
34499566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
34502829fed8SMatthew G. Knepley       /* Build coordinates */
34519566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3452dd400576SPatrick Sanan       if (rank == 0) {
34539371c9d4SSatish Balay         coordsIn[0 * embedDim + 0] = -R;
34549371c9d4SSatish Balay         coordsIn[0 * embedDim + 1] = R;
34559371c9d4SSatish Balay         coordsIn[0 * embedDim + 2] = -R;
34569371c9d4SSatish Balay         coordsIn[1 * embedDim + 0] = R;
34579371c9d4SSatish Balay         coordsIn[1 * embedDim + 1] = R;
34589371c9d4SSatish Balay         coordsIn[1 * embedDim + 2] = -R;
34599371c9d4SSatish Balay         coordsIn[2 * embedDim + 0] = R;
34609371c9d4SSatish Balay         coordsIn[2 * embedDim + 1] = -R;
34619371c9d4SSatish Balay         coordsIn[2 * embedDim + 2] = -R;
34629371c9d4SSatish Balay         coordsIn[3 * embedDim + 0] = -R;
34639371c9d4SSatish Balay         coordsIn[3 * embedDim + 1] = -R;
34649371c9d4SSatish Balay         coordsIn[3 * embedDim + 2] = -R;
34659371c9d4SSatish Balay         coordsIn[4 * embedDim + 0] = -R;
34669371c9d4SSatish Balay         coordsIn[4 * embedDim + 1] = R;
34679371c9d4SSatish Balay         coordsIn[4 * embedDim + 2] = R;
34689371c9d4SSatish Balay         coordsIn[5 * embedDim + 0] = R;
34699371c9d4SSatish Balay         coordsIn[5 * embedDim + 1] = R;
34709371c9d4SSatish Balay         coordsIn[5 * embedDim + 2] = R;
34719371c9d4SSatish Balay         coordsIn[6 * embedDim + 0] = -R;
34729371c9d4SSatish Balay         coordsIn[6 * embedDim + 1] = -R;
34739371c9d4SSatish Balay         coordsIn[6 * embedDim + 2] = R;
34749371c9d4SSatish Balay         coordsIn[7 * embedDim + 0] = R;
34759371c9d4SSatish Balay         coordsIn[7 * embedDim + 1] = -R;
34769371c9d4SSatish Balay         coordsIn[7 * embedDim + 2] = R;
347765a81367SMatthew G. Knepley       }
347845da822fSValeria Barra     }
347965a81367SMatthew G. Knepley     break;
348065a81367SMatthew G. Knepley   case 3:
3481116ded15SMatthew G. Knepley     if (simplex) {
3482116ded15SMatthew G. Knepley       const PetscReal edgeLen         = 1.0 / PETSC_PHI;
348351a74b61SMatthew G. Knepley       PetscReal       vertexA[4]      = {0.5, 0.5, 0.5, 0.5};
348451a74b61SMatthew G. Knepley       PetscReal       vertexB[4]      = {1.0, 0.0, 0.0, 0.0};
348551a74b61SMatthew G. Knepley       PetscReal       vertexC[4]      = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0};
3486116ded15SMatthew G. Knepley       const PetscInt  degree          = 12;
3487116ded15SMatthew G. Knepley       PetscInt        s[4]            = {1, 1, 1};
34889371c9d4SSatish Balay       PetscInt        evenPerm[12][4] = {
34899371c9d4SSatish Balay         {0, 1, 2, 3},
34909371c9d4SSatish Balay         {0, 2, 3, 1},
34919371c9d4SSatish Balay         {0, 3, 1, 2},
34929371c9d4SSatish Balay         {1, 0, 3, 2},
34939371c9d4SSatish Balay         {1, 2, 0, 3},
34949371c9d4SSatish Balay         {1, 3, 2, 0},
34959371c9d4SSatish Balay         {2, 0, 1, 3},
34969371c9d4SSatish Balay         {2, 1, 3, 0},
34979371c9d4SSatish Balay         {2, 3, 0, 1},
34989371c9d4SSatish Balay         {3, 0, 2, 1},
34999371c9d4SSatish Balay         {3, 1, 0, 2},
35009371c9d4SSatish Balay         {3, 2, 1, 0}
35019371c9d4SSatish Balay       };
3502116ded15SMatthew G. Knepley       PetscInt  cone[4];
3503116ded15SMatthew G. Knepley       PetscInt *graph, p, i, j, k, l;
3504116ded15SMatthew G. Knepley 
35059371c9d4SSatish Balay       vertexA[0] *= R;
35069371c9d4SSatish Balay       vertexA[1] *= R;
35079371c9d4SSatish Balay       vertexA[2] *= R;
35089371c9d4SSatish Balay       vertexA[3] *= R;
35099371c9d4SSatish Balay       vertexB[0] *= R;
35109371c9d4SSatish Balay       vertexB[1] *= R;
35119371c9d4SSatish Balay       vertexB[2] *= R;
35129371c9d4SSatish Balay       vertexB[3] *= R;
35139371c9d4SSatish Balay       vertexC[0] *= R;
35149371c9d4SSatish Balay       vertexC[1] *= R;
35159371c9d4SSatish Balay       vertexC[2] *= R;
35169371c9d4SSatish Balay       vertexC[3] *= R;
3517dd400576SPatrick Sanan       numCells    = rank == 0 ? 600 : 0;
3518dd400576SPatrick Sanan       numVerts    = rank == 0 ? 120 : 0;
3519116ded15SMatthew G. Knepley       firstVertex = numCells;
3520116ded15SMatthew G. Knepley       /* Use the 600-cell, which for a unit sphere has coordinates which are
3521116ded15SMatthew G. Knepley 
3522116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm 1,    \pm 1, \pm 1)                          16
3523116ded15SMatthew G. Knepley                (\pm 1,    0,       0,      0)  all cyclic permutations   8
3524116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm phi, \pm 1/phi, 0)  all even permutations    96
3525116ded15SMatthew G. Knepley 
3526116ded15SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
35276333ae4fSvaleriabarra          length is then given by 1/\phi = 0.61803.
3528116ded15SMatthew G. Knepley 
3529116ded15SMatthew G. Knepley          http://buzzard.pugetsound.edu/sage-practice/ch03s03.html
3530116ded15SMatthew G. Knepley          http://mathworld.wolfram.com/600-Cell.html
3531116ded15SMatthew G. Knepley       */
3532116ded15SMatthew G. Knepley       /* Construct vertices */
35339566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3534116ded15SMatthew G. Knepley       i = 0;
3535dd400576SPatrick Sanan       if (rank == 0) {
3536116ded15SMatthew G. Knepley         for (s[0] = -1; s[0] < 2; s[0] += 2) {
3537116ded15SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
3538116ded15SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
3539116ded15SMatthew G. Knepley               for (s[3] = -1; s[3] < 2; s[3] += 2) {
3540116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d];
3541116ded15SMatthew G. Knepley                 ++i;
3542116ded15SMatthew G. Knepley               }
3543116ded15SMatthew G. Knepley             }
3544116ded15SMatthew G. Knepley           }
3545116ded15SMatthew G. Knepley         }
3546116ded15SMatthew G. Knepley         for (p = 0; p < embedDim; ++p) {
3547116ded15SMatthew G. Knepley           s[1] = s[2] = s[3] = 1;
3548116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
3549116ded15SMatthew G. Knepley             for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim];
3550116ded15SMatthew G. Knepley             ++i;
3551116ded15SMatthew G. Knepley           }
3552116ded15SMatthew G. Knepley         }
3553116ded15SMatthew G. Knepley         for (p = 0; p < 12; ++p) {
3554116ded15SMatthew G. Knepley           s[3] = 1;
3555116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
3556116ded15SMatthew G. Knepley             for (s[1] = -1; s[1] < 2; s[1] += 2) {
3557116ded15SMatthew G. Knepley               for (s[2] = -1; s[2] < 2; s[2] += 2) {
3558116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]];
3559116ded15SMatthew G. Knepley                 ++i;
3560116ded15SMatthew G. Knepley               }
3561116ded15SMatthew G. Knepley             }
3562116ded15SMatthew G. Knepley           }
3563116ded15SMatthew G. Knepley         }
356445da822fSValeria Barra       }
356563a3b9bcSJacob Faibussowitsch       PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts);
3566116ded15SMatthew G. Knepley       /* Construct graph */
35679566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
3568116ded15SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
3569116ded15SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
35709371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
35719371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
35729371c9d4SSatish Balay             ++k;
35739371c9d4SSatish Balay           }
3574116ded15SMatthew G. Knepley         }
357563a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
3576116ded15SMatthew G. Knepley       }
3577116ded15SMatthew G. Knepley       /* Build Topology */
35789566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
357907c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
35809566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3581116ded15SMatthew G. Knepley       /* Cells */
3582dd400576SPatrick Sanan       if (rank == 0) {
358307c565c5SJose E. Roman         for (PetscInt i = 0, c = 0; i < numVerts; ++i) {
3584116ded15SMatthew G. Knepley           for (j = 0; j < i; ++j) {
3585116ded15SMatthew G. Knepley             for (k = 0; k < j; ++k) {
3586116ded15SMatthew G. Knepley               for (l = 0; l < k; ++l) {
35879371c9d4SSatish 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]) {
35889371c9d4SSatish Balay                   cone[0] = firstVertex + i;
35899371c9d4SSatish Balay                   cone[1] = firstVertex + j;
35909371c9d4SSatish Balay                   cone[2] = firstVertex + k;
35919371c9d4SSatish Balay                   cone[3] = firstVertex + l;
3592116ded15SMatthew G. Knepley                   /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */
3593116ded15SMatthew G. Knepley                   {
35949371c9d4SSatish Balay                     const PetscInt epsilon[4][4][4][4] = {
35959371c9d4SSatish 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}}},
3596116ded15SMatthew G. Knepley 
35979371c9d4SSatish 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}}},
3598116ded15SMatthew G. Knepley 
35999371c9d4SSatish 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}}},
3600116ded15SMatthew G. Knepley 
36019371c9d4SSatish 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}} }
36029371c9d4SSatish Balay                     };
3603116ded15SMatthew G. Knepley                     PetscReal normal[4];
3604116ded15SMatthew G. Knepley                     PetscInt  e, f, g;
3605116ded15SMatthew G. Knepley 
3606116ded15SMatthew G. Knepley                     for (d = 0; d < embedDim; ++d) {
3607116ded15SMatthew G. Knepley                       normal[d] = 0.0;
3608116ded15SMatthew G. Knepley                       for (e = 0; e < embedDim; ++e) {
3609116ded15SMatthew G. Knepley                         for (f = 0; f < embedDim; ++f) {
3610116ded15SMatthew G. Knepley                           for (g = 0; g < embedDim; ++g) {
3611116ded15SMatthew 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]);
3612116ded15SMatthew G. Knepley                           }
3613116ded15SMatthew G. Knepley                         }
3614116ded15SMatthew G. Knepley                       }
3615116ded15SMatthew G. Knepley                     }
36169371c9d4SSatish Balay                     if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
36179371c9d4SSatish Balay                       PetscInt tmp = cone[1];
36189371c9d4SSatish Balay                       cone[1]      = cone[2];
36199371c9d4SSatish Balay                       cone[2]      = tmp;
36209371c9d4SSatish Balay                     }
3621116ded15SMatthew G. Knepley                   }
36229566063dSJacob Faibussowitsch                   PetscCall(DMPlexSetCone(dm, c++, cone));
3623116ded15SMatthew G. Knepley                 }
3624116ded15SMatthew G. Knepley               }
3625116ded15SMatthew G. Knepley             }
3626116ded15SMatthew G. Knepley           }
3627116ded15SMatthew G. Knepley         }
362845da822fSValeria Barra       }
36299566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
36309566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
36319566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
3632116ded15SMatthew G. Knepley     }
3633f4d061e9SPierre Jolivet     break;
3634d71ae5a4SJacob Faibussowitsch   default:
3635d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim);
363665a81367SMatthew G. Knepley   }
363765a81367SMatthew G. Knepley   /* Create coordinates */
36389566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
36399566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
36409566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim));
36419566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts));
36422829fed8SMatthew G. Knepley   for (v = firstVertex; v < firstVertex + numVerts; ++v) {
36439566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, embedDim));
36449566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim));
36452829fed8SMatthew G. Knepley   }
36469566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
36479566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
36489566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
36499566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, embedDim));
36509566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
36519566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
36529566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
36539566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
36549371c9d4SSatish Balay   for (v = 0; v < numVerts; ++v)
3655ad540459SPierre Jolivet     for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d];
36569566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
36579566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
36589566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
36599566063dSJacob Faibussowitsch   PetscCall(PetscFree(coordsIn));
366051a74b61SMatthew G. Knepley   {
366151a74b61SMatthew G. Knepley     DM          cdm;
366251a74b61SMatthew G. Knepley     PetscDS     cds;
36639318fe57SMatthew G. Knepley     PetscScalar c = R;
366451a74b61SMatthew G. Knepley 
3665509b31aaSMatthew G. Knepley     PetscCall(DMPlexSetCoordinateMap(dm, snapToSphere));
3666*4c712d99Sksagiyam     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE, NULL));
36679566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
36689566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
36699566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 1, &c));
367051a74b61SMatthew G. Knepley   }
367146139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
36729318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
36739566063dSJacob Faibussowitsch   if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
36743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36759318fe57SMatthew G. Knepley }
36769318fe57SMatthew G. Knepley 
3677b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]);
3678b7f5c055SJed Brown 
3679b7f5c055SJed Brown /*
3680b7f5c055SJed Brown  The Schwarz P implicit surface is
3681b7f5c055SJed Brown 
3682b7f5c055SJed Brown      f(x) = cos(x0) + cos(x1) + cos(x2) = 0
3683b7f5c055SJed Brown */
3684d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
3685d71ae5a4SJacob Faibussowitsch {
3686b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)};
3687b7f5c055SJed Brown   PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)};
3688b7f5c055SJed Brown   f[0]           = c[0] + c[1] + c[2];
3689b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
3690b7f5c055SJed Brown     grad[i] = PETSC_PI * g[i];
3691ad540459SPierre Jolivet     for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.;
3692b7f5c055SJed Brown   }
3693b7f5c055SJed Brown }
3694b7f5c055SJed Brown 
36954663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
3696d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
3697d71ae5a4SJacob Faibussowitsch {
3698ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI);
36993ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
37004663dae6SJed Brown }
37014663dae6SJed Brown 
3702b7f5c055SJed Brown /*
3703b7f5c055SJed Brown  The Gyroid implicit surface is
3704b7f5c055SJed Brown 
3705b7f5c055SJed 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)
3706b7f5c055SJed Brown 
3707b7f5c055SJed Brown */
3708d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
3709d71ae5a4SJacob Faibussowitsch {
3710b7f5c055SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))};
3711b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))};
3712b7f5c055SJed Brown   f[0]           = s[0] * c[1] + s[1] * c[2] + s[2] * c[0];
3713b7f5c055SJed Brown   grad[0]        = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
3714b7f5c055SJed Brown   grad[1]        = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
3715b7f5c055SJed Brown   grad[2]        = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
3716b7f5c055SJed Brown   hess[0][0]     = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]);
3717b7f5c055SJed Brown   hess[0][1]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
3718b7f5c055SJed Brown   hess[0][2]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
3719b7f5c055SJed Brown   hess[1][0]     = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]);
3720b7f5c055SJed Brown   hess[1][1]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
3721b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
3722b7f5c055SJed Brown   hess[2][0]     = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]);
3723b7f5c055SJed Brown   hess[2][1]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
3724b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
3725b7f5c055SJed Brown }
3726b7f5c055SJed Brown 
37274663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
3728d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
3729d71ae5a4SJacob Faibussowitsch {
37304663dae6SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))};
37314663dae6SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))};
37324663dae6SJed Brown   u[0]           = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
37334663dae6SJed Brown   u[1]           = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
37344663dae6SJed Brown   u[2]           = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
37353ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
37364663dae6SJed Brown }
37374663dae6SJed Brown 
3738b7f5c055SJed Brown /*
3739b7f5c055SJed Brown    We wish to solve
3740b7f5c055SJed Brown 
3741b7f5c055SJed Brown          min_y || y - x ||^2  subject to f(y) = 0
3742b7f5c055SJed Brown 
3743b7f5c055SJed Brown    Let g(y) = grad(f).  The minimization problem is equivalent to asking to satisfy
3744b7f5c055SJed 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
3745b7f5c055SJed Brown    tangent space and ask for both components in the tangent space to be zero.
3746b7f5c055SJed Brown 
3747b7f5c055SJed Brown    Take g to be a column vector and compute the "full QR" factorization Q R = g,
3748b7f5c055SJed Brown    where Q = I - 2 n n^T is a symmetric orthogonal matrix.
3749b7f5c055SJed Brown    The first column of Q is parallel to g so the remaining two columns span the null space.
3750b7f5c055SJed Brown    Let Qn = Q[:,1:] be those remaining columns.  Then Qn Qn^T is an orthogonal projector into the tangent space.
3751da81f932SPierre Jolivet    Since Q is symmetric, this is equivalent to multiplying by Q and taking the last two entries.
3752b7f5c055SJed Brown    In total, we have a system of 3 equations in 3 unknowns:
3753b7f5c055SJed Brown 
3754b7f5c055SJed Brown      f(y) = 0                       1 equation
3755b7f5c055SJed Brown      Qn^T (y - x) = 0               2 equations
3756b7f5c055SJed Brown 
3757b7f5c055SJed Brown    Here, we compute the residual and Jacobian of this system.
3758b7f5c055SJed Brown */
3759d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[])
3760d71ae5a4SJacob Faibussowitsch {
3761b7f5c055SJed Brown   PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])};
3762b7f5c055SJed Brown   PetscReal d[3]     = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])};
37632f0490c0SSatish Balay   PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign;
37649371c9d4SSatish Balay   PetscReal n_y[3][3] = {
37659371c9d4SSatish Balay     {0, 0, 0},
37669371c9d4SSatish Balay     {0, 0, 0},
37679371c9d4SSatish Balay     {0, 0, 0}
37689371c9d4SSatish Balay   };
3769b7f5c055SJed Brown 
3770b7f5c055SJed Brown   feval(yreal, &f, grad, n_y);
3771b7f5c055SJed Brown 
3772b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n[i] = grad[i];
3773b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
3774ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i];
3775b7f5c055SJed Brown 
3776b7f5c055SJed Brown   // Define the Householder reflector
3777b7f5c055SJed Brown   sign = n[0] >= 0 ? 1. : -1.;
3778b7f5c055SJed Brown   n[0] += norm * sign;
3779b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign;
3780b7f5c055SJed Brown 
3781b7f5c055SJed Brown   norm      = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
3782b7f5c055SJed Brown   norm_y[0] = 1. / norm * (n[0] * n_y[0][0]);
3783b7f5c055SJed Brown   norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]);
3784b7f5c055SJed Brown   norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]);
3785b7f5c055SJed Brown 
3786b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
3787b7f5c055SJed Brown     n[i] /= norm;
3788b7f5c055SJed Brown     for (PetscInt j = 0; j < 3; j++) {
3789b7f5c055SJed Brown       // note that n[i] is n_old[i]/norm when executing the code below
3790b7f5c055SJed Brown       n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j];
3791b7f5c055SJed Brown     }
3792b7f5c055SJed Brown   }
3793b7f5c055SJed Brown 
3794b7f5c055SJed Brown   nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2];
3795b7f5c055SJed 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];
3796b7f5c055SJed Brown 
3797b7f5c055SJed Brown   res[0] = f;
3798b7f5c055SJed Brown   res[1] = d[1] - 2 * n[1] * nd;
3799b7f5c055SJed Brown   res[2] = d[2] - 2 * n[2] * nd;
3800b7f5c055SJed Brown   // J[j][i] is J_{ij} (column major)
3801b7f5c055SJed Brown   for (PetscInt j = 0; j < 3; j++) {
3802b7f5c055SJed Brown     J[0 + j * 3] = grad[j];
3803b7f5c055SJed Brown     J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]);
3804b7f5c055SJed Brown     J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]);
3805b7f5c055SJed Brown   }
3806b7f5c055SJed Brown }
3807b7f5c055SJed Brown 
3808b7f5c055SJed Brown /*
3809b7f5c055SJed Brown    Project x to the nearest point on the implicit surface using Newton's method.
3810b7f5c055SJed Brown */
3811d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[])
3812d71ae5a4SJacob Faibussowitsch {
3813b7f5c055SJed Brown   PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess
3814b7f5c055SJed Brown 
3815b7f5c055SJed Brown   PetscFunctionBegin;
3816b7f5c055SJed Brown   for (PetscInt iter = 0; iter < 10; iter++) {
3817b7f5c055SJed Brown     PetscScalar res[3], J[9];
3818b7f5c055SJed Brown     PetscReal   resnorm;
3819b7f5c055SJed Brown     TPSNearestPointResJac(feval, x, y, res, J);
3820b7f5c055SJed Brown     resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2])));
3821b7f5c055SJed Brown     if (0) { // Turn on this monitor if you need to confirm quadratic convergence
382263a3b9bcSJacob 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])));
3823b7f5c055SJed Brown     }
3824b7f5c055SJed Brown     if (resnorm < PETSC_SMALL) break;
3825b7f5c055SJed Brown 
3826b7f5c055SJed Brown     // Take the Newton step
38279566063dSJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL));
3828b7f5c055SJed Brown     PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res);
3829b7f5c055SJed Brown   }
3830b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) x[i] = y[i];
38313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3832b7f5c055SJed Brown }
3833b7f5c055SJed Brown 
3834b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL};
3835b7f5c055SJed Brown 
3836d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness)
3837d71ae5a4SJacob Faibussowitsch {
3838b7f5c055SJed Brown   PetscMPIInt rank;
3839b7f5c055SJed Brown   PetscInt    topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0;
3840b7f5c055SJed Brown   PetscInt (*edges)[2] = NULL, *edgeSets = NULL;
3841b7f5c055SJed Brown   PetscInt           *cells_flat = NULL;
3842b7f5c055SJed Brown   PetscReal          *vtxCoords  = NULL;
3843b7f5c055SJed Brown   TPSEvaluateFunc     evalFunc   = NULL;
38448434afd1SBarry Smith   PetscSimplePointFn *normalFunc = NULL;
3845b7f5c055SJed Brown   DMLabel             label;
3846b7f5c055SJed Brown 
3847b7f5c055SJed Brown   PetscFunctionBegin;
384846139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
38499566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
385063a3b9bcSJacob 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);
3851b7f5c055SJed Brown   switch (tpstype) {
3852b7f5c055SJed Brown   case DMPLEX_TPS_SCHWARZ_P:
3853b7f5c055SJed 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");
3854c5853193SPierre Jolivet     if (rank == 0) {
3855b7f5c055SJed Brown       PetscInt (*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn]
3856b7f5c055SJed Brown       PetscInt  Njunctions = 0, Ncuts = 0, Npipes[3], vcount;
3857b7f5c055SJed Brown       PetscReal L = 1;
3858b7f5c055SJed Brown 
3859b7f5c055SJed Brown       Npipes[0]   = (extent[0] + 1) * extent[1] * extent[2];
3860b7f5c055SJed Brown       Npipes[1]   = extent[0] * (extent[1] + 1) * extent[2];
3861b7f5c055SJed Brown       Npipes[2]   = extent[0] * extent[1] * (extent[2] + 1);
3862b7f5c055SJed Brown       Njunctions  = extent[0] * extent[1] * extent[2];
3863b7f5c055SJed Brown       Ncuts       = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]);
3864b7f5c055SJed Brown       numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions;
38659566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords));
38669566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Njunctions, &cells));
38679566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edges));
38689566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets));
3869b7f5c055SJed Brown       // x-normal pipes
3870b7f5c055SJed Brown       vcount = 0;
3871b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0] + 1; i++) {
3872b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3873b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3874b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3875b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * i - 1) * L;
3876b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3877b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3878b7f5c055SJed Brown             }
3879b7f5c055SJed Brown           }
3880b7f5c055SJed Brown         }
3881b7f5c055SJed Brown       }
3882b7f5c055SJed Brown       // y-normal pipes
3883b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3884b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1] + 1; j++) {
3885b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3886b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3887b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3888b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * j - 1) * L;
3889b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3890b7f5c055SJed Brown             }
3891b7f5c055SJed Brown           }
3892b7f5c055SJed Brown         }
3893b7f5c055SJed Brown       }
3894b7f5c055SJed Brown       // z-normal pipes
3895b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3896b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3897b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2] + 1; k++) {
3898b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3899b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3900b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3901b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * k - 1) * L;
3902b7f5c055SJed Brown             }
3903b7f5c055SJed Brown           }
3904b7f5c055SJed Brown         }
3905b7f5c055SJed Brown       }
3906b7f5c055SJed Brown       // junctions
3907b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3908b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3909b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3910b7f5c055SJed Brown             const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8;
3911b7f5c055SJed Brown             PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count");
3912b7f5c055SJed Brown             for (PetscInt ii = 0; ii < 2; ii++) {
3913b7f5c055SJed Brown               for (PetscInt jj = 0; jj < 2; jj++) {
3914b7f5c055SJed Brown                 for (PetscInt kk = 0; kk < 2; kk++) {
3915b7f5c055SJed Brown                   double Ls           = (1 - sqrt(2) / 4) * L;
3916b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls;
3917b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls;
3918b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls;
3919b7f5c055SJed Brown                 }
3920b7f5c055SJed Brown               }
3921b7f5c055SJed Brown             }
3922b7f5c055SJed Brown             const PetscInt jfaces[3][2][4] = {
3923b7f5c055SJed Brown               {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned
3924b7f5c055SJed Brown               {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned
3925b7f5c055SJed Brown               {{6, 2, 0, 4}, {7, 3, 1, 5}}  // z-aligned
3926b7f5c055SJed Brown             };
3927b7f5c055SJed Brown             const PetscInt pipe_lo[3] = {// vertex numbers of pipes
39289371c9d4SSatish 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};
3929b7f5c055SJed Brown             const PetscInt pipe_hi[3] = {// vertex numbers of pipes
39309371c9d4SSatish 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};
3931b7f5c055SJed Brown             for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z
3932b7f5c055SJed Brown               const PetscInt ijk[3] = {i, j, k};
3933b7f5c055SJed Brown               for (PetscInt l = 0; l < 4; l++) { // rotations
3934b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l;
3935b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l];
3936b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4];
3937b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4;
3938b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l];
3939b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l;
3940b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4;
3941b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4];
3942b7f5c055SJed Brown                 if (ijk[dir] == 0) {
3943b7f5c055SJed Brown                   edges[numEdges][0] = pipe_lo[dir] + l;
3944b7f5c055SJed Brown                   edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4;
3945b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 1;
3946b7f5c055SJed Brown                   numEdges++;
3947b7f5c055SJed Brown                 }
3948b7f5c055SJed Brown                 if (ijk[dir] + 1 == extent[dir]) {
3949b7f5c055SJed Brown                   edges[numEdges][0] = pipe_hi[dir] + l;
3950b7f5c055SJed Brown                   edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4;
3951b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 2;
3952b7f5c055SJed Brown                   numEdges++;
3953b7f5c055SJed Brown                 }
3954b7f5c055SJed Brown               }
3955b7f5c055SJed Brown             }
3956b7f5c055SJed Brown           }
3957b7f5c055SJed Brown         }
3958b7f5c055SJed Brown       }
395963a3b9bcSJacob Faibussowitsch       PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts);
3960b7f5c055SJed Brown       numFaces   = 24 * Njunctions;
3961b7f5c055SJed Brown       cells_flat = cells[0][0][0];
3962b7f5c055SJed Brown     }
3963b7f5c055SJed Brown     evalFunc   = TPSEvaluate_SchwarzP;
39644663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_SchwarzP;
3965b7f5c055SJed Brown     break;
3966b7f5c055SJed Brown   case DMPLEX_TPS_GYROID:
3967c5853193SPierre Jolivet     if (rank == 0) {
3968b7f5c055SJed Brown       // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set
3969b7f5c055SJed Brown       //
3970b7f5c055SJed 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)
3971b7f5c055SJed Brown       //
3972b7f5c055SJed Brown       // on the cell [0,2]^3.
3973b7f5c055SJed Brown       //
3974b7f5c055SJed Brown       // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2].
3975b7f5c055SJed Brown       // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins
3976b7f5c055SJed Brown       // like a boomerang:
3977b7f5c055SJed Brown       //
3978b7f5c055SJed Brown       //     z = 0          z = 1/4        z = 1/2        z = 3/4     //
3979b7f5c055SJed Brown       //     -----          -------        -------        -------     //
3980b7f5c055SJed Brown       //                                                              //
3981b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
3982b7f5c055SJed Brown       //      \                                   /            \      //
3983b7f5c055SJed Brown       //       \            `-_   _-'            /              }     //
3984b7f5c055SJed Brown       //        *-_            `-'            _-'              /      //
3985b7f5c055SJed Brown       //     +     `-+      +       +      +-'     +      +   /   +   //
3986b7f5c055SJed Brown       //                                                              //
3987b7f5c055SJed Brown       //                                                              //
3988b7f5c055SJed Brown       //     z = 1          z = 5/4        z = 3/2        z = 7/4     //
3989b7f5c055SJed Brown       //     -----          -------        -------        -------     //
3990b7f5c055SJed Brown       //                                                              //
3991b7f5c055SJed Brown       //     +-_     +      +       +      +     _-+      +   /   +   //
3992b7f5c055SJed Brown       //        `-_            _-_            _-`            /        //
3993b7f5c055SJed Brown       //           \        _-'   `-_        /              {         //
3994b7f5c055SJed Brown       //            \                       /                \        //
3995b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
3996b7f5c055SJed Brown       //
3997b7f5c055SJed Brown       //
3998b7f5c055SJed Brown       // This course mesh approximates each of these slices by two line segments,
3999b7f5c055SJed Brown       // and then connects the segments in consecutive layers with quadrilateral faces.
4000b7f5c055SJed Brown       // All of the end points of the segments are multiples of 1/4 except for the
4001b7f5c055SJed Brown       // point * in the picture for z = 0 above and the similar points in other layers.
4002b7f5c055SJed Brown       // That point is at (gamma, gamma, 0), where gamma is calculated below.
4003b7f5c055SJed Brown       //
4004b7f5c055SJed Brown       // The column  [1,2]x[1,2]x[0,2] looks the same as this column;
4005b7f5c055SJed Brown       // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images.
4006b7f5c055SJed Brown       //
4007b7f5c055SJed Brown       // As for how this method turned into the names given to the vertices:
4008b7f5c055SJed Brown       // that was not systematic, it was just the way it worked out in my handwritten notes.
4009b7f5c055SJed Brown 
4010b7f5c055SJed Brown       PetscInt facesPerBlock = 64;
4011b7f5c055SJed Brown       PetscInt vertsPerBlock = 56;
4012b7f5c055SJed Brown       PetscInt extentPlus[3];
4013b7f5c055SJed Brown       PetscInt numBlocks, numBlocksPlus;
40149371c9d4SSatish 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;
40159371c9d4SSatish Balay       const PetscInt pattern[64][4] = {
40169371c9d4SSatish Balay         /* face to vertex within the coarse discretization of a single gyroid block */
4017b7f5c055SJed Brown         /* layer 0 */
40189371c9d4SSatish Balay         {A,           C,           K,           G          },
40199371c9d4SSatish Balay         {C,           B,           II,          K          },
40209371c9d4SSatish Balay         {D,           A,           H,           L          },
40219371c9d4SSatish Balay         {B + 56 * 1,  D,           L,           J          },
40229371c9d4SSatish Balay         {E,           B + 56 * 1,  J,           N          },
40239371c9d4SSatish Balay         {A + 56 * 2,  E,           N,           H + 56 * 2 },
40249371c9d4SSatish Balay         {F,           A + 56 * 2,  G + 56 * 2,  M          },
40259371c9d4SSatish Balay         {B,           F,           M,           II         },
4026b7f5c055SJed Brown         /* layer 1 */
40279371c9d4SSatish Balay         {G,           K,           Q,           O          },
40289371c9d4SSatish Balay         {K,           II,          P,           Q          },
40299371c9d4SSatish Balay         {L,           H,           O + 56 * 1,  R          },
40309371c9d4SSatish Balay         {J,           L,           R,           P          },
40319371c9d4SSatish Balay         {N,           J,           P,           S          },
40329371c9d4SSatish Balay         {H + 56 * 2,  N,           S,           O + 56 * 3 },
40339371c9d4SSatish Balay         {M,           G + 56 * 2,  O + 56 * 2,  T          },
40349371c9d4SSatish Balay         {II,          M,           T,           P          },
4035b7f5c055SJed Brown         /* layer 2 */
40369371c9d4SSatish Balay         {O,           Q,           Y,           U          },
40379371c9d4SSatish Balay         {Q,           P,           W,           Y          },
40389371c9d4SSatish Balay         {R,           O + 56 * 1,  U + 56 * 1,  Ap         },
40399371c9d4SSatish Balay         {P,           R,           Ap,          W          },
40409371c9d4SSatish Balay         {S,           P,           X,           Bp         },
40419371c9d4SSatish Balay         {O + 56 * 3,  S,           Bp,          V + 56 * 1 },
40429371c9d4SSatish Balay         {T,           O + 56 * 2,  V,           Z          },
40439371c9d4SSatish Balay         {P,           T,           Z,           X          },
4044b7f5c055SJed Brown         /* layer 3 */
40459371c9d4SSatish Balay         {U,           Y,           Ep,          Dp         },
40469371c9d4SSatish Balay         {Y,           W,           Cp,          Ep         },
40479371c9d4SSatish Balay         {Ap,          U + 56 * 1,  Dp + 56 * 1, Gp         },
40489371c9d4SSatish Balay         {W,           Ap,          Gp,          Cp         },
40499371c9d4SSatish Balay         {Bp,          X,           Cp + 56 * 2, Fp         },
40509371c9d4SSatish Balay         {V + 56 * 1,  Bp,          Fp,          Dp + 56 * 1},
40519371c9d4SSatish Balay         {Z,           V,           Dp,          Hp         },
40529371c9d4SSatish Balay         {X,           Z,           Hp,          Cp + 56 * 2},
4053b7f5c055SJed Brown         /* layer 4 */
40549371c9d4SSatish Balay         {Dp,          Ep,          Mp,          Kp         },
40559371c9d4SSatish Balay         {Ep,          Cp,          Ip,          Mp         },
40569371c9d4SSatish Balay         {Gp,          Dp + 56 * 1, Lp,          Np         },
40579371c9d4SSatish Balay         {Cp,          Gp,          Np,          Jp         },
40589371c9d4SSatish Balay         {Fp,          Cp + 56 * 2, Jp + 56 * 2, Pp         },
40599371c9d4SSatish Balay         {Dp + 56 * 1, Fp,          Pp,          Lp         },
40609371c9d4SSatish Balay         {Hp,          Dp,          Kp,          Op         },
40619371c9d4SSatish Balay         {Cp + 56 * 2, Hp,          Op,          Ip + 56 * 2},
4062b7f5c055SJed Brown         /* layer 5 */
40639371c9d4SSatish Balay         {Kp,          Mp,          Sp,          Rp         },
40649371c9d4SSatish Balay         {Mp,          Ip,          Qp,          Sp         },
40659371c9d4SSatish Balay         {Np,          Lp,          Rp,          Tp         },
40669371c9d4SSatish Balay         {Jp,          Np,          Tp,          Qp + 56 * 1},
40679371c9d4SSatish Balay         {Pp,          Jp + 56 * 2, Qp + 56 * 3, Up         },
40689371c9d4SSatish Balay         {Lp,          Pp,          Up,          Rp         },
40699371c9d4SSatish Balay         {Op,          Kp,          Rp,          Vp         },
40709371c9d4SSatish Balay         {Ip + 56 * 2, Op,          Vp,          Qp + 56 * 2},
4071b7f5c055SJed Brown         /* layer 6 */
40729371c9d4SSatish Balay         {Rp,          Sp,          Aq,          Yp         },
40739371c9d4SSatish Balay         {Sp,          Qp,          Wp,          Aq         },
40749371c9d4SSatish Balay         {Tp,          Rp,          Yp,          Cq         },
40759371c9d4SSatish Balay         {Qp + 56 * 1, Tp,          Cq,          Wp + 56 * 1},
40769371c9d4SSatish Balay         {Up,          Qp + 56 * 3, Xp + 56 * 1, Dq         },
40779371c9d4SSatish Balay         {Rp,          Up,          Dq,          Zp         },
40789371c9d4SSatish Balay         {Vp,          Rp,          Zp,          Bq         },
40799371c9d4SSatish Balay         {Qp + 56 * 2, Vp,          Bq,          Xp         },
4080b7f5c055SJed Brown         /* layer 7 (the top is the periodic image of the bottom of layer 0) */
40819371c9d4SSatish Balay         {Yp,          Aq,          C + 56 * 4,  A + 56 * 4 },
40829371c9d4SSatish Balay         {Aq,          Wp,          B + 56 * 4,  C + 56 * 4 },
40839371c9d4SSatish Balay         {Cq,          Yp,          A + 56 * 4,  D + 56 * 4 },
40849371c9d4SSatish Balay         {Wp + 56 * 1, Cq,          D + 56 * 4,  B + 56 * 5 },
40859371c9d4SSatish Balay         {Dq,          Xp + 56 * 1, B + 56 * 5,  E + 56 * 4 },
40869371c9d4SSatish Balay         {Zp,          Dq,          E + 56 * 4,  A + 56 * 6 },
40879371c9d4SSatish Balay         {Bq,          Zp,          A + 56 * 6,  F + 56 * 4 },
40889371c9d4SSatish Balay         {Xp,          Bq,          F + 56 * 4,  B + 56 * 4 }
4089b7f5c055SJed Brown       };
4090b7f5c055SJed Brown       const PetscReal gamma                = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI;
40919371c9d4SSatish Balay       const PetscReal patternCoords[56][3] = {
4092bee3fc89SBarry Smith         {1.,        0.,        0.  }, /* A  */
4093bee3fc89SBarry Smith         {0.,        1.,        0.  }, /* B  */
4094bee3fc89SBarry Smith         {gamma,     gamma,     0.  }, /* C  */
4095bee3fc89SBarry Smith         {1 + gamma, 1 - gamma, 0.  }, /* D  */
4096bee3fc89SBarry Smith         {2 - gamma, 2 - gamma, 0.  }, /* E  */
4097bee3fc89SBarry Smith         {1 - gamma, 1 + gamma, 0.  }, /* F  */
4098b7f5c055SJed Brown 
4099bee3fc89SBarry Smith         {.5,        0,         .25 }, /* G  */
4100bee3fc89SBarry Smith         {1.5,       0.,        .25 }, /* H  */
4101bee3fc89SBarry Smith         {.5,        1.,        .25 }, /* II */
4102bee3fc89SBarry Smith         {1.5,       1.,        .25 }, /* J  */
4103bee3fc89SBarry Smith         {.25,       .5,        .25 }, /* K  */
4104bee3fc89SBarry Smith         {1.25,      .5,        .25 }, /* L  */
4105bee3fc89SBarry Smith         {.75,       1.5,       .25 }, /* M  */
4106bee3fc89SBarry Smith         {1.75,      1.5,       .25 }, /* N  */
4107b7f5c055SJed Brown 
4108bee3fc89SBarry Smith         {0.,        0.,        .5  }, /* O  */
4109bee3fc89SBarry Smith         {1.,        1.,        .5  }, /* P  */
4110bee3fc89SBarry Smith         {gamma,     1 - gamma, .5  }, /* Q  */
4111bee3fc89SBarry Smith         {1 + gamma, gamma,     .5  }, /* R  */
4112bee3fc89SBarry Smith         {2 - gamma, 1 + gamma, .5  }, /* S  */
4113bee3fc89SBarry Smith         {1 - gamma, 2 - gamma, .5  }, /* T  */
4114b7f5c055SJed Brown 
4115bee3fc89SBarry Smith         {0.,        .5,        .75 }, /* U  */
4116bee3fc89SBarry Smith         {0.,        1.5,       .75 }, /* V  */
4117bee3fc89SBarry Smith         {1.,        .5,        .75 }, /* W  */
4118bee3fc89SBarry Smith         {1.,        1.5,       .75 }, /* X  */
4119bee3fc89SBarry Smith         {.5,        .75,       .75 }, /* Y  */
4120bee3fc89SBarry Smith         {.5,        1.75,      .75 }, /* Z  */
4121bee3fc89SBarry Smith         {1.5,       .25,       .75 }, /* Ap */
4122bee3fc89SBarry Smith         {1.5,       1.25,      .75 }, /* Bp */
4123b7f5c055SJed Brown 
4124bee3fc89SBarry Smith         {1.,        0.,        1.  }, /* Cp */
4125bee3fc89SBarry Smith         {0.,        1.,        1.  }, /* Dp */
4126bee3fc89SBarry Smith         {1 - gamma, 1 - gamma, 1.  }, /* Ep */
4127bee3fc89SBarry Smith         {1 + gamma, 1 + gamma, 1.  }, /* Fp */
4128bee3fc89SBarry Smith         {2 - gamma, gamma,     1.  }, /* Gp */
4129bee3fc89SBarry Smith         {gamma,     2 - gamma, 1.  }, /* Hp */
4130b7f5c055SJed Brown 
4131bee3fc89SBarry Smith         {.5,        0.,        1.25}, /* Ip */
4132bee3fc89SBarry Smith         {1.5,       0.,        1.25}, /* Jp */
4133bee3fc89SBarry Smith         {.5,        1.,        1.25}, /* Kp */
4134bee3fc89SBarry Smith         {1.5,       1.,        1.25}, /* Lp */
4135bee3fc89SBarry Smith         {.75,       .5,        1.25}, /* Mp */
4136bee3fc89SBarry Smith         {1.75,      .5,        1.25}, /* Np */
4137bee3fc89SBarry Smith         {.25,       1.5,       1.25}, /* Op */
4138bee3fc89SBarry Smith         {1.25,      1.5,       1.25}, /* Pp */
4139b7f5c055SJed Brown 
4140bee3fc89SBarry Smith         {0.,        0.,        1.5 }, /* Qp */
4141bee3fc89SBarry Smith         {1.,        1.,        1.5 }, /* Rp */
4142bee3fc89SBarry Smith         {1 - gamma, gamma,     1.5 }, /* Sp */
4143bee3fc89SBarry Smith         {2 - gamma, 1 - gamma, 1.5 }, /* Tp */
4144bee3fc89SBarry Smith         {1 + gamma, 2 - gamma, 1.5 }, /* Up */
4145bee3fc89SBarry Smith         {gamma,     1 + gamma, 1.5 }, /* Vp */
4146b7f5c055SJed Brown 
4147bee3fc89SBarry Smith         {0.,        .5,        1.75}, /* Wp */
4148bee3fc89SBarry Smith         {0.,        1.5,       1.75}, /* Xp */
4149bee3fc89SBarry Smith         {1.,        .5,        1.75}, /* Yp */
4150bee3fc89SBarry Smith         {1.,        1.5,       1.75}, /* Zp */
4151bee3fc89SBarry Smith         {.5,        .25,       1.75}, /* Aq */
4152bee3fc89SBarry Smith         {.5,        1.25,      1.75}, /* Bq */
4153bee3fc89SBarry Smith         {1.5,       .75,       1.75}, /* Cq */
4154bee3fc89SBarry Smith         {1.5,       1.75,      1.75}, /* Dq */
4155b7f5c055SJed Brown       };
4156b7f5c055SJed Brown       PetscInt (*cells)[64][4] = NULL;
4157b7f5c055SJed Brown       PetscBool *seen;
4158b7f5c055SJed Brown       PetscInt  *vertToTrueVert;
4159b7f5c055SJed Brown       PetscInt   count;
4160b7f5c055SJed Brown 
4161b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1;
4162b7f5c055SJed Brown       numBlocks = 1;
4163b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i];
4164b7f5c055SJed Brown       numBlocksPlus = 1;
4165b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i];
4166b7f5c055SJed Brown       numFaces = numBlocks * facesPerBlock;
41679566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocks, &cells));
41689566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen));
4169b7f5c055SJed Brown       for (PetscInt k = 0; k < extent[2]; k++) {
4170b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
4171b7f5c055SJed Brown           for (PetscInt i = 0; i < extent[0]; i++) {
4172b7f5c055SJed Brown             for (PetscInt f = 0; f < facesPerBlock; f++) {
4173b7f5c055SJed Brown               for (PetscInt v = 0; v < 4; v++) {
4174b7f5c055SJed Brown                 PetscInt vertRaw     = pattern[f][v];
4175b7f5c055SJed Brown                 PetscInt blockidx    = vertRaw / 56;
4176b7f5c055SJed Brown                 PetscInt patternvert = vertRaw % 56;
4177b7f5c055SJed Brown                 PetscInt xplus       = (blockidx & 1);
4178b7f5c055SJed Brown                 PetscInt yplus       = (blockidx & 2) >> 1;
4179b7f5c055SJed Brown                 PetscInt zplus       = (blockidx & 4) >> 2;
4180b7f5c055SJed Brown                 PetscInt zcoord      = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus);
4181b7f5c055SJed Brown                 PetscInt ycoord      = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus);
4182b7f5c055SJed Brown                 PetscInt xcoord      = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus);
4183b7f5c055SJed Brown                 PetscInt vert        = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert;
4184b7f5c055SJed Brown 
4185b7f5c055SJed Brown                 cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert;
4186b7f5c055SJed Brown                 seen[vert]                                       = PETSC_TRUE;
4187b7f5c055SJed Brown               }
4188b7f5c055SJed Brown             }
4189b7f5c055SJed Brown           }
4190b7f5c055SJed Brown         }
4191b7f5c055SJed Brown       }
41929371c9d4SSatish Balay       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++)
41939371c9d4SSatish Balay         if (seen[i]) numVertices++;
4194b7f5c055SJed Brown       count = 0;
41959566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert));
41969566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords));
4197b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1;
4198b7f5c055SJed Brown       for (PetscInt k = 0; k < extentPlus[2]; k++) {
4199b7f5c055SJed Brown         for (PetscInt j = 0; j < extentPlus[1]; j++) {
4200b7f5c055SJed Brown           for (PetscInt i = 0; i < extentPlus[0]; i++) {
4201b7f5c055SJed Brown             for (PetscInt v = 0; v < vertsPerBlock; v++) {
4202b7f5c055SJed Brown               PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v;
4203b7f5c055SJed Brown 
4204b7f5c055SJed Brown               if (seen[vIdx]) {
4205b7f5c055SJed Brown                 PetscInt thisVert;
4206b7f5c055SJed Brown 
4207b7f5c055SJed Brown                 vertToTrueVert[vIdx] = thisVert = count++;
4208b7f5c055SJed Brown 
4209b7f5c055SJed Brown                 for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d];
4210b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 0] += i * 2;
4211b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 1] += j * 2;
4212b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 2] += k * 2;
4213b7f5c055SJed Brown               }
4214b7f5c055SJed Brown             }
4215b7f5c055SJed Brown           }
4216b7f5c055SJed Brown         }
4217b7f5c055SJed Brown       }
4218b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocks; i++) {
4219b7f5c055SJed Brown         for (PetscInt f = 0; f < facesPerBlock; f++) {
4220ad540459SPierre Jolivet           for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]];
4221b7f5c055SJed Brown         }
4222b7f5c055SJed Brown       }
42239566063dSJacob Faibussowitsch       PetscCall(PetscFree(vertToTrueVert));
42249566063dSJacob Faibussowitsch       PetscCall(PetscFree(seen));
4225b7f5c055SJed Brown       cells_flat = cells[0][0];
4226b7f5c055SJed Brown       numEdges   = 0;
4227b7f5c055SJed Brown       for (PetscInt i = 0; i < numFaces; i++) {
4228b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
4229b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
4230b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
4231b7f5c055SJed Brown 
4232b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
4233b7f5c055SJed Brown             if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) {
4234b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++;
4235b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++;
4236b7f5c055SJed Brown             }
4237b7f5c055SJed Brown           }
4238b7f5c055SJed Brown         }
4239b7f5c055SJed Brown       }
42409566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edges));
42419566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edgeSets));
4242b7f5c055SJed Brown       for (PetscInt edge = 0, i = 0; i < numFaces; i++) {
4243b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
4244b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
4245b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
4246b7f5c055SJed Brown 
4247b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
4248b7f5c055SJed Brown             if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) {
4249b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) {
4250b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
4251b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
4252b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d;
4253b7f5c055SJed Brown               }
4254b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) {
4255b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
4256b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
4257b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d + 1;
4258b7f5c055SJed Brown               }
4259b7f5c055SJed Brown             }
4260b7f5c055SJed Brown           }
4261b7f5c055SJed Brown         }
4262b7f5c055SJed Brown       }
4263b7f5c055SJed Brown     }
4264b7f5c055SJed Brown     evalFunc   = TPSEvaluate_Gyroid;
42654663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_Gyroid;
4266b7f5c055SJed Brown     break;
4267b7f5c055SJed Brown   }
4268b7f5c055SJed Brown 
42699566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, topoDim));
4270c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat));
42719566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL));
42729566063dSJacob Faibussowitsch   PetscCall(PetscFree(cells_flat));
4273b7f5c055SJed Brown   {
4274b7f5c055SJed Brown     DM idm;
42759566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
427669d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &idm));
4277b7f5c055SJed Brown   }
4278c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords));
42799566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL));
42809566063dSJacob Faibussowitsch   PetscCall(PetscFree(vtxCoords));
4281b7f5c055SJed Brown 
42829566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
42839566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
4284b7f5c055SJed Brown   for (PetscInt e = 0; e < numEdges; e++) {
4285b7f5c055SJed Brown     PetscInt        njoin;
4286b7f5c055SJed Brown     const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]};
42879566063dSJacob Faibussowitsch     PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join));
428863a3b9bcSJacob 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]);
42899566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(label, join[0], edgeSets[e]));
42909566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join));
4291b7f5c055SJed Brown   }
42929566063dSJacob Faibussowitsch   PetscCall(PetscFree(edges));
42939566063dSJacob Faibussowitsch   PetscCall(PetscFree(edgeSets));
42941436d7faSJed Brown   if (tps_distribute) {
42951436d7faSJed Brown     DM               pdm = NULL;
42961436d7faSJed Brown     PetscPartitioner part;
42971436d7faSJed Brown 
42989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
42999566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
43009566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm));
430148a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
43021436d7faSJed Brown     // Do not auto-distribute again
43039566063dSJacob Faibussowitsch     PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
43041436d7faSJed Brown   }
4305b7f5c055SJed Brown 
43069566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
4307b7f5c055SJed Brown   for (PetscInt refine = 0; refine < refinements; refine++) {
4308b7f5c055SJed Brown     PetscInt     m;
4309f1d4225fSZach Atkins     DM           dmf, cdm, cdmf;
4310b7f5c055SJed Brown     Vec          X;
4311b7f5c055SJed Brown     PetscScalar *x;
4312f1d4225fSZach Atkins 
43139566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf));
4314f1d4225fSZach Atkins     PetscCall(DMGetCoordinateDM(dm, &cdm));
4315f1d4225fSZach Atkins     PetscCall(DMGetCoordinateDM(dmf, &cdmf));
4316f1d4225fSZach Atkins     PetscCall(DMCopyDisc(cdm, cdmf));
431769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmf));
4318b7f5c055SJed Brown 
43199566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &X));
43209566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(X, &m));
43219566063dSJacob Faibussowitsch     PetscCall(VecGetArray(X, &x));
432248a46eb9SPierre Jolivet     for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i]));
43239566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(X, &x));
4324b7f5c055SJed Brown   }
4325b7f5c055SJed Brown 
4326b7f5c055SJed Brown   // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices.
43279566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
43289566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, label));
4329b7f5c055SJed Brown 
433046139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
433146139095SJed Brown 
4332b7f5c055SJed Brown   if (thickness > 0) {
43334663dae6SJed Brown     DM              edm, cdm, ecdm;
43344663dae6SJed Brown     DMPlexTransform tr;
43354663dae6SJed Brown     const char     *prefix;
43364663dae6SJed Brown     PetscOptions    options;
43374663dae6SJed Brown     // Code from DMPlexExtrude
43384663dae6SJed Brown     PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr));
43394663dae6SJed Brown     PetscCall(DMPlexTransformSetDM(tr, dm));
4340ce78bad3SBarry Smith     PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDETYPE));
43414663dae6SJed Brown     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
43424663dae6SJed Brown     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix));
43434663dae6SJed Brown     PetscCall(PetscObjectGetOptions((PetscObject)dm, &options));
43444663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, options));
43454663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers));
43464663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness));
43474663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE));
43484663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE));
43494663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc));
43504663dae6SJed Brown     PetscCall(DMPlexTransformSetFromOptions(tr));
43514663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL));
43524663dae6SJed Brown     PetscCall(DMPlexTransformSetUp(tr));
43534663dae6SJed Brown     PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view"));
43544663dae6SJed Brown     PetscCall(DMPlexTransformApply(tr, dm, &edm));
43554663dae6SJed Brown     PetscCall(DMCopyDisc(dm, edm));
43564663dae6SJed Brown     PetscCall(DMGetCoordinateDM(dm, &cdm));
43574663dae6SJed Brown     PetscCall(DMGetCoordinateDM(edm, &ecdm));
43584663dae6SJed Brown     PetscCall(DMCopyDisc(cdm, ecdm));
43594663dae6SJed Brown     PetscCall(DMPlexTransformCreateDiscLabels(tr, edm));
43604663dae6SJed Brown     PetscCall(DMPlexTransformDestroy(&tr));
4361a77a5016SMatthew G. Knepley     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, edm));
436269d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
4363b7f5c055SJed Brown   }
43643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4365b7f5c055SJed Brown }
4366b7f5c055SJed Brown 
4367b7f5c055SJed Brown /*@
4368b7f5c055SJed Brown   DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface
4369b7f5c055SJed Brown 
4370b7f5c055SJed Brown   Collective
4371b7f5c055SJed Brown 
4372b7f5c055SJed Brown   Input Parameters:
4373a1cb98faSBarry Smith + comm           - The communicator for the `DM` object
4374b7f5c055SJed Brown . tpstype        - Type of triply-periodic surface
4375b7f5c055SJed Brown . extent         - Array of length 3 containing number of periods in each direction
437620f4b53cSBarry Smith . periodic       - array of length 3 with periodicity, or `NULL` for non-periodic
43771436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable)
4378817da375SSatish Balay . refinements    - Number of factor-of-2 refinements of 2D manifold mesh
43791436d7faSJed Brown . layers         - Number of cell layers extruded in normal direction
4380817da375SSatish Balay - thickness      - Thickness in normal direction
4381b7f5c055SJed Brown 
4382b7f5c055SJed Brown   Output Parameter:
4383a1cb98faSBarry Smith . dm - The `DM` object
4384a1cb98faSBarry Smith 
4385a1cb98faSBarry Smith   Level: beginner
4386b7f5c055SJed Brown 
4387b7f5c055SJed Brown   Notes:
438815229ffcSPierre Jolivet   This meshes the surface of the Schwarz P or Gyroid surfaces.  Schwarz P is the simplest member of the triply-periodic minimal surfaces.
43891d27aa22SBarry Smith   <https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22)> and can be cut with "clean" boundaries.
43901d27aa22SBarry 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.
4391b7f5c055SJed Brown   Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested.
4392b7f5c055SJed Brown   On each refinement, all vertices are projected to their nearest point on the surface.
4393b7f5c055SJed Brown   This projection could readily be extended to related surfaces.
4394b7f5c055SJed Brown 
43951d27aa22SBarry Smith   See {cite}`maskery2018insights`
43961d27aa22SBarry Smith 
43971d27aa22SBarry Smith   The face (edge) sets for the Schwarz P surface are numbered $1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z)$.
43981d27aa22SBarry Smith   When the mesh is refined, "Face Sets" contain the new vertices (created during refinement).
43991d27aa22SBarry Smith   Use `DMPlexLabelComplete()` to propagate to coarse-level vertices.
4400b7f5c055SJed Brown 
440160225df5SJacob Faibussowitsch   Developer Notes:
4402b7f5c055SJed Brown   The Gyroid mesh does not currently mark boundary sets.
4403b7f5c055SJed Brown 
44041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()`
4405b7f5c055SJed Brown @*/
4406d71ae5a4SJacob 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)
4407d71ae5a4SJacob Faibussowitsch {
4408b7f5c055SJed Brown   PetscFunctionBegin;
44099566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
44109566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
44119566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness));
44123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4413b7f5c055SJed Brown }
4414b7f5c055SJed Brown 
44159318fe57SMatthew G. Knepley /*@
44169318fe57SMatthew G. Knepley   DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d.
44179318fe57SMatthew G. Knepley 
44189318fe57SMatthew G. Knepley   Collective
44199318fe57SMatthew G. Knepley 
44209318fe57SMatthew G. Knepley   Input Parameters:
4421a1cb98faSBarry Smith + comm    - The communicator for the `DM` object
44229318fe57SMatthew G. Knepley . dim     - The dimension
44239318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells
44249318fe57SMatthew G. Knepley - R       - The radius
44259318fe57SMatthew G. Knepley 
44269318fe57SMatthew G. Knepley   Output Parameter:
4427a1cb98faSBarry Smith . dm - The `DM` object
44289318fe57SMatthew G. Knepley 
44299318fe57SMatthew G. Knepley   Level: beginner
44309318fe57SMatthew G. Knepley 
44311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
44329318fe57SMatthew G. Knepley @*/
4433d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm)
4434d71ae5a4SJacob Faibussowitsch {
44359318fe57SMatthew G. Knepley   PetscFunctionBegin;
44364f572ea9SToby Isaac   PetscAssertPointer(dm, 5);
44379566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
44389566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
44399566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R));
44403ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44419318fe57SMatthew G. Knepley }
44429318fe57SMatthew G. Knepley 
4443d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R)
4444d71ae5a4SJacob Faibussowitsch {
44459318fe57SMatthew G. Knepley   DM          sdm, vol;
44469318fe57SMatthew G. Knepley   DMLabel     bdlabel;
4447dd2b43ebSStefano Zampini   const char *prefix;
44489318fe57SMatthew G. Knepley 
44499318fe57SMatthew G. Knepley   PetscFunctionBegin;
44509566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm));
44519566063dSJacob Faibussowitsch   PetscCall(DMSetType(sdm, DMPLEX));
4452dd2b43ebSStefano Zampini   PetscCall(DMGetOptionsPrefix(dm, &prefix));
4453dd2b43ebSStefano Zampini   PetscCall(DMSetOptionsPrefix(sdm, prefix));
4454dd2b43ebSStefano Zampini   PetscCall(DMAppendOptionsPrefix(sdm, "bd_"));
4455dd2b43ebSStefano Zampini   PetscCall(DMPlexDistributeSetDefault(sdm, PETSC_FALSE));
44569566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R));
44579566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(sdm));
44589566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view"));
44599566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol));
44609566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&sdm));
446169d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
44629566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
44639566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
44649566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
44659566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, bdlabel));
44663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
446751a74b61SMatthew G. Knepley }
446851a74b61SMatthew G. Knepley 
446951a74b61SMatthew G. Knepley /*@
447051a74b61SMatthew G. Knepley   DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d.
447151a74b61SMatthew G. Knepley 
447251a74b61SMatthew G. Knepley   Collective
447351a74b61SMatthew G. Knepley 
447451a74b61SMatthew G. Knepley   Input Parameters:
4475a1cb98faSBarry Smith + comm - The communicator for the `DM` object
447651a74b61SMatthew G. Knepley . dim  - The dimension
447751a74b61SMatthew G. Knepley - R    - The radius
447851a74b61SMatthew G. Knepley 
447951a74b61SMatthew G. Knepley   Output Parameter:
4480a1cb98faSBarry Smith . dm - The `DM` object
448151a74b61SMatthew G. Knepley 
4482a1cb98faSBarry Smith   Options Database Key:
448360225df5SJacob Faibussowitsch . bd_dm_refine - This will refine the surface mesh preserving the sphere geometry
448451a74b61SMatthew G. Knepley 
448551a74b61SMatthew G. Knepley   Level: beginner
448651a74b61SMatthew G. Knepley 
44871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
448851a74b61SMatthew G. Knepley @*/
4489d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm)
4490d71ae5a4SJacob Faibussowitsch {
449151a74b61SMatthew G. Knepley   PetscFunctionBegin;
44929566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
44939566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
44949566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R));
44953ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44962829fed8SMatthew G. Knepley }
44972829fed8SMatthew G. Knepley 
4498d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct)
4499d71ae5a4SJacob Faibussowitsch {
45000a6ba040SMatthew G. Knepley   PetscFunctionBegin;
45019318fe57SMatthew G. Knepley   switch (ct) {
45029371c9d4SSatish Balay   case DM_POLYTOPE_POINT: {
45039318fe57SMatthew G. Knepley     PetscInt    numPoints[1]        = {1};
45049318fe57SMatthew G. Knepley     PetscInt    coneSize[1]         = {0};
45059318fe57SMatthew G. Knepley     PetscInt    cones[1]            = {0};
45069318fe57SMatthew G. Knepley     PetscInt    coneOrientations[1] = {0};
45079318fe57SMatthew G. Knepley     PetscScalar vertexCoords[1]     = {0.0};
45089318fe57SMatthew G. Knepley 
45099566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 0));
45109566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45119371c9d4SSatish Balay   } break;
45129371c9d4SSatish Balay   case DM_POLYTOPE_SEGMENT: {
45139318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
45149318fe57SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
45159318fe57SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
45169318fe57SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
45179318fe57SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
45189318fe57SMatthew G. Knepley 
45199566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
45209566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45219371c9d4SSatish Balay   } break;
45229371c9d4SSatish Balay   case DM_POLYTOPE_POINT_PRISM_TENSOR: {
4523b5a892a1SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
4524b5a892a1SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
4525b5a892a1SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
4526b5a892a1SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
4527b5a892a1SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
4528b5a892a1SMatthew G. Knepley 
45299566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
45309566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45319371c9d4SSatish Balay   } break;
45329371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
45339318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {3, 1};
45349318fe57SMatthew G. Knepley     PetscInt    coneSize[4]         = {3, 0, 0, 0};
45359318fe57SMatthew G. Knepley     PetscInt    cones[3]            = {1, 2, 3};
45369318fe57SMatthew G. Knepley     PetscInt    coneOrientations[3] = {0, 0, 0};
45379318fe57SMatthew G. Knepley     PetscScalar vertexCoords[6]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0};
45389318fe57SMatthew G. Knepley 
45399566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
45409566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45419371c9d4SSatish Balay   } break;
45429371c9d4SSatish Balay   case DM_POLYTOPE_QUADRILATERAL: {
45439318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
45449318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
45459318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
45469318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
45479318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0};
45489318fe57SMatthew G. Knepley 
45499566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
45509566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45519371c9d4SSatish Balay   } break;
45529371c9d4SSatish Balay   case DM_POLYTOPE_SEG_PRISM_TENSOR: {
45539318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
45549318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
45559318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
45569318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
45579318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0};
45589318fe57SMatthew G. Knepley 
45599566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
45609566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45619371c9d4SSatish Balay   } break;
45629371c9d4SSatish Balay   case DM_POLYTOPE_TETRAHEDRON: {
45639318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
45649318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
4565f0edb160SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
45669318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
4567f0edb160SMatthew 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};
45689318fe57SMatthew G. Knepley 
45699566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
45709566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45719371c9d4SSatish Balay   } break;
45729371c9d4SSatish Balay   case DM_POLYTOPE_HEXAHEDRON: {
45739318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
45749318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
4575f0edb160SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
45769318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
45779371c9d4SSatish 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};
45789318fe57SMatthew G. Knepley 
45799566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
45809566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45819371c9d4SSatish Balay   } break;
45829371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM: {
45839318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
45849318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
4585f0edb160SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
45869318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
45879371c9d4SSatish 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};
45889318fe57SMatthew G. Knepley 
45899566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
45909566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45919371c9d4SSatish Balay   } break;
45929371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM_TENSOR: {
45939318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
45949318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
45959318fe57SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
45969318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
45979371c9d4SSatish 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};
45989318fe57SMatthew G. Knepley 
45999566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
46009566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
46019371c9d4SSatish Balay   } break;
46029371c9d4SSatish Balay   case DM_POLYTOPE_QUAD_PRISM_TENSOR: {
46039318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
46049318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
46059318fe57SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
46069318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
46079371c9d4SSatish 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};
46089318fe57SMatthew G. Knepley 
46099566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
46109566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
46119371c9d4SSatish Balay   } break;
46129371c9d4SSatish Balay   case DM_POLYTOPE_PYRAMID: {
46139318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {5, 1};
46149318fe57SMatthew G. Knepley     PetscInt    coneSize[6]         = {5, 0, 0, 0, 0, 0};
4615f0edb160SMatthew G. Knepley     PetscInt    cones[5]            = {1, 2, 3, 4, 5};
46169318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
46179371c9d4SSatish 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};
46189318fe57SMatthew G. Knepley 
46199566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
46209566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
46219371c9d4SSatish Balay   } break;
4622d71ae5a4SJacob Faibussowitsch   default:
4623d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]);
46249318fe57SMatthew G. Knepley   }
46259318fe57SMatthew G. Knepley   {
46269318fe57SMatthew G. Knepley     PetscInt Nv, v;
46279318fe57SMatthew G. Knepley 
46289318fe57SMatthew G. Knepley     /* Must create the celltype label here so that we do not automatically try to compute the types */
46299566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(rdm, "celltype"));
46309566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(rdm, 0, ct));
46319566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(rdm, NULL, &Nv));
46329566063dSJacob Faibussowitsch     for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT));
46339318fe57SMatthew G. Knepley   }
46349566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(rdm));
46359566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct]));
46363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46370a6ba040SMatthew G. Knepley }
46380a6ba040SMatthew G. Knepley 
46399318fe57SMatthew G. Knepley /*@
4640a1cb98faSBarry Smith   DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell
46419318fe57SMatthew G. Knepley 
46429318fe57SMatthew G. Knepley   Collective
46439318fe57SMatthew G. Knepley 
46449318fe57SMatthew G. Knepley   Input Parameters:
46459318fe57SMatthew G. Knepley + comm - The communicator
46469318fe57SMatthew G. Knepley - ct   - The cell type of the reference cell
46479318fe57SMatthew G. Knepley 
46489318fe57SMatthew G. Knepley   Output Parameter:
46499318fe57SMatthew G. Knepley . refdm - The reference cell
46509318fe57SMatthew G. Knepley 
46519318fe57SMatthew G. Knepley   Level: intermediate
46529318fe57SMatthew G. Knepley 
465342747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`
46549318fe57SMatthew G. Knepley @*/
4655d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm)
4656d71ae5a4SJacob Faibussowitsch {
46570a6ba040SMatthew G. Knepley   PetscFunctionBegin;
46589566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, refdm));
46599566063dSJacob Faibussowitsch   PetscCall(DMSetType(*refdm, DMPLEX));
46609566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct));
46613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46629318fe57SMatthew G. Knepley }
466379a015ccSMatthew G. Knepley 
4664d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[])
4665d71ae5a4SJacob Faibussowitsch {
46669318fe57SMatthew G. Knepley   DM        plex;
46679318fe57SMatthew G. Knepley   DMLabel   label;
46689318fe57SMatthew G. Knepley   PetscBool hasLabel;
46690a6ba040SMatthew G. Knepley 
4670c22d3578SMatthew G. Knepley   PetscFunctionBegin;
46719566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &hasLabel));
46723ba16761SJacob Faibussowitsch   if (hasLabel) PetscFunctionReturn(PETSC_SUCCESS);
46739566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, name));
46749566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
46759566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
46769566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label));
46771c8afea9SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(plex, label));
46789566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
46793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46809318fe57SMatthew G. Knepley }
4681acdc6f61SToby Isaac 
4682669647acSMatthew G. Knepley /*
4683669647acSMatthew 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.
4684669647acSMatthew G. Knepley 
4685669647acSMatthew G. Knepley     (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0]))
4686669647acSMatthew G. Knepley */
4687d71ae5a4SJacob 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[])
4688d71ae5a4SJacob Faibussowitsch {
4689669647acSMatthew G. Knepley   const PetscReal low = PetscRealPart(constants[0]);
4690669647acSMatthew G. Knepley   const PetscReal upp = PetscRealPart(constants[1]);
4691669647acSMatthew G. Knepley   const PetscReal r   = PetscRealPart(u[1]);
4692669647acSMatthew G. Knepley   const PetscReal th  = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low);
4693669647acSMatthew G. Knepley 
4694669647acSMatthew G. Knepley   f0[0] = r * PetscCosReal(th);
4695669647acSMatthew G. Knepley   f0[1] = r * PetscSinReal(th);
4696669647acSMatthew G. Knepley }
4697669647acSMatthew G. Knepley 
46985390be7dSMatthew G. Knepley // Insert vertices and their joins, marked by depth
46995390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Vertices(DM dm, DMLabel label, DMLabel vlabel, PetscInt val, PetscInt n, const PetscInt vertices[])
47005390be7dSMatthew G. Knepley {
47015390be7dSMatthew G. Knepley   PetscFunctionBegin;
47025390be7dSMatthew G. Knepley   PetscCall(DMPlexMarkSubmesh_Interpolated(dm, vlabel, val, PETSC_FALSE, PETSC_FALSE, label, NULL));
47035390be7dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
47045390be7dSMatthew G. Knepley }
47055390be7dSMatthew G. Knepley 
47065390be7dSMatthew G. Knepley // Insert faces and their closures, marked by depth
47075390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Faces(DM dm, DMLabel label, PetscInt n, const PetscInt faces[])
47085390be7dSMatthew G. Knepley {
47095390be7dSMatthew G. Knepley   PetscFunctionBegin;
47105390be7dSMatthew G. Knepley   for (PetscInt p = 0; p < n; ++p) {
47115390be7dSMatthew G. Knepley     const PetscInt point   = faces[p];
47125390be7dSMatthew G. Knepley     PetscInt      *closure = NULL;
47135390be7dSMatthew G. Knepley     PetscInt       clSize, pdepth;
47145390be7dSMatthew G. Knepley 
47155390be7dSMatthew G. Knepley     PetscCall(DMPlexGetPointDepth(dm, point, &pdepth));
47165390be7dSMatthew G. Knepley     PetscCall(DMLabelSetValue(label, point, pdepth));
47175390be7dSMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure));
47185390be7dSMatthew G. Knepley     for (PetscInt cl = 0; cl < clSize * 2; cl += 2) {
47195390be7dSMatthew G. Knepley       PetscCall(DMPlexGetPointDepth(dm, closure[cl], &pdepth));
47205390be7dSMatthew G. Knepley       PetscCall(DMLabelSetValue(label, closure[cl], pdepth));
47215390be7dSMatthew G. Knepley     }
47225390be7dSMatthew G. Knepley     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure));
47235390be7dSMatthew G. Knepley   }
47245390be7dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
47255390be7dSMatthew G. Knepley }
47265390be7dSMatthew G. Knepley 
47274e22dd4cSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *flg);
47284e22dd4cSMatthew G. Knepley 
47295dca41c3SJed Brown const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "zbox", "unknown", "DMPlexShape", "DM_SHAPE_", NULL};
47309318fe57SMatthew G. Knepley 
4731ce78bad3SBarry Smith static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems PetscOptionsObject, PetscBool *useCoordSpace, DM dm)
4732d71ae5a4SJacob Faibussowitsch {
47339318fe57SMatthew G. Knepley   DMPlexShape    shape   = DM_SHAPE_BOX;
47349318fe57SMatthew G. Knepley   DMPolytopeType cell    = DM_POLYTOPE_TRIANGLE;
47359318fe57SMatthew G. Knepley   PetscInt       dim     = 2;
4736b9da1bb3SMatthew G. Knepley   PetscBool      simplex = PETSC_TRUE, interpolate = PETSC_TRUE, orient = PETSC_FALSE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE;
4737d0812dedSMatthew G. Knepley   PetscBool      flg, flg2, fflg, strflg, bdfflg, nameflg;
47389318fe57SMatthew G. Knepley   MPI_Comm       comm;
4739ed5e4e85SVaclav Hapla   char           filename[PETSC_MAX_PATH_LEN]   = "<unspecified>";
4740ed5e4e85SVaclav Hapla   char           bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>";
4741ed5e4e85SVaclav Hapla   char           plexname[PETSC_MAX_PATH_LEN]   = "";
47424e22dd4cSMatthew G. Knepley   const char    *option;
47439318fe57SMatthew G. Knepley 
47449318fe57SMatthew G. Knepley   PetscFunctionBegin;
4745708be2fdSJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromOptions, dm, 0, 0, 0));
47469566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
47479318fe57SMatthew G. Knepley   /* TODO Turn this into a registration interface */
47489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg));
4749d0812dedSMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_plex_file_contents", "Contents of a file format in a string", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &strflg));
47509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg));
47519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg));
47529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL));
47539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL));
47549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg));
47559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0));
47569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg));
47579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg));
4758b9da1bb3SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_orient", "Orient the constructed mesh", "DMPlexOrient", orient, &orient, &flg));
47599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg));
47609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2));
47619566063dSJacob Faibussowitsch   if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure));
47623f3e541fSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_adj", "Debug output level all adjacency computations", "", 0, &((DM_Plex *)dm->data)->printAdj, NULL, 0));
47639318fe57SMatthew G. Knepley 
476461a622f3SMatthew G. Knepley   switch (cell) {
476561a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT:
476661a622f3SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
476761a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
476861a622f3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
476961a622f3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
477061a622f3SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
4771d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_HEXAHEDRON:
4772d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_TRUE;
4773d71ae5a4SJacob Faibussowitsch     break;
4774d71ae5a4SJacob Faibussowitsch   default:
4775d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_FALSE;
4776d71ae5a4SJacob Faibussowitsch     break;
477761a622f3SMatthew G. Knepley   }
477861a622f3SMatthew G. Knepley 
47799318fe57SMatthew G. Knepley   if (fflg) {
47809318fe57SMatthew G. Knepley     DM          dmnew;
47811e4a82c4SMatthew G. Knepley     const char *name;
47829318fe57SMatthew G. Knepley 
47831e4a82c4SMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
47841e4a82c4SMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, nameflg ? plexname : name, interpolate, &dmnew));
47855de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
478669d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
47879318fe57SMatthew G. Knepley   } else if (refDomain) {
47889566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell));
47899318fe57SMatthew G. Knepley   } else if (bdfflg) {
47909318fe57SMatthew G. Knepley     DM          bdm, dmnew;
47911e4a82c4SMatthew G. Knepley     const char *name;
47929318fe57SMatthew G. Knepley 
47931e4a82c4SMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
47941e4a82c4SMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, nameflg ? plexname : name, interpolate, &bdm));
47959566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_"));
47969566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(bdm));
47979566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew));
47989566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&bdm));
47995de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
480069d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
4801d0812dedSMatthew G. Knepley   } else if (strflg) {
4802d0812dedSMatthew G. Knepley     DM          dmnew;
4803d0812dedSMatthew G. Knepley     PetscViewer viewer;
4804d0812dedSMatthew G. Knepley     const char *contents;
4805d0812dedSMatthew G. Knepley     char       *strname;
4806d0812dedSMatthew G. Knepley     char        tmpdir[PETSC_MAX_PATH_LEN];
4807d0812dedSMatthew G. Knepley     char        tmpfilename[PETSC_MAX_PATH_LEN];
4808d0812dedSMatthew G. Knepley     char        name[PETSC_MAX_PATH_LEN];
4809d0812dedSMatthew G. Knepley     MPI_Comm    comm;
4810d0812dedSMatthew G. Knepley     PetscMPIInt rank;
4811d0812dedSMatthew G. Knepley 
4812d0812dedSMatthew G. Knepley     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4813d0812dedSMatthew G. Knepley     PetscCallMPI(MPI_Comm_rank(comm, &rank));
4814d0812dedSMatthew G. Knepley     PetscCall(PetscStrchr(filename, ':', &strname));
4815d0812dedSMatthew G. Knepley     PetscCheck(strname, comm, PETSC_ERR_ARG_WRONG, "File contents must have the form \"ext:string_name\", not %s", filename);
4816d0812dedSMatthew G. Knepley     strname[0] = '\0';
4817d0812dedSMatthew G. Knepley     ++strname;
4818d0812dedSMatthew G. Knepley     PetscCall(PetscDLSym(NULL, strname, (void **)&contents));
4819d0812dedSMatthew G. Knepley     PetscCheck(contents, comm, PETSC_ERR_ARG_WRONG, "Could not locate mesh string %s", strname);
4820d0812dedSMatthew G. Knepley     PetscCall(PetscGetTmp(comm, tmpdir, PETSC_MAX_PATH_LEN));
4821ed32af8cSMatthew G. Knepley     PetscCall(PetscStrlcat(tmpdir, "/meshXXXXXX", PETSC_MAX_PATH_LEN));
4822ed32af8cSMatthew G. Knepley     PetscCall(PetscMkdtemp(tmpdir));
4823ed32af8cSMatthew G. Knepley     PetscCall(PetscSNPrintf(tmpfilename, PETSC_MAX_PATH_LEN, "%s/mesh.%s", tmpdir, filename));
4824d0812dedSMatthew G. Knepley     PetscCall(PetscViewerASCIIOpen(comm, tmpfilename, &viewer));
4825d0812dedSMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", contents));
4826d0812dedSMatthew G. Knepley     PetscCall(PetscViewerDestroy(&viewer));
4827d0812dedSMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), tmpfilename, plexname, interpolate, &dmnew));
4828ed32af8cSMatthew G. Knepley     PetscCall(PetscRMTree(tmpdir));
4829d0812dedSMatthew G. Knepley     PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%s Mesh", strname));
4830d0812dedSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, name));
4831d0812dedSMatthew G. Knepley     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
4832d0812dedSMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
48339318fe57SMatthew G. Knepley   } else {
48349566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape]));
48359318fe57SMatthew G. Knepley     switch (shape) {
4836669647acSMatthew G. Knepley     case DM_SHAPE_BOX:
48375dca41c3SJed Brown     case DM_SHAPE_ZBOX:
4838669647acSMatthew G. Knepley     case DM_SHAPE_ANNULUS: {
48399318fe57SMatthew G. Knepley       PetscInt       faces[3]  = {0, 0, 0};
48409318fe57SMatthew G. Knepley       PetscReal      lower[3]  = {0, 0, 0};
48419318fe57SMatthew G. Knepley       PetscReal      upper[3]  = {1, 1, 1};
48429318fe57SMatthew G. Knepley       DMBoundaryType bdt[3]    = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
4843669647acSMatthew G. Knepley       PetscBool      isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE;
48449318fe57SMatthew G. Knepley       PetscInt       i, n;
48459318fe57SMatthew G. Knepley 
48469318fe57SMatthew G. Knepley       n = dim;
48479318fe57SMatthew G. Knepley       for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim);
48489566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
48499318fe57SMatthew G. Knepley       n = 3;
48509566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
485163a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
48529318fe57SMatthew G. Knepley       n = 3;
48539566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
485463a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
48559318fe57SMatthew G. Knepley       n = 3;
48569566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
485763a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
4858669647acSMatthew G. Knepley 
4859669647acSMatthew G. Knepley       PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented");
4860669647acSMatthew G. Knepley       if (isAnnular)
4861669647acSMatthew G. Knepley         for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC;
4862669647acSMatthew G. Knepley 
48639318fe57SMatthew G. Knepley       switch (cell) {
486461a622f3SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
48659566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt));
4866d410b0cfSMatthew G. Knepley         if (!interpolate) {
4867d410b0cfSMatthew G. Knepley           DM udm;
4868d410b0cfSMatthew G. Knepley 
48699566063dSJacob Faibussowitsch           PetscCall(DMPlexUninterpolate(dm, &udm));
487069d8a87bSksagiyam           PetscCall(DMPlexReplace_Internal(dm, &udm));
4871d410b0cfSMatthew G. Knepley         }
48729318fe57SMatthew G. Knepley         break;
4873d71ae5a4SJacob Faibussowitsch       default:
48745dca41c3SJed Brown         PetscCall(DMPlexCreateBoxMesh_Internal(dm, shape, dim, simplex, faces, lower, upper, bdt, interpolate));
4875d71ae5a4SJacob Faibussowitsch         break;
48769318fe57SMatthew G. Knepley       }
4877669647acSMatthew G. Knepley       if (isAnnular) {
4878669647acSMatthew G. Knepley         DM          cdm;
4879669647acSMatthew G. Knepley         PetscDS     cds;
4880669647acSMatthew G. Knepley         PetscScalar bounds[2] = {lower[0], upper[0]};
4881669647acSMatthew G. Knepley 
4882669647acSMatthew G. Knepley         // Fix coordinates for annular region
4883669647acSMatthew G. Knepley         PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL));
4884669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinatesLocal(dm, NULL));
4885669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinates(dm, NULL));
4886*4c712d99Sksagiyam         PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE, NULL));
4887669647acSMatthew G. Knepley         PetscCall(DMGetCoordinateDM(dm, &cdm));
4888669647acSMatthew G. Knepley         PetscCall(DMGetDS(cdm, &cds));
4889669647acSMatthew G. Knepley         PetscCall(PetscDSSetConstants(cds, 2, bounds));
4890669647acSMatthew G. Knepley         PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus));
4891669647acSMatthew G. Knepley       }
48929371c9d4SSatish Balay     } break;
48939371c9d4SSatish Balay     case DM_SHAPE_BOX_SURFACE: {
48949318fe57SMatthew G. Knepley       PetscInt  faces[3] = {0, 0, 0};
48959318fe57SMatthew G. Knepley       PetscReal lower[3] = {0, 0, 0};
48969318fe57SMatthew G. Knepley       PetscReal upper[3] = {1, 1, 1};
48979318fe57SMatthew G. Knepley       PetscInt  i, n;
48989318fe57SMatthew G. Knepley 
48999318fe57SMatthew G. Knepley       n = dim + 1;
49009318fe57SMatthew G. Knepley       for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1));
49019566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
49029318fe57SMatthew G. Knepley       n = 3;
49039566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
490463a3b9bcSJacob 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);
49059318fe57SMatthew G. Knepley       n = 3;
49069566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
490763a3b9bcSJacob 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);
49089566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate));
49099371c9d4SSatish Balay     } break;
49109371c9d4SSatish Balay     case DM_SHAPE_SPHERE: {
49119318fe57SMatthew G. Knepley       PetscReal R = 1.0;
49129318fe57SMatthew G. Knepley 
49139566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg));
49149566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R));
49159371c9d4SSatish Balay     } break;
49169371c9d4SSatish Balay     case DM_SHAPE_BALL: {
49179318fe57SMatthew G. Knepley       PetscReal R = 1.0;
49189318fe57SMatthew G. Knepley 
49199566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg));
49209566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R));
49219371c9d4SSatish Balay     } break;
49229371c9d4SSatish Balay     case DM_SHAPE_CYLINDER: {
49239318fe57SMatthew G. Knepley       DMBoundaryType bdt = DM_BOUNDARY_NONE;
49249318fe57SMatthew G. Knepley       PetscInt       Nw  = 6;
492549704ca5SMatthew G. Knepley       PetscInt       Nr  = 0;
49269318fe57SMatthew G. Knepley 
49279566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL));
49289566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL));
492949704ca5SMatthew G. Knepley       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_refine", "Number of refinements before projection", "", Nr, &Nr, NULL));
49309318fe57SMatthew G. Knepley       switch (cell) {
4931d71ae5a4SJacob Faibussowitsch       case DM_POLYTOPE_TRI_PRISM_TENSOR:
4932d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate));
4933d71ae5a4SJacob Faibussowitsch         break;
4934d71ae5a4SJacob Faibussowitsch       default:
493549704ca5SMatthew G. Knepley         PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt, Nr));
4936d71ae5a4SJacob Faibussowitsch         break;
49379318fe57SMatthew G. Knepley       }
49389371c9d4SSatish Balay     } break;
4939b7f5c055SJed Brown     case DM_SHAPE_SCHWARZ_P: // fallthrough
49409371c9d4SSatish Balay     case DM_SHAPE_GYROID: {
4941b7f5c055SJed Brown       PetscInt       extent[3] = {1, 1, 1}, refine = 0, layers = 0, three;
4942b7f5c055SJed Brown       PetscReal      thickness   = 0.;
4943b7f5c055SJed Brown       DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
4944b7f5c055SJed Brown       DMPlexTPSType  tps_type    = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID;
49451436d7faSJed Brown       PetscBool      tps_distribute;
49469566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL));
49479566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL));
49489566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL));
49499566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL));
49509566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL));
49519566063dSJacob Faibussowitsch       PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute));
49529566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL));
49539566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness));
49549371c9d4SSatish Balay     } break;
49559371c9d4SSatish Balay     case DM_SHAPE_DOUBLET: {
495605bd46c0SStefano Zampini       DM        dmnew;
495705bd46c0SStefano Zampini       PetscReal rl = 0.0;
495805bd46c0SStefano Zampini 
495905bd46c0SStefano Zampini       PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL));
496005bd46c0SStefano Zampini       PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew));
49615de52c6dSVaclav Hapla       PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
496269d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &dmnew));
49639371c9d4SSatish Balay     } break;
4964cfb853baSMatthew G. Knepley     case DM_SHAPE_HYPERCUBIC: {
49658d2ec52aSSatish Balay       PetscInt       *edges, overlap = 1;
4966cfb853baSMatthew G. Knepley       PetscReal      *lower, *upper;
4967cfb853baSMatthew G. Knepley       DMBoundaryType *bdt;
4968cfb853baSMatthew G. Knepley       PetscInt        n, d;
4969cfb853baSMatthew G. Knepley 
4970cfb853baSMatthew G. Knepley       *useCoordSpace = PETSC_FALSE;
4971cfb853baSMatthew G. Knepley       PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt));
4972cfb853baSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
4973cfb853baSMatthew G. Knepley         edges[d] = 1;
4974cfb853baSMatthew G. Knepley         lower[d] = 0.;
4975cfb853baSMatthew G. Knepley         upper[d] = 1.;
4976cfb853baSMatthew G. Knepley         bdt[d]   = DM_BOUNDARY_PERIODIC;
4977cfb853baSMatthew G. Knepley       }
4978cfb853baSMatthew G. Knepley       n = dim;
4979cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg));
4980cfb853baSMatthew G. Knepley       n = dim;
4981cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
4982cfb853baSMatthew 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);
4983cfb853baSMatthew G. Knepley       n = dim;
4984cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
4985cfb853baSMatthew 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);
4986cfb853baSMatthew G. Knepley       n = dim;
4987cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
4988cfb853baSMatthew 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);
49898d2ec52aSSatish Balay       PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", overlap, &overlap, NULL, 0));
49908d2ec52aSSatish Balay       PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, overlap, bdt));
4991cfb853baSMatthew G. Knepley       PetscCall(PetscFree4(edges, lower, upper, bdt));
4992cfb853baSMatthew G. Knepley     } break;
4993d71ae5a4SJacob Faibussowitsch     default:
4994d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]);
49959318fe57SMatthew G. Knepley     }
49969318fe57SMatthew G. Knepley   }
49979566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
499848a46eb9SPierre Jolivet   if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname));
4999b9da1bb3SMatthew G. Knepley   if (orient) PetscCall(DMPlexOrient(dm));
50004e22dd4cSMatthew G. Knepley   // Allow label creation
50014e22dd4cSMatthew G. Knepley   PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_label_", &option, NULL, &flg));
50024e22dd4cSMatthew G. Knepley   if (flg) {
50034e22dd4cSMatthew G. Knepley     DMLabel     label;
50044e22dd4cSMatthew G. Knepley     PetscInt    points[1024], n = 1024;
50054e22dd4cSMatthew G. Knepley     char        fulloption[PETSC_MAX_PATH_LEN];
50064e22dd4cSMatthew G. Knepley     const char *name = &option[14];
50074e22dd4cSMatthew G. Knepley 
50084e22dd4cSMatthew G. Knepley     PetscCall(DMCreateLabel(dm, name));
50094e22dd4cSMatthew G. Knepley     PetscCall(DMGetLabel(dm, name, &label));
50104e22dd4cSMatthew G. Knepley     fulloption[0] = '-';
50114e22dd4cSMatthew G. Knepley     fulloption[1] = 0;
50124e22dd4cSMatthew G. Knepley     PetscCall(PetscStrlcat(fulloption, option, PETSC_MAX_PATH_LEN));
50134e22dd4cSMatthew G. Knepley     PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, NULL));
50144e22dd4cSMatthew G. Knepley     for (PetscInt p = 0; p < n; ++p) PetscCall(DMLabelSetValue(label, points[p], 1));
50154e22dd4cSMatthew G. Knepley   }
5016dd0eeac9SMatthew G. Knepley   // Allow cohesive label creation
5017dd0eeac9SMatthew G. Knepley   //   Faces are input, completed, and all points are marked with their depth
5018dd0eeac9SMatthew G. Knepley   PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_cohesive_label_", &option, NULL, &flg));
5019dd0eeac9SMatthew G. Knepley   if (flg) {
5020dd0eeac9SMatthew G. Knepley     DMLabel   label;
5021dd0eeac9SMatthew G. Knepley     PetscInt  points[1024], n, pStart, pEnd, Nl = 1;
50225390be7dSMatthew G. Knepley     PetscBool noCreate = PETSC_FALSE;
5023dd0eeac9SMatthew G. Knepley     char      fulloption[PETSC_MAX_PATH_LEN];
5024dd0eeac9SMatthew G. Knepley     char      name[PETSC_MAX_PATH_LEN];
5025dd0eeac9SMatthew G. Knepley     size_t    len;
5026dd0eeac9SMatthew G. Knepley 
5027dd0eeac9SMatthew G. Knepley     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
5028dd0eeac9SMatthew G. Knepley     PetscCall(PetscStrncpy(name, &option[23], PETSC_MAX_PATH_LEN));
5029dd0eeac9SMatthew G. Knepley     PetscCall(PetscStrlen(name, &len));
5030dd0eeac9SMatthew G. Knepley     if (name[len - 1] == '0') Nl = 10;
5031dd0eeac9SMatthew G. Knepley     for (PetscInt l = 0; l < Nl; ++l) {
50326497c311SBarry Smith       if (l > 0) name[len - 1] = (char)('0' + l);
5033dd0eeac9SMatthew G. Knepley       fulloption[0] = 0;
5034dd0eeac9SMatthew G. Knepley       PetscCall(PetscStrlcat(fulloption, "-dm_plex_cohesive_label_", 32));
5035dd0eeac9SMatthew G. Knepley       PetscCall(PetscStrlcat(fulloption, name, PETSC_MAX_PATH_LEN - 32));
5036dd0eeac9SMatthew G. Knepley       n = 1024;
5037dd0eeac9SMatthew G. Knepley       PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, &flg));
5038dd0eeac9SMatthew G. Knepley       if (!flg) break;
50395390be7dSMatthew G. Knepley       PetscCall(DMHasLabel(dm, name, &noCreate));
50405390be7dSMatthew G. Knepley       if (noCreate) {
50415390be7dSMatthew G. Knepley         DMLabel         inlabel;
50425390be7dSMatthew G. Knepley         IS              pointIS;
50435390be7dSMatthew G. Knepley         const PetscInt *lpoints;
50445390be7dSMatthew G. Knepley         PetscInt        pdep, ln, inval = points[0];
50455390be7dSMatthew G. Knepley         char            newname[PETSC_MAX_PATH_LEN];
50465390be7dSMatthew G. Knepley 
50475390be7dSMatthew G. Knepley         PetscCheck(n == 1, comm, PETSC_ERR_ARG_WRONG, "Must specify a label value with this option");
50485390be7dSMatthew G. Knepley         PetscCall(DMGetLabel(dm, name, &inlabel));
50495390be7dSMatthew G. Knepley         PetscCall(DMLabelGetStratumIS(inlabel, inval, &pointIS));
50505390be7dSMatthew G. Knepley         PetscCall(ISGetLocalSize(pointIS, &ln));
50515390be7dSMatthew G. Knepley         PetscCall(ISGetIndices(pointIS, &lpoints));
50525390be7dSMatthew G. Knepley         PetscCall(DMPlexGetPointDepth(dm, lpoints[0], &pdep));
50535390be7dSMatthew G. Knepley         PetscCall(PetscSNPrintf(newname, PETSC_MAX_PATH_LEN, "%s%" PetscInt_FMT, name, points[0]));
50545390be7dSMatthew G. Knepley         PetscCall(DMCreateLabel(dm, newname));
50555390be7dSMatthew G. Knepley         PetscCall(DMGetLabel(dm, newname, &label));
50565390be7dSMatthew G. Knepley         if (!pdep) PetscCall(ProcessCohesiveLabel_Vertices(dm, label, inlabel, inval, ln, lpoints));
50575390be7dSMatthew G. Knepley         else PetscCall(ProcessCohesiveLabel_Faces(dm, label, ln, lpoints));
50585390be7dSMatthew G. Knepley         PetscCall(ISRestoreIndices(pointIS, &lpoints));
50595390be7dSMatthew G. Knepley         PetscCall(ISDestroy(&pointIS));
50605390be7dSMatthew G. Knepley       } else {
5061dd0eeac9SMatthew G. Knepley         PetscCall(DMCreateLabel(dm, name));
5062dd0eeac9SMatthew G. Knepley         PetscCall(DMGetLabel(dm, name, &label));
5063dd0eeac9SMatthew G. Knepley         if (pStart >= pEnd) n = 0;
50645390be7dSMatthew G. Knepley         PetscCall(ProcessCohesiveLabel_Faces(dm, label, n, points));
5065dd0eeac9SMatthew G. Knepley       }
5066dd0eeac9SMatthew G. Knepley       PetscCall(DMPlexOrientLabel(dm, label));
50670542aa8cSMatthew G. Knepley       PetscCall(DMPlexLabelCohesiveComplete(dm, label, NULL, 1, PETSC_FALSE, PETSC_FALSE, NULL));
5068dd0eeac9SMatthew G. Knepley     }
5069dd0eeac9SMatthew G. Knepley   }
50705390be7dSMatthew G. Knepley   PetscCall(DMViewFromOptions(dm, NULL, "-created_dm_view"));
5071708be2fdSJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromOptions, dm, 0, 0, 0));
50723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50730a6ba040SMatthew G. Knepley }
50740a6ba040SMatthew G. Knepley 
5075ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems PetscOptionsObject)
5076d71ae5a4SJacob Faibussowitsch {
50770a6ba040SMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
50787f9d8d6cSVaclav Hapla   PetscBool flg, flg2;
50799318fe57SMatthew G. Knepley   char      bdLabel[PETSC_MAX_PATH_LEN];
5080adc21957SMatthew G. Knepley   char      method[PETSC_MAX_PATH_LEN];
50810a6ba040SMatthew G. Knepley 
50820a6ba040SMatthew G. Knepley   PetscFunctionBegin;
50830a6ba040SMatthew G. Knepley   /* Handle viewing */
50849566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL));
50855962854dSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level for all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0));
50865962854dSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fvm", "Debug output level for all fvm computations", "DMPlexSNESComputeResidualFVM", 0, &mesh->printFVM, NULL, 0));
50879566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL));
50889566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0));
5089f5867de0SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0));
5090a77a5016SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_project", "Debug output level all projection computations", "DMPlexProject", 0, &mesh->printProject, NULL, 0));
50919566063dSJacob Faibussowitsch   PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg));
50929566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscLogDefaultBegin());
50935e2c5519SMatthew G. Knepley   // Interpolation
50945e2c5519SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_interpolate_prefer_tensor", "When different orderings exist, prefer the tensor order", "DMPlexSetInterpolationPreferTensor", mesh->interpolatePreferTensor, &mesh->interpolatePreferTensor, NULL));
50959318fe57SMatthew G. Knepley   /* Labeling */
50969566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg));
50979566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel));
5098953fc75cSMatthew G. Knepley   /* Point Location */
50999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL));
51000848f4b5SMatthew G. Knepley   /* Partitioning and distribution */
51019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL));
5102d02c7345SMatthew G. Knepley   /* Reordering */
5103adc21957SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_reorder_section", "Compute point permutation for local section", "DMReorderSectionSetDefault", PETSC_FALSE, &flg2, &flg));
5104adc21957SMatthew G. Knepley   if (flg) PetscCall(DMReorderSectionSetDefault(dm, flg2 ? DM_REORDER_DEFAULT_TRUE : DM_REORDER_DEFAULT_FALSE));
5105adc21957SMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_reorder_section_type", "Reordering method for local section", "DMReorderSectionSetType", method, method, PETSC_MAX_PATH_LEN, &flg));
5106adc21957SMatthew G. Knepley   if (flg) PetscCall(DMReorderSectionSetType(dm, method));
51072e62ab5aSMatthew G. Knepley   /* Generation and remeshing */
51089566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL));
510961f058f9SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_save_transform", "Save the transform producing this mesh", "DMAdapt", PETSC_FALSE, &mesh->saveTransform, NULL));
5110b29cfa1cSToby Isaac   /* Projection behavior */
5111d5b43468SJose E. Roman   PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0));
51129566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL));
5113f12cf164SMatthew G. Knepley   /* Checking structure */
5114f12cf164SMatthew G. Knepley   {
51157f9d8d6cSVaclav Hapla     PetscBool all = PETSC_FALSE;
5116f12cf164SMatthew G. Knepley 
51177f9d8d6cSVaclav Hapla     PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL));
51187f9d8d6cSVaclav Hapla     if (all) {
51197f9d8d6cSVaclav Hapla       PetscCall(DMPlexCheck(dm));
51207f9d8d6cSVaclav Hapla     } else {
51219566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2));
51227f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm));
51239566063dSJacob 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));
51247f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0));
51259566063dSJacob 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));
51267f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0));
51279566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2));
51287f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm));
51299566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2));
5130d7d32a9aSMatthew G. Knepley       if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
51319566063dSJacob 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));
51327f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm));
51337f9d8d6cSVaclav Hapla     }
51349566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2));
51359566063dSJacob Faibussowitsch     if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE));
5136f12cf164SMatthew G. Knepley   }
51379318fe57SMatthew G. Knepley   {
51389318fe57SMatthew G. Knepley     PetscReal scale = 1.0;
51394f3833eaSMatthew G. Knepley 
51409566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg));
51419318fe57SMatthew G. Knepley     if (flg) {
51429318fe57SMatthew G. Knepley       Vec coordinates, coordinatesLocal;
51439318fe57SMatthew G. Knepley 
51449566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinates(dm, &coordinates));
51459566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
51469566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinates, scale));
51479566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinatesLocal, scale));
51489318fe57SMatthew G. Knepley     }
51499318fe57SMatthew G. Knepley   }
51509566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner));
51513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
515268d4fef7SMatthew G. Knepley }
515368d4fef7SMatthew G. Knepley 
5154ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems PetscOptionsObject, PetscInt *overlap)
5155d71ae5a4SJacob Faibussowitsch {
5156c506a872SMatthew G. Knepley   PetscInt  numOvLabels = 16, numOvExLabels = 16;
5157c506a872SMatthew G. Knepley   char     *ovLabelNames[16], *ovExLabelNames[16];
5158c506a872SMatthew G. Knepley   PetscInt  numOvValues = 16, numOvExValues = 16, l;
5159c506a872SMatthew G. Knepley   PetscBool flg;
5160c506a872SMatthew G. Knepley 
5161c506a872SMatthew G. Knepley   PetscFunctionBegin;
5162c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0));
5163c506a872SMatthew G. Knepley   PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg));
5164c506a872SMatthew G. Knepley   if (!flg) numOvLabels = 0;
5165c506a872SMatthew G. Knepley   if (numOvLabels) {
5166c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvLabels = numOvLabels;
5167c506a872SMatthew G. Knepley     for (l = 0; l < numOvLabels; ++l) {
5168c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l]));
5169c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]);
5170c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovLabelNames[l]));
5171c506a872SMatthew G. Knepley     }
5172c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg));
5173c506a872SMatthew G. Knepley     if (!flg) numOvValues = 0;
5174c506a872SMatthew 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);
5175c506a872SMatthew G. Knepley 
5176c506a872SMatthew G. Knepley     PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg));
5177c506a872SMatthew G. Knepley     if (!flg) numOvExLabels = 0;
5178c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels;
5179c506a872SMatthew G. Knepley     for (l = 0; l < numOvExLabels; ++l) {
5180c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l]));
5181c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]);
5182c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovExLabelNames[l]));
5183c506a872SMatthew G. Knepley     }
5184c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg));
5185c506a872SMatthew G. Knepley     if (!flg) numOvExValues = 0;
5186c506a872SMatthew 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);
5187c506a872SMatthew G. Knepley   }
51883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5189c506a872SMatthew G. Knepley }
5190c506a872SMatthew G. Knepley 
5191ce78bad3SBarry Smith static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems PetscOptionsObject)
5192d71ae5a4SJacob Faibussowitsch {
5193bdf63967SMatthew G. Knepley   PetscFunctionList    ordlist;
5194bdf63967SMatthew G. Knepley   char                 oname[256];
51954e22dd4cSMatthew G. Knepley   char                 sublabelname[PETSC_MAX_PATH_LEN] = "";
5196adc21957SMatthew G. Knepley   DMReorderDefaultFlag reorder;
5197d410b0cfSMatthew G. Knepley   PetscReal            volume    = -1.0;
51989318fe57SMatthew G. Knepley   PetscInt             prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim;
5199530e699aSMatthew G. Knepley   PetscBool            uniformOrig = PETSC_FALSE, uniform = PETSC_TRUE, distribute, saveSF = PETSC_FALSE, interpolate = PETSC_TRUE, coordSpace = PETSC_FALSE, remap = PETSC_TRUE, ghostCells = PETSC_FALSE, isHierarchy, flg;
520068d4fef7SMatthew G. Knepley 
520168d4fef7SMatthew G. Knepley   PetscFunctionBegin;
5202d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options");
5203dd4c3f67SMatthew G. Knepley   if (dm->cloneOpts) goto non_refine;
52049318fe57SMatthew G. Knepley   /* Handle automatic creation */
52059566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
5206530e699aSMatthew G. Knepley   if (dim < 0) PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));
52076bc1bd01Sksagiyam   PetscCall(DMGetDimension(dm, &dim));
5208d89e6e46SMatthew G. Knepley   /* Handle interpolation before distribution */
52099566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg));
5210d89e6e46SMatthew G. Knepley   if (flg) {
5211d89e6e46SMatthew G. Knepley     DMPlexInterpolatedFlag interpolated;
5212d89e6e46SMatthew G. Knepley 
52139566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpolated));
5214d89e6e46SMatthew G. Knepley     if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) {
5215d89e6e46SMatthew G. Knepley       DM udm;
5216d89e6e46SMatthew G. Knepley 
52179566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(dm, &udm));
521869d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &udm));
5219d89e6e46SMatthew G. Knepley     } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) {
5220d89e6e46SMatthew G. Knepley       DM idm;
5221d89e6e46SMatthew G. Knepley 
52229566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(dm, &idm));
522369d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &idm));
5224d89e6e46SMatthew G. Knepley     }
5225d89e6e46SMatthew G. Knepley   }
52264e22dd4cSMatthew G. Knepley   // Handle submesh selection before distribution
52274e22dd4cSMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_plex_submesh", "Label to use for submesh selection", "", sublabelname, sublabelname, PETSC_MAX_PATH_LEN, &flg));
52284e22dd4cSMatthew G. Knepley   if (flg) {
52294e22dd4cSMatthew G. Knepley     DM              subdm;
52304e22dd4cSMatthew G. Knepley     DMLabel         label;
52314e22dd4cSMatthew G. Knepley     IS              valueIS, pointIS;
52324e22dd4cSMatthew G. Knepley     const PetscInt *values, *points;
52334e22dd4cSMatthew G. Knepley     PetscBool       markedFaces = PETSC_FALSE;
52344e22dd4cSMatthew G. Knepley     PetscInt        Nv, value, Np;
52354e22dd4cSMatthew G. Knepley 
52364e22dd4cSMatthew G. Knepley     PetscCall(DMGetLabel(dm, sublabelname, &label));
52374e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetNumValues(label, &Nv));
52384e22dd4cSMatthew 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);
52394e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetValueIS(label, &valueIS));
52404e22dd4cSMatthew G. Knepley     PetscCall(ISGetIndices(valueIS, &values));
52414e22dd4cSMatthew G. Knepley     value = values[0];
52424e22dd4cSMatthew G. Knepley     PetscCall(ISRestoreIndices(valueIS, &values));
52434e22dd4cSMatthew G. Knepley     PetscCall(ISDestroy(&valueIS));
52444e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetStratumSize(label, value, &Np));
52454e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetStratumIS(label, value, &pointIS));
52464e22dd4cSMatthew G. Knepley     PetscCall(ISGetIndices(pointIS, &points));
52474e22dd4cSMatthew G. Knepley     for (PetscInt p = 0; p < Np; ++p) {
52484e22dd4cSMatthew G. Knepley       PetscInt pdepth;
52494e22dd4cSMatthew G. Knepley 
52504e22dd4cSMatthew G. Knepley       PetscCall(DMPlexGetPointDepth(dm, points[p], &pdepth));
52514e22dd4cSMatthew G. Knepley       if (pdepth) {
52524e22dd4cSMatthew G. Knepley         markedFaces = PETSC_TRUE;
52534e22dd4cSMatthew G. Knepley         break;
52544e22dd4cSMatthew G. Knepley       }
52554e22dd4cSMatthew G. Knepley     }
52564e22dd4cSMatthew G. Knepley     PetscCall(ISRestoreIndices(pointIS, &points));
52574e22dd4cSMatthew G. Knepley     PetscCall(ISDestroy(&pointIS));
52584e22dd4cSMatthew G. Knepley     PetscCall(DMPlexCreateSubmesh(dm, label, value, markedFaces, &subdm));
52594e22dd4cSMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &subdm));
52604e22dd4cSMatthew G. Knepley     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
52614e22dd4cSMatthew G. Knepley   }
52629b44eab4SMatthew G. Knepley   /* Handle DMPlex refinement before distribution */
52639566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig));
52649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0));
52659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
52669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg));
52679566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform));
52689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg));
52699318fe57SMatthew G. Knepley   if (flg) {
52709566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE));
52719566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(dm, volume));
52729318fe57SMatthew G. Knepley     prerefine = PetscMax(prerefine, 1);
52739318fe57SMatthew G. Knepley   }
5274b23db253SStefano Zampini   if (prerefine) PetscCall(DMLocalizeCoordinates(dm));
52759b44eab4SMatthew G. Knepley   for (r = 0; r < prerefine; ++r) {
52769b44eab4SMatthew G. Knepley     DM            rdm;
52772192575eSBarry Smith     PetscPointFn *coordFunc;
52789b44eab4SMatthew G. Knepley 
5279509b31aaSMatthew G. Knepley     PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc));
5280dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
52819566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
528269d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &rdm));
5283dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
528461a622f3SMatthew G. Knepley     if (coordFunc && remap) {
52859566063dSJacob Faibussowitsch       PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
5286509b31aaSMatthew G. Knepley       PetscCall(DMPlexSetCoordinateMap(dm, coordFunc));
52879b44eab4SMatthew G. Knepley     }
52889b44eab4SMatthew G. Knepley   }
52899566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig));
52909318fe57SMatthew G. Knepley   /* Handle DMPlex extrusion before distribution */
52919566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0));
52929318fe57SMatthew G. Knepley   if (extLayers) {
52939318fe57SMatthew G. Knepley     DM edm;
52949318fe57SMatthew G. Knepley 
52959566063dSJacob Faibussowitsch     PetscCall(DMExtrude(dm, extLayers, &edm));
529669d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
5297509b31aaSMatthew G. Knepley     PetscCall(DMPlexSetCoordinateMap(dm, NULL));
5298dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
5299d410b0cfSMatthew G. Knepley     extLayers = 0;
53005e17fc22SAidan Hamilton     PetscCall(DMGetDimension(dm, &dim));
53019318fe57SMatthew G. Knepley   }
5302bdf63967SMatthew G. Knepley   /* Handle DMPlex reordering before distribution */
53036bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dm, &reorder));
53049566063dSJacob Faibussowitsch   PetscCall(MatGetOrderingList(&ordlist));
53056bc1bd01Sksagiyam   PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname)));
53069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg));
5307adc21957SMatthew G. Knepley   if (reorder == DM_REORDER_DEFAULT_TRUE || flg) {
5308bdf63967SMatthew G. Knepley     DM pdm;
5309bdf63967SMatthew G. Knepley     IS perm;
5310bdf63967SMatthew G. Knepley 
53119566063dSJacob Faibussowitsch     PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm));
53129566063dSJacob Faibussowitsch     PetscCall(DMPlexPermute(dm, perm, &pdm));
53139566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&perm));
531469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &pdm));
5315dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
5316bdf63967SMatthew G. Knepley   }
53179b44eab4SMatthew G. Knepley   /* Handle DMPlex distribution */
53189566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dm, &distribute));
5319c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL));
5320a286e215SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute_save_sf", "Flag to save the migration SF", "DMPlexSetMigrationSF", saveSF, &saveSF, NULL));
5321dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap));
53229b44eab4SMatthew G. Knepley   if (distribute) {
53239b44eab4SMatthew G. Knepley     DM               pdm = NULL;
53249b44eab4SMatthew G. Knepley     PetscPartitioner part;
5325a286e215SMatthew G. Knepley     PetscSF          sfMigration;
53269566ead2SJames Wright     PetscBool        use_partition_balance;
53279b44eab4SMatthew G. Knepley 
53289566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
53299566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
53309566ead2SJames Wright     PetscCall(DMPlexGetPartitionBalance(dm, &use_partition_balance));
53319566ead2SJames Wright     PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", use_partition_balance, &use_partition_balance, &flg));
53329566ead2SJames Wright     if (flg) PetscCall(DMPlexSetPartitionBalance(dm, use_partition_balance));
5333a286e215SMatthew G. Knepley     PetscCall(DMPlexDistribute(dm, overlap, &sfMigration, &pdm));
53345d2873a6SJames Wright     if (pdm) {
53355d2873a6SJames Wright       // Delete the local section to force the existing one to be rebuilt with the distributed DM
53365d2873a6SJames Wright       PetscCall(DMSetLocalSection(dm, pdm->localSection));
53375d2873a6SJames Wright       PetscCall(DMPlexReplace_Internal(dm, &pdm));
53385d2873a6SJames Wright     }
5339a286e215SMatthew G. Knepley     if (saveSF) PetscCall(DMPlexSetMigrationSF(dm, sfMigration));
5340a286e215SMatthew G. Knepley     PetscCall(PetscSFDestroy(&sfMigration));
53419b44eab4SMatthew G. Knepley   }
53424054ae39SJames Wright 
53434054ae39SJames Wright   {
53444054ae39SJames Wright     PetscBool useBoxLabel = PETSC_FALSE;
53454054ae39SJames Wright     PetscCall(PetscOptionsBool("-dm_plex_box_label", "Create 'Face Sets' assuming boundary faces align with cartesian directions", "DMCreate", useBoxLabel, &useBoxLabel, NULL));
5346d7d2d1d2SJames Wright     if (useBoxLabel) {
5347d7d2d1d2SJames Wright       PetscInt       n      = 3;
5348d7d2d1d2SJames Wright       DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
5349d7d2d1d2SJames Wright 
5350d7d2d1d2SJames Wright       PetscCall(PetscOptionsEnumArray("-dm_plex_box_label_bd", "Boundary type for each dimension when using -dm_plex_box_label", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
5351d7d2d1d2SJames Wright       PetscCheck(!flg || !(n != dim), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
5352d7d2d1d2SJames Wright       PetscCall(DMPlexSetBoxLabel_Internal(dm, bdt));
5353d7d2d1d2SJames Wright     }
53544054ae39SJames Wright   }
5355d2b2dc1eSMatthew G. Knepley   /* Must check CEED options before creating function space for coordinates */
5356d2b2dc1eSMatthew G. Knepley   {
5357d2b2dc1eSMatthew G. Knepley     PetscBool useCeed = PETSC_FALSE, flg;
5358d2b2dc1eSMatthew G. Knepley 
5359d2b2dc1eSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_plex_use_ceed", "Use LibCEED as the FEM backend", "DMPlexSetUseCeed", useCeed, &useCeed, &flg));
5360d2b2dc1eSMatthew G. Knepley     if (flg) PetscCall(DMPlexSetUseCeed(dm, useCeed));
5361d2b2dc1eSMatthew G. Knepley   }
53629318fe57SMatthew G. Knepley   /* Create coordinate space */
5363530e699aSMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, NULL));
5364530e699aSMatthew G. Knepley   if (coordSpace) {
5365e44f6aebSMatthew G. Knepley     PetscInt  degree = 1, deg;
53665515ebd3SMatthew G. Knepley     PetscInt  height = 0;
53675515ebd3SMatthew G. Knepley     DM        cdm;
5368530e699aSMatthew G. Knepley     PetscBool localize = PETSC_TRUE, sparseLocalize = PETSC_TRUE;
53699318fe57SMatthew G. Knepley 
53709566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, &degree, NULL));
5371e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDegree_Internal(dm, &deg));
5372*4c712d99Sksagiyam     if (coordSpace && deg <= 1) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_FALSE, PETSC_TRUE, NULL));
53735515ebd3SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
5374530e699aSMatthew G. Knepley     if (!coordSpace) {
537561a622f3SMatthew G. Knepley       PetscDS      cds;
537661a622f3SMatthew G. Knepley       PetscObject  obj;
537761a622f3SMatthew G. Knepley       PetscClassId id;
537861a622f3SMatthew G. Knepley 
53799566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdm, &cds));
53809566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
53819566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
538261a622f3SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
538361a622f3SMatthew G. Knepley         PetscContainer dummy;
538461a622f3SMatthew G. Knepley 
53859566063dSJacob Faibussowitsch         PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy));
53869566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates"));
53879566063dSJacob Faibussowitsch         PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy));
53889566063dSJacob Faibussowitsch         PetscCall(PetscContainerDestroy(&dummy));
53899566063dSJacob Faibussowitsch         PetscCall(DMClearDS(cdm));
539061a622f3SMatthew G. Knepley       }
5391509b31aaSMatthew G. Knepley       PetscCall(DMPlexSetCoordinateMap(dm, NULL));
539261a622f3SMatthew G. Knepley     }
5393c3db174cSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_localize", "Localize mesh coordinates", "", localize, &localize, NULL));
5394c3db174cSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "DMSetSparseLocalize", sparseLocalize, &sparseLocalize, &flg));
5395c3db174cSMatthew G. Knepley     if (flg) PetscCall(DMSetSparseLocalize(dm, sparseLocalize));
53965515ebd3SMatthew G. Knepley     PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg));
53975515ebd3SMatthew G. Knepley     if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height));
5398c3db174cSMatthew G. Knepley     if (localize) PetscCall(DMLocalizeCoordinates(dm));
53999318fe57SMatthew G. Knepley   }
540068d4fef7SMatthew G. Knepley   /* Handle DMPlex refinement */
540161a622f3SMatthew G. Knepley   remap = PETSC_TRUE;
54029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0));
54039566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
54049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0));
54059566063dSJacob Faibussowitsch   if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
540668d4fef7SMatthew G. Knepley   if (refine && isHierarchy) {
5407acdc6f61SToby Isaac     DM *dms, coarseDM;
540868d4fef7SMatthew G. Knepley 
54099566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &coarseDM));
54109566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarseDM));
54119566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(refine, &dms));
54129566063dSJacob Faibussowitsch     PetscCall(DMRefineHierarchy(dm, refine, dms));
541368d4fef7SMatthew G. Knepley     /* Total hack since we do not pass in a pointer */
54149566063dSJacob Faibussowitsch     PetscCall(DMPlexSwap_Static(dm, dms[refine - 1]));
541568d4fef7SMatthew G. Knepley     if (refine == 1) {
54169566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[0]));
54179566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
541868d4fef7SMatthew G. Knepley     } else {
54199566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[refine - 2]));
54209566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
54219566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1]));
54229566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE));
542368d4fef7SMatthew G. Knepley     }
54249566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM));
54259566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coarseDM));
542668d4fef7SMatthew G. Knepley     /* Free DMs */
542768d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
5428dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
54299566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
543068d4fef7SMatthew G. Knepley     }
54319566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
543268d4fef7SMatthew G. Knepley   } else {
543368d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
54349318fe57SMatthew G. Knepley       DM            rdm;
54352192575eSBarry Smith       PetscPointFn *coordFunc;
543668d4fef7SMatthew G. Knepley 
5437dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
54389566063dSJacob Faibussowitsch       PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
543968d4fef7SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
544069d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
5441dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
54423674be70SMatthew G. Knepley       PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc));
544361a622f3SMatthew G. Knepley       if (coordFunc && remap) {
54449566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
5445509b31aaSMatthew G. Knepley         PetscCall(DMPlexSetCoordinateMap(dm, coordFunc));
544651a74b61SMatthew G. Knepley       }
544768d4fef7SMatthew G. Knepley     }
544868d4fef7SMatthew G. Knepley   }
54493cf6fe12SMatthew G. Knepley   /* Handle DMPlex coarsening */
54509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0));
54519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0));
5452b653a561SMatthew G. Knepley   if (coarsen && isHierarchy) {
5453b653a561SMatthew G. Knepley     DM *dms;
5454b653a561SMatthew G. Knepley 
54559566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coarsen, &dms));
54569566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHierarchy(dm, coarsen, dms));
5457b653a561SMatthew G. Knepley     /* Free DMs */
5458b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
5459dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
54609566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
5461b653a561SMatthew G. Knepley     }
54629566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
5463b653a561SMatthew G. Knepley   } else {
5464b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
54659318fe57SMatthew G. Knepley       DM            cdm;
54662192575eSBarry Smith       PetscPointFn *coordFunc;
54673cf6fe12SMatthew G. Knepley 
5468509b31aaSMatthew G. Knepley       PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc));
5469dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
54709566063dSJacob Faibussowitsch       PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm));
54713cf6fe12SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
547269d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &cdm));
5473dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
54749318fe57SMatthew G. Knepley       if (coordFunc) {
54759566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
5476509b31aaSMatthew G. Knepley         PetscCall(DMPlexSetCoordinateMap(dm, coordFunc));
54779318fe57SMatthew G. Knepley       }
54783cf6fe12SMatthew G. Knepley     }
5479b653a561SMatthew G. Knepley   }
5480be664eb1SMatthew G. Knepley   // Handle coordinate remapping
5481be664eb1SMatthew G. Knepley   remap = PETSC_FALSE;
5482be664eb1SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_coord_remap", "Flag to control coordinate remapping", "", remap, &remap, NULL));
5483be664eb1SMatthew G. Knepley   if (remap) {
5484be664eb1SMatthew G. Knepley     DMPlexCoordMap map     = DM_COORD_MAP_NONE;
54852192575eSBarry Smith     PetscPointFn  *mapFunc = NULL;
5486be664eb1SMatthew G. Knepley     PetscScalar    params[16];
5487f45b553cSPierre Jolivet     PetscInt       Np = PETSC_STATIC_ARRAY_LENGTH(params), cdim;
5488be664eb1SMatthew G. Knepley     MPI_Comm       comm;
5489be664eb1SMatthew G. Knepley 
5490be664eb1SMatthew G. Knepley     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5491be664eb1SMatthew G. Knepley     PetscCall(DMGetCoordinateDim(dm, &cdim));
5492be664eb1SMatthew G. Knepley     PetscCall(PetscOptionsScalarArray("-dm_coord_map_params", "Parameters for the coordinate remapping", "", params, &Np, &flg));
5493be664eb1SMatthew G. Knepley     if (!flg) Np = 0;
5494be664eb1SMatthew G. Knepley     // TODO Allow user to pass a map function by name
5495be664eb1SMatthew G. Knepley     PetscCall(PetscOptionsEnum("-dm_coord_map", "Coordinate mapping for built-in mesh", "", DMPlexCoordMaps, (PetscEnum)map, (PetscEnum *)&map, &flg));
5496be664eb1SMatthew G. Knepley     if (flg) {
5497be664eb1SMatthew G. Knepley       switch (map) {
5498be664eb1SMatthew G. Knepley       case DM_COORD_MAP_NONE:
5499be664eb1SMatthew G. Knepley         mapFunc = coordMap_identity;
5500be664eb1SMatthew G. Knepley         break;
5501be664eb1SMatthew G. Knepley       case DM_COORD_MAP_SHEAR:
5502be664eb1SMatthew G. Knepley         mapFunc = coordMap_shear;
5503be664eb1SMatthew G. Knepley         if (!Np) {
5504be664eb1SMatthew G. Knepley           Np        = cdim + 1;
5505be664eb1SMatthew G. Knepley           params[0] = 0;
5506be664eb1SMatthew G. Knepley           for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0;
5507be664eb1SMatthew G. Knepley         }
5508be664eb1SMatthew 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);
5509be664eb1SMatthew G. Knepley         break;
5510be664eb1SMatthew G. Knepley       case DM_COORD_MAP_FLARE:
5511be664eb1SMatthew G. Knepley         mapFunc = coordMap_flare;
5512be664eb1SMatthew G. Knepley         if (!Np) {
5513be664eb1SMatthew G. Knepley           Np        = cdim + 1;
5514be664eb1SMatthew G. Knepley           params[0] = 0;
5515be664eb1SMatthew G. Knepley           for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0;
5516be664eb1SMatthew G. Knepley         }
5517be664eb1SMatthew 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);
5518be664eb1SMatthew G. Knepley         break;
5519be664eb1SMatthew G. Knepley       case DM_COORD_MAP_ANNULUS:
5520be664eb1SMatthew G. Knepley         mapFunc = coordMap_annulus;
5521be664eb1SMatthew G. Knepley         if (!Np) {
5522be664eb1SMatthew G. Knepley           Np        = 2;
5523be664eb1SMatthew G. Knepley           params[0] = 1.;
5524be664eb1SMatthew G. Knepley           params[1] = 2.;
5525be664eb1SMatthew G. Knepley         }
5526be664eb1SMatthew G. Knepley         PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The annulus coordinate map must have 2 parameters, not %" PetscInt_FMT, Np);
5527be664eb1SMatthew G. Knepley         break;
5528be664eb1SMatthew G. Knepley       case DM_COORD_MAP_SHELL:
5529be664eb1SMatthew G. Knepley         mapFunc = coordMap_shell;
5530be664eb1SMatthew G. Knepley         if (!Np) {
5531be664eb1SMatthew G. Knepley           Np        = 2;
5532be664eb1SMatthew G. Knepley           params[0] = 1.;
5533be664eb1SMatthew G. Knepley           params[1] = 2.;
5534be664eb1SMatthew G. Knepley         }
5535be664eb1SMatthew G. Knepley         PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The spherical shell coordinate map must have 2 parameters, not %" PetscInt_FMT, Np);
5536be664eb1SMatthew G. Knepley         break;
5537530e699aSMatthew G. Knepley       case DM_COORD_MAP_SINUSOID:
5538530e699aSMatthew G. Knepley         mapFunc = coordMap_sinusoid;
5539530e699aSMatthew G. Knepley         if (!Np) {
5540530e699aSMatthew G. Knepley           Np        = 3;
5541530e699aSMatthew G. Knepley           params[0] = 1.;
5542530e699aSMatthew G. Knepley           params[1] = 1.;
5543530e699aSMatthew G. Knepley           params[2] = 1.;
5544530e699aSMatthew G. Knepley         }
5545530e699aSMatthew G. Knepley         PetscCheck(Np == 3, comm, PETSC_ERR_ARG_WRONG, "The sinusoidal coordinate map must have 3 parameters, not %" PetscInt_FMT, Np);
5546530e699aSMatthew G. Knepley         break;
5547be664eb1SMatthew G. Knepley       default:
5548be664eb1SMatthew G. Knepley         mapFunc = coordMap_identity;
5549be664eb1SMatthew G. Knepley       }
5550be664eb1SMatthew G. Knepley     }
5551be664eb1SMatthew G. Knepley     if (Np) {
5552be664eb1SMatthew G. Knepley       DM      cdm;
5553be664eb1SMatthew G. Knepley       PetscDS cds;
5554be664eb1SMatthew G. Knepley 
5555be664eb1SMatthew G. Knepley       PetscCall(DMGetCoordinateDM(dm, &cdm));
5556be664eb1SMatthew G. Knepley       PetscCall(DMGetDS(cdm, &cds));
5557be664eb1SMatthew G. Knepley       PetscCall(PetscDSSetConstants(cds, Np, params));
5558be664eb1SMatthew G. Knepley     }
5559be664eb1SMatthew G. Knepley     PetscCall(DMPlexRemapGeometry(dm, 0.0, mapFunc));
5560be664eb1SMatthew G. Knepley   }
5561909dfd52SMatthew G. Knepley   /* Handle ghost cells */
55629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL));
5563909dfd52SMatthew G. Knepley   if (ghostCells) {
5564909dfd52SMatthew G. Knepley     DM   gdm;
5565909dfd52SMatthew G. Knepley     char lname[PETSC_MAX_PATH_LEN];
5566909dfd52SMatthew G. Knepley 
5567909dfd52SMatthew G. Knepley     lname[0] = '\0';
55689566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg));
55699566063dSJacob Faibussowitsch     PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm));
557069d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &gdm));
5571909dfd52SMatthew G. Knepley   }
55726913077dSMatthew G. Knepley   /* Handle 1D order */
5573adc21957SMatthew G. Knepley   if (reorder != DM_REORDER_DEFAULT_FALSE && dim == 1) {
55746913077dSMatthew G. Knepley     DM           cdm, rdm;
55756913077dSMatthew G. Knepley     PetscDS      cds;
55766913077dSMatthew G. Knepley     PetscObject  obj;
55776913077dSMatthew G. Knepley     PetscClassId id = PETSC_OBJECT_CLASSID;
55786913077dSMatthew G. Knepley     IS           perm;
55796bc1bd01Sksagiyam     PetscInt     Nf;
55806913077dSMatthew G. Knepley     PetscBool    distributed;
55816913077dSMatthew G. Knepley 
55829566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(dm, &distributed));
55839566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
55849566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
55859566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(cds, &Nf));
55866913077dSMatthew G. Knepley     if (Nf) {
55879566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
55889566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
55896913077dSMatthew G. Knepley     }
55906bc1bd01Sksagiyam     if (!distributed && id != PETSCFE_CLASSID) {
55919566063dSJacob Faibussowitsch       PetscCall(DMPlexGetOrdering1D(dm, &perm));
55929566063dSJacob Faibussowitsch       PetscCall(DMPlexPermute(dm, perm, &rdm));
559369d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
55949566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&perm));
55956913077dSMatthew G. Knepley     }
55966913077dSMatthew G. Knepley   }
55973cf6fe12SMatthew G. Knepley /* Handle */
5598dd4c3f67SMatthew G. Knepley non_refine:
5599dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
560022d6dc08SStefano Zampini   char    *phases[16];
560122d6dc08SStefano Zampini   PetscInt Nphases = 16;
560222d6dc08SStefano Zampini   PetscCall(PetscOptionsStringArray("-dm_plex_option_phases", "Option phase prefixes", "DMSetFromOptions", phases, &Nphases, &flg));
5603d0609cedSBarry Smith   PetscOptionsHeadEnd();
560422d6dc08SStefano Zampini 
560522d6dc08SStefano Zampini   // Phases
560622d6dc08SStefano Zampini   if (flg) {
5607530e699aSMatthew G. Knepley     DM          cdm;
5608530e699aSMatthew G. Knepley     char       *oldPrefix, *oldCoordPrefix;
5609530e699aSMatthew G. Knepley     const char *tmp;
561022d6dc08SStefano Zampini 
5611530e699aSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
5612530e699aSMatthew G. Knepley     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &tmp));
5613530e699aSMatthew G. Knepley     PetscCall(PetscStrallocpy(tmp, &oldPrefix));
5614530e699aSMatthew G. Knepley     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)cdm, &tmp));
5615530e699aSMatthew G. Knepley     PetscCall(PetscStrallocpy(tmp, &oldCoordPrefix));
561622d6dc08SStefano Zampini     for (PetscInt ph = 0; ph < Nphases; ++ph) {
561722d6dc08SStefano Zampini       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, phases[ph]));
5618530e699aSMatthew G. Knepley       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)cdm, phases[ph]));
561922d6dc08SStefano Zampini       PetscCall(PetscInfo(dm, "Options phase %s for DM %s\n", phases[ph], dm->hdr.name));
562022d6dc08SStefano Zampini       PetscCall(DMSetFromOptions(dm));
562122d6dc08SStefano Zampini       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix));
5622530e699aSMatthew G. Knepley       PetscCall(DMGetCoordinateDM(dm, &cdm));
5623530e699aSMatthew G. Knepley       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)cdm, oldCoordPrefix));
562422d6dc08SStefano Zampini       PetscCall(PetscFree(phases[ph]));
562522d6dc08SStefano Zampini     }
5626530e699aSMatthew G. Knepley     PetscCall(PetscFree(oldPrefix));
5627530e699aSMatthew G. Knepley     PetscCall(PetscFree(oldCoordPrefix));
562822d6dc08SStefano Zampini   }
56293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56300a6ba040SMatthew G. Knepley }
56310a6ba040SMatthew G. Knepley 
5632d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec)
5633d71ae5a4SJacob Faibussowitsch {
5634552f7358SJed Brown   PetscFunctionBegin;
56359566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector_Section_Private(dm, vec));
56369566063dSJacob Faibussowitsch   /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
56379566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex));
56389566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native));
56399566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex));
56409566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native));
56413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5642552f7358SJed Brown }
5643552f7358SJed Brown 
5644d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec)
5645d71ae5a4SJacob Faibussowitsch {
5646552f7358SJed Brown   PetscFunctionBegin;
56479566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector_Section_Private(dm, vec));
56489566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local));
56499566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local));
56503ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5651552f7358SJed Brown }
5652552f7358SJed Brown 
5653d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
5654d71ae5a4SJacob Faibussowitsch {
5655793f3fe5SMatthew G. Knepley   PetscInt depth, d;
5656793f3fe5SMatthew G. Knepley 
5657793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
56589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
5659793f3fe5SMatthew G. Knepley   if (depth == 1) {
56609566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &d));
56619566063dSJacob Faibussowitsch     if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
56629566063dSJacob Faibussowitsch     else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd));
56639371c9d4SSatish Balay     else {
56649371c9d4SSatish Balay       *pStart = 0;
56659371c9d4SSatish Balay       *pEnd   = 0;
56669371c9d4SSatish Balay     }
5667793f3fe5SMatthew G. Knepley   } else {
56689566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
5669793f3fe5SMatthew G. Knepley   }
56703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5671793f3fe5SMatthew G. Knepley }
5672793f3fe5SMatthew G. Knepley 
5673d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
5674d71ae5a4SJacob Faibussowitsch {
5675502a2867SDave May   PetscSF            sf;
56766497c311SBarry Smith   PetscMPIInt        niranks, njranks;
56776497c311SBarry Smith   PetscInt           n;
56780a19bb7dSprj-   const PetscMPIInt *iranks, *jranks;
56790a19bb7dSprj-   DM_Plex           *data = (DM_Plex *)dm->data;
5680502a2867SDave May 
56812f356facSMatthew G. Knepley   PetscFunctionBegin;
56829566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
56830a19bb7dSprj-   if (!data->neighbors) {
56849566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sf));
56859566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL));
56869566063dSJacob Faibussowitsch     PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL));
56879566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors));
56889566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks));
56899566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks));
56900a19bb7dSprj-     n = njranks + niranks;
56919566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1));
56920a19bb7dSprj-     /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */
56939566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(n, data->neighbors));
56940a19bb7dSprj-   }
56950a19bb7dSprj-   if (nranks) *nranks = data->neighbors[0];
56960a19bb7dSprj-   if (ranks) {
56970a19bb7dSprj-     if (data->neighbors[0]) *ranks = data->neighbors + 1;
56980a19bb7dSprj-     else *ranks = NULL;
56990a19bb7dSprj-   }
57003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5701502a2867SDave May }
5702502a2867SDave May 
57031eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec);
57041eb70e55SToby Isaac 
5705d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm)
5706d71ae5a4SJacob Faibussowitsch {
5707552f7358SJed Brown   PetscFunctionBegin;
5708552f7358SJed Brown   dm->ops->view                      = DMView_Plex;
57092c40f234SMatthew G. Knepley   dm->ops->load                      = DMLoad_Plex;
5710552f7358SJed Brown   dm->ops->setfromoptions            = DMSetFromOptions_Plex;
571138221697SMatthew G. Knepley   dm->ops->clone                     = DMClone_Plex;
5712552f7358SJed Brown   dm->ops->setup                     = DMSetUp_Plex;
57131bb6d2a8SBarry Smith   dm->ops->createlocalsection        = DMCreateLocalSection_Plex;
5714adc21957SMatthew G. Knepley   dm->ops->createsectionpermutation  = DMCreateSectionPermutation_Plex;
571566ad2231SToby Isaac   dm->ops->createdefaultconstraints  = DMCreateDefaultConstraints_Plex;
5716552f7358SJed Brown   dm->ops->createglobalvector        = DMCreateGlobalVector_Plex;
5717552f7358SJed Brown   dm->ops->createlocalvector         = DMCreateLocalVector_Plex;
5718184d77edSJed Brown   dm->ops->getlocaltoglobalmapping   = NULL;
57190298fd71SBarry Smith   dm->ops->createfieldis             = NULL;
5720552f7358SJed Brown   dm->ops->createcoordinatedm        = DMCreateCoordinateDM_Plex;
572199acd26cSksagiyam   dm->ops->createcellcoordinatedm    = DMCreateCellCoordinateDM_Plex;
5722f19dbd58SToby Isaac   dm->ops->createcoordinatefield     = DMCreateCoordinateField_Plex;
57230a6ba040SMatthew G. Knepley   dm->ops->getcoloring               = NULL;
5724552f7358SJed Brown   dm->ops->creatematrix              = DMCreateMatrix_Plex;
5725bceba477SMatthew G. Knepley   dm->ops->createinterpolation       = DMCreateInterpolation_Plex;
5726bd041c0cSMatthew G. Knepley   dm->ops->createmassmatrix          = DMCreateMassMatrix_Plex;
5727b4937a87SMatthew G. Knepley   dm->ops->createmassmatrixlumped    = DMCreateMassMatrixLumped_Plex;
57285a84ad33SLisandro Dalcin   dm->ops->createinjection           = DMCreateInjection_Plex;
5729552f7358SJed Brown   dm->ops->refine                    = DMRefine_Plex;
57300a6ba040SMatthew G. Knepley   dm->ops->coarsen                   = DMCoarsen_Plex;
57310a6ba040SMatthew G. Knepley   dm->ops->refinehierarchy           = DMRefineHierarchy_Plex;
5732b653a561SMatthew G. Knepley   dm->ops->coarsenhierarchy          = DMCoarsenHierarchy_Plex;
5733d410b0cfSMatthew G. Knepley   dm->ops->extrude                   = DMExtrude_Plex;
57340298fd71SBarry Smith   dm->ops->globaltolocalbegin        = NULL;
57350298fd71SBarry Smith   dm->ops->globaltolocalend          = NULL;
57360298fd71SBarry Smith   dm->ops->localtoglobalbegin        = NULL;
57370298fd71SBarry Smith   dm->ops->localtoglobalend          = NULL;
5738552f7358SJed Brown   dm->ops->destroy                   = DMDestroy_Plex;
5739552f7358SJed Brown   dm->ops->createsubdm               = DMCreateSubDM_Plex;
57402adcc780SMatthew G. Knepley   dm->ops->createsuperdm             = DMCreateSuperDM_Plex;
5741793f3fe5SMatthew G. Knepley   dm->ops->getdimpoints              = DMGetDimPoints_Plex;
5742552f7358SJed Brown   dm->ops->locatepoints              = DMLocatePoints_Plex;
57430709b2feSToby Isaac   dm->ops->projectfunctionlocal      = DMProjectFunctionLocal_Plex;
57440709b2feSToby Isaac   dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex;
5745bfc4295aSToby Isaac   dm->ops->projectfieldlocal         = DMProjectFieldLocal_Plex;
57468c6c5593SMatthew G. Knepley   dm->ops->projectfieldlabellocal    = DMProjectFieldLabelLocal_Plex;
5747ece3a9fcSMatthew G. Knepley   dm->ops->projectbdfieldlabellocal  = DMProjectBdFieldLabelLocal_Plex;
57480709b2feSToby Isaac   dm->ops->computel2diff             = DMComputeL2Diff_Plex;
5749b698f381SToby Isaac   dm->ops->computel2gradientdiff     = DMComputeL2GradientDiff_Plex;
57502a16baeaSToby Isaac   dm->ops->computel2fielddiff        = DMComputeL2FieldDiff_Plex;
575128d58a37SPierre Jolivet   dm->ops->getneighbors              = DMGetNeighbors_Plex;
57526c6a6b79SMatthew G. Knepley   dm->ops->getlocalboundingbox       = DMGetLocalBoundingBox_Coordinates;
5753907a3e9cSStefano Zampini   dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_Plex;
5754907a3e9cSStefano Zampini   dm->ops->createddscatters          = DMCreateDomainDecompositionScatters_Plex;
57559566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex));
57566c51210dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex));
575701468941SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBounds_C", DMPlexInsertBounds_Plex));
57589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex));
57599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex));
57609566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex));
57619566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex));
57626bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex));
57636bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex));
5764adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", DMReorderSectionGetDefault_Plex));
5765adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", DMReorderSectionSetDefault_Plex));
5766adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", DMReorderSectionGetType_Plex));
5767adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", DMReorderSectionSetType_Plex));
57689566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex));
5769c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
5770c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex));
5771d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", DMPlexGetUseCeed_Plex));
5772d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", DMPlexSetUseCeed_Plex));
57733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5774552f7358SJed Brown }
5775552f7358SJed Brown 
5776d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm)
5777d71ae5a4SJacob Faibussowitsch {
577863a16f15SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex *)dm->data;
57791fca310dSJames Wright   const PetscSF *face_sfs;
57801fca310dSJames Wright   PetscInt       num_face_sfs;
578163a16f15SMatthew G. Knepley 
578263a16f15SMatthew G. Knepley   PetscFunctionBegin;
578363a16f15SMatthew G. Knepley   mesh->refct++;
578463a16f15SMatthew G. Knepley   (*newdm)->data = mesh;
57851fca310dSJames Wright   PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &face_sfs));
57861fca310dSJames Wright   PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, num_face_sfs, (PetscSF *)face_sfs));
57879566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX));
57889566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(*newdm));
57893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
579063a16f15SMatthew G. Knepley }
579163a16f15SMatthew G. Knepley 
57928818961aSMatthew G Knepley /*MC
57930b4b7b1cSBarry Smith   DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh (or grid), or CW Complex {cite}`cwcomplex`,
57940b4b7b1cSBarry Smith            which can be expressed using a Hasse Diagram {cite}`hassediagram`.
579520f4b53cSBarry Smith            In the local representation, `Vec`s contain all unknowns in the interior and shared boundary. This is
57960b4b7b1cSBarry Smith            specified by a `PetscSection` object. Ownership in the global representation is determined by
5797a1cb98faSBarry Smith            ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object.
57988818961aSMatthew G Knepley 
5799e5893cccSMatthew G. Knepley   Options Database Keys:
5800250712c9SMatthew G. Knepley + -dm_refine_pre                     - Refine mesh before distribution
5801250712c9SMatthew G. Knepley + -dm_refine_uniform_pre             - Choose uniform or generator-based refinement
5802250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre        - Cell volume limit after pre-refinement using generator
5803250712c9SMatthew G. Knepley . -dm_distribute                     - Distribute mesh across processes
5804250712c9SMatthew G. Knepley . -dm_distribute_overlap             - Number of cells to overlap for distribution
5805250712c9SMatthew G. Knepley . -dm_refine                         - Refine mesh after distribution
5806c3db174cSMatthew G. Knepley . -dm_localize <bool>                - Whether to localize coordinates for periodic meshes
5807c3db174cSMatthew G. Knepley . -dm_sparse_localize <bool>         - Whether to only localize cells on the periodic boundary
5808250712c9SMatthew G. Knepley . -dm_plex_hash_location             - Use grid hashing for point location
5809ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p>    - The number of divisions in each direction of the grid hash
5810f12cf164SMatthew G. Knepley . -dm_plex_partition_balance         - Attempt to evenly divide points on partition boundary between processes
5811f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd                 - Allow changes to the boundary on remeshing
5812d5b43468SJose E. Roman . -dm_plex_max_projection_height     - Maximum mesh point height used to project locally
5813f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement        - Use special nested projection algorithm for regular refinement
5814d02c7345SMatthew G. Knepley . -dm_plex_reorder_section           - Use specialized blocking if available
5815aaa8cc7dSPierre Jolivet . -dm_plex_check_all                 - Perform all checks below
5816f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry            - Check that the adjacency information in the mesh is symmetric
5817f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices
5818f12cf164SMatthew 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
5819f12cf164SMatthew G. Knepley . -dm_plex_check_geometry            - Check that cells have positive volume
5820f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex     - View the mesh in LaTeX/TikZ
5821e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num>          - Scale the TikZ
58225962854dSMatthew G. Knepley . -dm_plex_print_fem <num>           - View FEM assembly information, such as element vectors and matrices
58235962854dSMatthew G. Knepley - -dm_plex_print_fvm <num>           - View FVM assembly information, such as flux updates
5824e5893cccSMatthew G. Knepley 
58258818961aSMatthew G Knepley   Level: intermediate
58268818961aSMatthew G Knepley 
58271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection`
58288818961aSMatthew G Knepley M*/
58298818961aSMatthew G Knepley 
5830d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
5831d71ae5a4SJacob Faibussowitsch {
5832552f7358SJed Brown   DM_Plex *mesh;
5833412e9a14SMatthew G. Knepley   PetscInt unit;
5834552f7358SJed Brown 
5835552f7358SJed Brown   PetscFunctionBegin;
5836f39ec787SMatthew G. Knepley   PetscCall(PetscCitationsRegister(PlexCitation, &Plexcite));
5837552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58384dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&mesh));
5839adc21957SMatthew G. Knepley   dm->reorderSection = DM_REORDER_DEFAULT_NOTSET;
5840552f7358SJed Brown   dm->data           = mesh;
5841552f7358SJed Brown 
5842552f7358SJed Brown   mesh->refct = 1;
58439566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection));
58449566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection));
5845552f7358SJed Brown   mesh->refinementUniform       = PETSC_TRUE;
5846552f7358SJed Brown   mesh->refinementLimit         = -1.0;
5847e600fa54SMatthew G. Knepley   mesh->distDefault             = PETSC_TRUE;
5848adc21957SMatthew G. Knepley   mesh->reorderDefault          = DM_REORDER_DEFAULT_NOTSET;
58491d1f2f2aSksagiyam   mesh->distributionName        = NULL;
58507d0f5628SVaclav Hapla   mesh->interpolated            = DMPLEX_INTERPOLATED_INVALID;
58517d0f5628SVaclav Hapla   mesh->interpolatedCollective  = DMPLEX_INTERPOLATED_INVALID;
58525e2c5519SMatthew G. Knepley   mesh->interpolatePreferTensor = PETSC_TRUE;
5853552f7358SJed Brown 
58549566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner));
58552e62ab5aSMatthew G. Knepley   mesh->remeshBd = PETSC_FALSE;
5856d9deefdfSMatthew G. Knepley 
58578865f1eaSKarl Rupp   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
5858552f7358SJed Brown 
5859df0420ecSMatthew G. Knepley   mesh->depthState    = -1;
5860ba2698f1SMatthew G. Knepley   mesh->celltypeState = -1;
58616113b454SMatthew G. Knepley   mesh->printTol      = 1.0e-10;
5862c29ce622SStefano Zampini   mesh->nonempty_comm = MPI_COMM_SELF;
5863552f7358SJed Brown 
58649566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
58653ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5866552f7358SJed Brown }
5867552f7358SJed Brown 
5868552f7358SJed Brown /*@
5869a1cb98faSBarry Smith   DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
5870552f7358SJed Brown 
5871d083f849SBarry Smith   Collective
5872552f7358SJed Brown 
5873552f7358SJed Brown   Input Parameter:
5874a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object
5875552f7358SJed Brown 
5876552f7358SJed Brown   Output Parameter:
5877a1cb98faSBarry Smith . mesh - The `DMPLEX` object
5878552f7358SJed Brown 
5879552f7358SJed Brown   Level: beginner
5880552f7358SJed Brown 
588142747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMCreate()`, `DMSetType()`
5882552f7358SJed Brown @*/
5883d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
5884d71ae5a4SJacob Faibussowitsch {
5885552f7358SJed Brown   PetscFunctionBegin;
58864f572ea9SToby Isaac   PetscAssertPointer(mesh, 2);
58879566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, mesh));
58889566063dSJacob Faibussowitsch   PetscCall(DMSetType(*mesh, DMPLEX));
58893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5890552f7358SJed Brown }
5891552f7358SJed Brown 
5892b09969d6SVaclav Hapla /*@C
5893b0fe842aSMatthew 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
5894a1cb98faSBarry Smith 
589520f4b53cSBarry Smith   Collective; No Fortran Support
5896b09969d6SVaclav Hapla 
5897b09969d6SVaclav Hapla   Input Parameters:
5898a1cb98faSBarry Smith + dm          - The `DM`
5899b09969d6SVaclav Hapla . numCells    - The number of cells owned by this process
5900a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
5901a1cb98faSBarry Smith . NVertices   - The global number of vertices, or `PETSC_DETERMINE`
5902b09969d6SVaclav Hapla . numCorners  - The number of vertices for each cell
59035e488331SVaclav Hapla - cells       - An array of numCells*numCorners numbers, the global vertex numbers for each cell
5904b09969d6SVaclav Hapla 
5905be8c289dSNicolas Barral   Output Parameters:
5906a1cb98faSBarry Smith + vertexSF         - (Optional) `PetscSF` describing complete vertex ownership
5907be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
5908b09969d6SVaclav Hapla 
5909b09969d6SVaclav Hapla   Level: advanced
5910b09969d6SVaclav Hapla 
5911a1cb98faSBarry Smith   Notes:
5912a1cb98faSBarry Smith   Two triangles sharing a face
5913a1cb98faSBarry Smith .vb
5914a1cb98faSBarry Smith 
5915a1cb98faSBarry Smith         2
5916a1cb98faSBarry Smith       / | \
5917a1cb98faSBarry Smith      /  |  \
5918a1cb98faSBarry Smith     /   |   \
5919a1cb98faSBarry Smith    0  0 | 1  3
5920a1cb98faSBarry Smith     \   |   /
5921a1cb98faSBarry Smith      \  |  /
5922a1cb98faSBarry Smith       \ | /
5923a1cb98faSBarry Smith         1
5924a1cb98faSBarry Smith .ve
5925a1cb98faSBarry Smith   would have input
5926a1cb98faSBarry Smith .vb
5927a1cb98faSBarry Smith   numCells = 2, numVertices = 4
5928a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
5929a1cb98faSBarry Smith .ve
5930a1cb98faSBarry Smith   which would result in the `DMPLEX`
5931a1cb98faSBarry Smith .vb
5932a1cb98faSBarry Smith 
5933a1cb98faSBarry Smith         4
5934a1cb98faSBarry Smith       / | \
5935a1cb98faSBarry Smith      /  |  \
5936a1cb98faSBarry Smith     /   |   \
5937a1cb98faSBarry Smith    2  0 | 1  5
5938a1cb98faSBarry Smith     \   |   /
5939a1cb98faSBarry Smith      \  |  /
5940a1cb98faSBarry Smith       \ | /
5941a1cb98faSBarry Smith         3
5942a1cb98faSBarry Smith .ve
5943a1cb98faSBarry Smith 
5944a1cb98faSBarry Smith   Vertices are implicitly numbered consecutively 0,...,NVertices.
5945a1cb98faSBarry Smith   Each rank owns a chunk of numVertices consecutive vertices.
5946a1cb98faSBarry Smith   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
5947a1cb98faSBarry Smith   If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
5948a1cb98faSBarry Smith   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
5949a1cb98faSBarry Smith 
5950a1cb98faSBarry Smith   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
5951a1cb98faSBarry Smith 
59521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
5953a1cb98faSBarry Smith           `PetscSF`
5954b09969d6SVaclav Hapla @*/
5955ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[])
5956d71ae5a4SJacob Faibussowitsch {
59572464107aSksagiyam   PetscSF     sfPoint;
59582464107aSksagiyam   PetscLayout layout;
595982fb893eSVaclav Hapla   PetscInt    numVerticesAdj, *verticesAdj, *cones, c, p;
5960a47d0d45SMatthew G. Knepley 
5961a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
596225b6865aSVaclav Hapla   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
59639566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
596425b6865aSVaclav Hapla   /* Get/check global number of vertices */
596525b6865aSVaclav Hapla   {
596625b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
596725b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
596825b6865aSVaclav Hapla 
596925b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
59701690c2aeSBarry Smith     NVerticesInCells = PETSC_INT_MIN;
59719371c9d4SSatish Balay     for (i = 0; i < len; i++)
59729371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
597325b6865aSVaclav Hapla     ++NVerticesInCells;
5974462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
597525b6865aSVaclav Hapla 
597625b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
59779371c9d4SSatish Balay     else
59789371c9d4SSatish 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);
597925b6865aSVaclav Hapla   }
59809079aca8SVaclav Hapla   /* Count locally unique vertices */
59819079aca8SVaclav Hapla   {
59829079aca8SVaclav Hapla     PetscHSetI vhash;
59839079aca8SVaclav Hapla     PetscInt   off = 0;
59849079aca8SVaclav Hapla 
59859566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&vhash));
5986a47d0d45SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
598748a46eb9SPierre Jolivet       for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p]));
5988a47d0d45SMatthew G. Knepley     }
59899566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
59909566063dSJacob Faibussowitsch     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
5991ad540459SPierre Jolivet     else verticesAdj = *verticesAdjSaved;
59929566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
59939566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&vhash));
599463a3b9bcSJacob Faibussowitsch     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
5995a47d0d45SMatthew G. Knepley   }
59969566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
5997a47d0d45SMatthew G. Knepley   /* Create cones */
59989566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
59999566063dSJacob Faibussowitsch   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
60009566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
60019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
6002a47d0d45SMatthew G. Knepley   for (c = 0; c < numCells; ++c) {
6003a47d0d45SMatthew G. Knepley     for (p = 0; p < numCorners; ++p) {
6004a47d0d45SMatthew G. Knepley       const PetscInt gv = cells[c * numCorners + p];
6005a47d0d45SMatthew G. Knepley       PetscInt       lv;
6006a47d0d45SMatthew G. Knepley 
60079079aca8SVaclav Hapla       /* Positions within verticesAdj form 0-based local vertex numbering;
60089079aca8SVaclav Hapla          we need to shift it by numCells to get correct DAG points (cells go first) */
60099566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
601063a3b9bcSJacob Faibussowitsch       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
6011961cfab0SVaclav Hapla       cones[c * numCorners + p] = lv + numCells;
6012a47d0d45SMatthew G. Knepley     }
6013a47d0d45SMatthew G. Knepley   }
60142464107aSksagiyam   /* Build point sf */
60159566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
60169566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(layout, NVertices));
60179566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
60189566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
60199566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
60209566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
60219566063dSJacob Faibussowitsch   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
60229566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
60232464107aSksagiyam   if (dm->sf) {
60242464107aSksagiyam     const char *prefix;
60252464107aSksagiyam 
60269566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
60279566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
60282464107aSksagiyam   }
60299566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sfPoint));
60309566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfPoint));
6031f4f49eeaSPierre Jolivet   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF"));
6032a47d0d45SMatthew G. Knepley   /* Fill in the rest of the topology structure */
60339566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
60349566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
60359566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
60363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6037a47d0d45SMatthew G. Knepley }
6038a47d0d45SMatthew G. Knepley 
6039b0fe842aSMatthew G. Knepley /*@C
6040b0fe842aSMatthew G. Knepley   DMPlexBuildFromCellSectionParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) allowing multiple celltypes
6041b0fe842aSMatthew G. Knepley 
6042b0fe842aSMatthew G. Knepley   Collective; No Fortran Support
6043b0fe842aSMatthew G. Knepley 
6044b0fe842aSMatthew G. Knepley   Input Parameters:
6045b0fe842aSMatthew G. Knepley + dm          - The `DM`
6046b0fe842aSMatthew G. Knepley . numCells    - The number of cells owned by this process
6047b0fe842aSMatthew G. Knepley . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
6048b0fe842aSMatthew G. Knepley . NVertices   - The global number of vertices, or `PETSC_DETERMINE`
6049b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells)
6050b0fe842aSMatthew G. Knepley - cells       - An array of the global vertex numbers for each cell
6051b0fe842aSMatthew G. Knepley 
6052b0fe842aSMatthew G. Knepley   Output Parameters:
6053b0fe842aSMatthew G. Knepley + vertexSF         - (Optional) `PetscSF` describing complete vertex ownership
6054b0fe842aSMatthew G. Knepley - verticesAdjSaved - (Optional) vertex adjacency array
6055b0fe842aSMatthew G. Knepley 
6056b0fe842aSMatthew G. Knepley   Level: advanced
6057b0fe842aSMatthew G. Knepley 
6058b0fe842aSMatthew G. Knepley   Notes:
6059b0fe842aSMatthew G. Knepley   A triangle and quadrilateral sharing a face
6060b0fe842aSMatthew G. Knepley .vb
6061b0fe842aSMatthew G. Knepley         2----------3
6062b0fe842aSMatthew G. Knepley       / |          |
6063b0fe842aSMatthew G. Knepley      /  |          |
6064b0fe842aSMatthew G. Knepley     /   |          |
6065b0fe842aSMatthew G. Knepley    0  0 |     1    |
6066b0fe842aSMatthew G. Knepley     \   |          |
6067b0fe842aSMatthew G. Knepley      \  |          |
6068b0fe842aSMatthew G. Knepley       \ |          |
6069b0fe842aSMatthew G. Knepley         1----------4
6070b0fe842aSMatthew G. Knepley .ve
6071b0fe842aSMatthew G. Knepley   would have input
6072b0fe842aSMatthew G. Knepley .vb
6073b0fe842aSMatthew G. Knepley   numCells = 2, numVertices = 5
6074b0fe842aSMatthew G. Knepley   cells = [0 1 2  1 4 3 2]
6075b0fe842aSMatthew G. Knepley .ve
6076b0fe842aSMatthew G. Knepley   which would result in the `DMPLEX`
6077b0fe842aSMatthew G. Knepley .vb
6078b0fe842aSMatthew G. Knepley         4----------5
6079b0fe842aSMatthew G. Knepley       / |          |
6080b0fe842aSMatthew G. Knepley      /  |          |
6081b0fe842aSMatthew G. Knepley     /   |          |
6082b0fe842aSMatthew G. Knepley    2  0 |     1    |
6083b0fe842aSMatthew G. Knepley     \   |          |
6084b0fe842aSMatthew G. Knepley      \  |          |
6085b0fe842aSMatthew G. Knepley       \ |          |
6086b0fe842aSMatthew G. Knepley         3----------6
6087b0fe842aSMatthew G. Knepley .ve
6088b0fe842aSMatthew G. Knepley 
6089b0fe842aSMatthew G. Knepley   Vertices are implicitly numbered consecutively 0,...,NVertices.
6090b0fe842aSMatthew G. Knepley   Each rank owns a chunk of numVertices consecutive vertices.
6091b0fe842aSMatthew G. Knepley   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
6092b0fe842aSMatthew 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.
6093b0fe842aSMatthew G. Knepley   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
6094b0fe842aSMatthew G. Knepley 
6095b0fe842aSMatthew G. Knepley   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
6096b0fe842aSMatthew G. Knepley 
6097b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexCreateFromCellSectionParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
6098b0fe842aSMatthew G. Knepley           `PetscSF`
6099b0fe842aSMatthew G. Knepley @*/
6100ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellSectionParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[])
6101b0fe842aSMatthew G. Knepley {
6102b0fe842aSMatthew G. Knepley   PetscSF     sfPoint;
6103b0fe842aSMatthew G. Knepley   PetscLayout layout;
6104b0fe842aSMatthew G. Knepley   PetscInt    numVerticesAdj, *verticesAdj, *cones, cStart, cEnd, len;
6105b0fe842aSMatthew G. Knepley 
6106b0fe842aSMatthew G. Knepley   PetscFunctionBegin;
6107b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
6108b0fe842aSMatthew G. Knepley   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
6109b0fe842aSMatthew G. Knepley   PetscCall(PetscSectionGetChart(cellSection, &cStart, &cEnd));
6110b0fe842aSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(cellSection, &len));
6111b0fe842aSMatthew 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);
6112b0fe842aSMatthew G. Knepley   /* Get/check global number of vertices */
6113b0fe842aSMatthew G. Knepley   {
6114b0fe842aSMatthew G. Knepley     PetscInt NVerticesInCells;
6115b0fe842aSMatthew G. Knepley 
6116b0fe842aSMatthew G. Knepley     /* NVerticesInCells = max(cells) + 1 */
6117b0fe842aSMatthew G. Knepley     NVerticesInCells = PETSC_MIN_INT;
6118b0fe842aSMatthew G. Knepley     for (PetscInt i = 0; i < len; i++)
6119b0fe842aSMatthew G. Knepley       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
6120b0fe842aSMatthew G. Knepley     ++NVerticesInCells;
6121b0fe842aSMatthew G. Knepley     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
6122b0fe842aSMatthew G. Knepley 
6123b0fe842aSMatthew G. Knepley     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
6124b0fe842aSMatthew G. Knepley     else
6125b0fe842aSMatthew 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);
6126b0fe842aSMatthew G. Knepley   }
6127b0fe842aSMatthew G. Knepley   /* Count locally unique vertices */
6128b0fe842aSMatthew G. Knepley   {
6129b0fe842aSMatthew G. Knepley     PetscHSetI vhash;
6130b0fe842aSMatthew G. Knepley     PetscInt   off = 0;
6131b0fe842aSMatthew G. Knepley 
6132b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetICreate(&vhash));
6133b0fe842aSMatthew G. Knepley     for (PetscInt i = 0; i < len; i++) PetscCall(PetscHSetIAdd(vhash, cells[i]));
6134b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
6135b0fe842aSMatthew G. Knepley     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
6136b0fe842aSMatthew G. Knepley     else verticesAdj = *verticesAdjSaved;
6137b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
6138b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIDestroy(&vhash));
6139b0fe842aSMatthew 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);
6140b0fe842aSMatthew G. Knepley   }
6141b0fe842aSMatthew G. Knepley   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
6142b0fe842aSMatthew G. Knepley   /* Create cones */
6143b0fe842aSMatthew G. Knepley   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
6144b0fe842aSMatthew G. Knepley   for (PetscInt c = 0; c < numCells; ++c) {
6145b0fe842aSMatthew G. Knepley     PetscInt dof;
6146b0fe842aSMatthew G. Knepley 
6147b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetDof(cellSection, c, &dof));
6148b0fe842aSMatthew G. Knepley     PetscCall(DMPlexSetConeSize(dm, c, dof));
6149b0fe842aSMatthew G. Knepley   }
6150b0fe842aSMatthew G. Knepley   PetscCall(DMSetUp(dm));
6151b0fe842aSMatthew G. Knepley   PetscCall(DMPlexGetCones(dm, &cones));
6152b0fe842aSMatthew G. Knepley   for (PetscInt c = 0; c < numCells; ++c) {
6153b0fe842aSMatthew G. Knepley     PetscInt dof, off;
6154b0fe842aSMatthew G. Knepley 
6155b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetDof(cellSection, c, &dof));
6156b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetOffset(cellSection, c, &off));
6157b0fe842aSMatthew G. Knepley     for (PetscInt p = off; p < off + dof; ++p) {
6158b0fe842aSMatthew G. Knepley       const PetscInt gv = cells[p];
6159b0fe842aSMatthew G. Knepley       PetscInt       lv;
6160b0fe842aSMatthew G. Knepley 
6161b0fe842aSMatthew G. Knepley       /* Positions within verticesAdj form 0-based local vertex numbering;
6162b0fe842aSMatthew G. Knepley          we need to shift it by numCells to get correct DAG points (cells go first) */
6163b0fe842aSMatthew G. Knepley       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
6164b0fe842aSMatthew G. Knepley       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
6165b0fe842aSMatthew G. Knepley       cones[p] = lv + numCells;
6166b0fe842aSMatthew G. Knepley     }
6167b0fe842aSMatthew G. Knepley   }
6168b0fe842aSMatthew G. Knepley   /* Build point sf */
6169b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
6170b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetSize(layout, NVertices));
6171b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
6172b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetBlockSize(layout, 1));
6173b0fe842aSMatthew G. Knepley   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
6174b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutDestroy(&layout));
6175b0fe842aSMatthew G. Knepley   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
6176b0fe842aSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
6177b0fe842aSMatthew G. Knepley   if (dm->sf) {
6178b0fe842aSMatthew G. Knepley     const char *prefix;
6179b0fe842aSMatthew G. Knepley 
6180b0fe842aSMatthew G. Knepley     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
6181b0fe842aSMatthew G. Knepley     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
6182b0fe842aSMatthew G. Knepley   }
6183b0fe842aSMatthew G. Knepley   PetscCall(DMSetPointSF(dm, sfPoint));
6184b0fe842aSMatthew G. Knepley   PetscCall(PetscSFDestroy(&sfPoint));
6185b0fe842aSMatthew G. Knepley   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF"));
6186b0fe842aSMatthew G. Knepley   /* Fill in the rest of the topology structure */
6187b0fe842aSMatthew G. Knepley   PetscCall(DMPlexSymmetrize(dm));
6188b0fe842aSMatthew G. Knepley   PetscCall(DMPlexStratify(dm));
6189b0fe842aSMatthew G. Knepley   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
6190b0fe842aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
6191b0fe842aSMatthew G. Knepley }
6192b0fe842aSMatthew G. Knepley 
6193cc4c1da9SBarry Smith /*@
6194a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
6195a1cb98faSBarry Smith 
619620f4b53cSBarry Smith   Collective; No Fortran Support
6197b09969d6SVaclav Hapla 
6198b09969d6SVaclav Hapla   Input Parameters:
6199a1cb98faSBarry Smith + dm           - The `DM`
6200b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
6201a1cb98faSBarry Smith . sfVert       - `PetscSF` describing complete vertex ownership
6202b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6203b09969d6SVaclav Hapla 
6204b09969d6SVaclav Hapla   Level: advanced
6205b09969d6SVaclav Hapla 
62061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()`
6207b09969d6SVaclav Hapla @*/
6208d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[])
6209d71ae5a4SJacob Faibussowitsch {
6210a47d0d45SMatthew G. Knepley   PetscSection coordSection;
6211a47d0d45SMatthew G. Knepley   Vec          coordinates;
6212a47d0d45SMatthew G. Knepley   PetscScalar *coords;
62131edcf0b2SVaclav Hapla   PetscInt     numVertices, numVerticesAdj, coordSize, v, vStart, vEnd;
6214835f2295SStefano Zampini   PetscMPIInt  spaceDimi;
6215a47d0d45SMatthew G. Knepley 
6216a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
62179566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
62189566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
62191dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
62209566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
62219566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL));
62221dca8a05SBarry 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);
62239566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
62249566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
62259566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
62269566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
62271edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
62289566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
62299566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
6230a47d0d45SMatthew G. Knepley   }
62319566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
62329566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
62339566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
62349566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
62359566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
62369566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
62379566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
62389566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
6239a47d0d45SMatthew G. Knepley   {
6240a47d0d45SMatthew G. Knepley     MPI_Datatype coordtype;
6241a47d0d45SMatthew G. Knepley 
6242a47d0d45SMatthew G. Knepley     /* Need a temp buffer for coords if we have complex/single */
6243835f2295SStefano Zampini     PetscCall(PetscMPIIntCast(spaceDim, &spaceDimi));
6244835f2295SStefano Zampini     PetscCallMPI(MPI_Type_contiguous(spaceDimi, MPIU_SCALAR, &coordtype));
62459566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&coordtype));
624621016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX)
624721016a8bSBarry Smith     {
624821016a8bSBarry Smith       PetscScalar *svertexCoords;
624921016a8bSBarry Smith       PetscInt     i;
62509566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords));
62513612f820SVaclav Hapla       for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i];
62529566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
62539566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
62549566063dSJacob Faibussowitsch       PetscCall(PetscFree(svertexCoords));
625521016a8bSBarry Smith     }
625621016a8bSBarry Smith #else
62579566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
62589566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
625921016a8bSBarry Smith #endif
62609566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&coordtype));
6261a47d0d45SMatthew G. Knepley   }
62629566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
62639566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
62649566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
62659566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
62663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6267a47d0d45SMatthew G. Knepley }
6268a47d0d45SMatthew G. Knepley 
6269c3edce3dSSatish Balay /*@
6270b0fe842aSMatthew 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
6271a1cb98faSBarry Smith 
6272a1cb98faSBarry Smith   Collective
6273a47d0d45SMatthew G. Knepley 
6274a47d0d45SMatthew G. Knepley   Input Parameters:
6275a47d0d45SMatthew G. Knepley + comm         - The communicator
6276a47d0d45SMatthew G. Knepley . dim          - The topological dimension of the mesh
6277a47d0d45SMatthew G. Knepley . numCells     - The number of cells owned by this process
6278a1cb98faSBarry Smith . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`
6279a1cb98faSBarry Smith . NVertices    - The global number of vertices, or `PETSC_DECIDE`
6280a47d0d45SMatthew G. Knepley . numCorners   - The number of vertices for each cell
6281a47d0d45SMatthew G. Knepley . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
6282a47d0d45SMatthew G. Knepley . cells        - An array of numCells*numCorners numbers, the global vertex numbers for each cell
6283a47d0d45SMatthew G. Knepley . spaceDim     - The spatial dimension used for coordinates
6284a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6285a47d0d45SMatthew G. Knepley 
6286d8d19677SJose E. Roman   Output Parameters:
6287a1cb98faSBarry Smith + dm          - The `DM`
6288a1cb98faSBarry Smith . vertexSF    - (Optional) `PetscSF` describing complete vertex ownership
628960225df5SJacob Faibussowitsch - verticesAdj - (Optional) vertex adjacency array
6290a47d0d45SMatthew G. Knepley 
6291b09969d6SVaclav Hapla   Level: intermediate
6292a47d0d45SMatthew G. Knepley 
6293a1cb98faSBarry Smith   Notes:
6294a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
6295a1cb98faSBarry Smith   `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
6296a1cb98faSBarry Smith 
6297a1cb98faSBarry Smith   See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters.
6298a1cb98faSBarry Smith 
6299a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
6300a1cb98faSBarry Smith 
63011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
6302a47d0d45SMatthew G. Knepley @*/
6303ce78bad3SBarry Smith 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[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdj[], DM *dm)
6304d71ae5a4SJacob Faibussowitsch {
6305a47d0d45SMatthew G. Knepley   PetscSF sfVert;
6306a47d0d45SMatthew G. Knepley 
6307a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
63089566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
63099566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
6310a47d0d45SMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
6311064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
63129566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
63139566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj));
6314a47d0d45SMatthew G. Knepley   if (interpolate) {
63155fd9971aSMatthew G. Knepley     DM idm;
6316a47d0d45SMatthew G. Knepley 
63179566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
63189566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
6319a47d0d45SMatthew G. Knepley     *dm = idm;
6320a47d0d45SMatthew G. Knepley   }
63219566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
632218d54ad4SMichael Lange   if (vertexSF) *vertexSF = sfVert;
63239566063dSJacob Faibussowitsch   else PetscCall(PetscSFDestroy(&sfVert));
63243ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6325a47d0d45SMatthew G. Knepley }
6326a47d0d45SMatthew G. Knepley 
6327cc4c1da9SBarry Smith /*@
6328b0fe842aSMatthew G. Knepley   DMPlexCreateFromCellSectionParallel - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) and supports multiple celltypes
6329b0fe842aSMatthew G. Knepley 
6330b0fe842aSMatthew G. Knepley   Collective
6331b0fe842aSMatthew G. Knepley 
6332b0fe842aSMatthew G. Knepley   Input Parameters:
6333b0fe842aSMatthew G. Knepley + comm         - The communicator
6334b0fe842aSMatthew G. Knepley . dim          - The topological dimension of the mesh
6335b0fe842aSMatthew G. Knepley . numCells     - The number of cells owned by this process
6336b0fe842aSMatthew G. Knepley . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`
6337b0fe842aSMatthew G. Knepley . NVertices    - The global number of vertices, or `PETSC_DECIDE`
6338b0fe842aSMatthew G. Knepley . cellSection  - The `PetscSection` giving the number of vertices for each cell (layout of cells)
6339b0fe842aSMatthew G. Knepley . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
6340b0fe842aSMatthew G. Knepley . cells        - An array of the global vertex numbers for each cell
6341b0fe842aSMatthew G. Knepley . spaceDim     - The spatial dimension used for coordinates
6342b0fe842aSMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6343b0fe842aSMatthew G. Knepley 
6344b0fe842aSMatthew G. Knepley   Output Parameters:
6345b0fe842aSMatthew G. Knepley + dm          - The `DM`
6346b0fe842aSMatthew G. Knepley . vertexSF    - (Optional) `PetscSF` describing complete vertex ownership
6347b0fe842aSMatthew G. Knepley - verticesAdj - (Optional) vertex adjacency array
6348b0fe842aSMatthew G. Knepley 
6349b0fe842aSMatthew G. Knepley   Level: intermediate
6350b0fe842aSMatthew G. Knepley 
6351b0fe842aSMatthew G. Knepley   Notes:
6352b0fe842aSMatthew G. Knepley   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
6353b0fe842aSMatthew G. Knepley   `DMPlexBuildFromCellSectionParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
6354b0fe842aSMatthew G. Knepley 
6355b0fe842aSMatthew G. Knepley   See `DMPlexBuildFromCellSectionParallel()` for an example and details about the topology-related parameters.
6356b0fe842aSMatthew G. Knepley 
6357b0fe842aSMatthew G. Knepley   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
6358b0fe842aSMatthew G. Knepley 
6359b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
6360b0fe842aSMatthew G. Knepley @*/
6361ce78bad3SBarry Smith 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[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdj[], DM *dm)
6362b0fe842aSMatthew G. Knepley {
6363b0fe842aSMatthew G. Knepley   PetscSF sfVert;
6364b0fe842aSMatthew G. Knepley 
6365b0fe842aSMatthew G. Knepley   PetscFunctionBegin;
6366b0fe842aSMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
6367b0fe842aSMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
6368b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
6369b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
6370b0fe842aSMatthew G. Knepley   PetscCall(DMSetDimension(*dm, dim));
6371b0fe842aSMatthew G. Knepley   PetscCall(DMPlexBuildFromCellSectionParallel(*dm, numCells, numVertices, NVertices, cellSection, cells, &sfVert, verticesAdj));
6372b0fe842aSMatthew G. Knepley   if (interpolate) {
6373b0fe842aSMatthew G. Knepley     DM idm;
6374b0fe842aSMatthew G. Knepley 
6375b0fe842aSMatthew G. Knepley     PetscCall(DMPlexInterpolate(*dm, &idm));
6376b0fe842aSMatthew G. Knepley     PetscCall(DMDestroy(dm));
6377b0fe842aSMatthew G. Knepley     *dm = idm;
6378b0fe842aSMatthew G. Knepley   }
6379b0fe842aSMatthew G. Knepley   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
6380b0fe842aSMatthew G. Knepley   if (vertexSF) *vertexSF = sfVert;
6381b0fe842aSMatthew G. Knepley   else PetscCall(PetscSFDestroy(&sfVert));
6382b0fe842aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
6383b0fe842aSMatthew G. Knepley }
6384b0fe842aSMatthew G. Knepley 
6385b0fe842aSMatthew G. Knepley /*@
6386a1cb98faSBarry Smith   DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output)
6387a1cb98faSBarry Smith 
638820f4b53cSBarry Smith   Collective; No Fortran Support
63899298eaa6SMatthew G Knepley 
63909298eaa6SMatthew G Knepley   Input Parameters:
6391a1cb98faSBarry Smith + dm          - The `DM`
6392b09969d6SVaclav Hapla . numCells    - The number of cells owned by this process
6393a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE`
63949298eaa6SMatthew G Knepley . numCorners  - The number of vertices for each cell
6395a3b724e8SBarry Smith - cells       - An array of `numCells` x `numCorners` numbers, the global vertex numbers for each cell
63969298eaa6SMatthew G Knepley 
6397b09969d6SVaclav Hapla   Level: advanced
63989298eaa6SMatthew G Knepley 
6399b09969d6SVaclav Hapla   Notes:
6400b09969d6SVaclav Hapla   Two triangles sharing a face
6401a1cb98faSBarry Smith .vb
64029298eaa6SMatthew G Knepley 
6403a1cb98faSBarry Smith         2
6404a1cb98faSBarry Smith       / | \
6405a1cb98faSBarry Smith      /  |  \
6406a1cb98faSBarry Smith     /   |   \
6407a1cb98faSBarry Smith    0  0 | 1  3
6408a1cb98faSBarry Smith     \   |   /
6409a1cb98faSBarry Smith      \  |  /
6410a1cb98faSBarry Smith       \ | /
6411a1cb98faSBarry Smith         1
6412a1cb98faSBarry Smith .ve
6413a1cb98faSBarry Smith   would have input
6414a1cb98faSBarry Smith .vb
6415a1cb98faSBarry Smith   numCells = 2, numVertices = 4
6416a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
6417a1cb98faSBarry Smith .ve
6418a1cb98faSBarry Smith   which would result in the `DMPLEX`
6419a1cb98faSBarry Smith .vb
6420a1cb98faSBarry Smith 
6421a1cb98faSBarry Smith         4
6422a1cb98faSBarry Smith       / | \
6423a1cb98faSBarry Smith      /  |  \
6424a1cb98faSBarry Smith     /   |   \
6425a1cb98faSBarry Smith    2  0 | 1  5
6426a1cb98faSBarry Smith     \   |   /
6427a1cb98faSBarry Smith      \  |  /
6428a1cb98faSBarry Smith       \ | /
6429a1cb98faSBarry Smith         3
6430a1cb98faSBarry Smith .ve
6431a1cb98faSBarry Smith 
6432a1cb98faSBarry Smith   If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1.
643325b6865aSVaclav Hapla 
64341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()`
6435b09969d6SVaclav Hapla @*/
6436d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[])
6437d71ae5a4SJacob Faibussowitsch {
6438961cfab0SVaclav Hapla   PetscInt *cones, c, p, dim;
6439b09969d6SVaclav Hapla 
6440b09969d6SVaclav Hapla   PetscFunctionBegin;
64419566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
64429566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
644325b6865aSVaclav Hapla   /* Get/check global number of vertices */
644425b6865aSVaclav Hapla   {
644525b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
644625b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
644725b6865aSVaclav Hapla 
644825b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
64491690c2aeSBarry Smith     NVerticesInCells = PETSC_INT_MIN;
64509371c9d4SSatish Balay     for (i = 0; i < len; i++)
64519371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
645225b6865aSVaclav Hapla     ++NVerticesInCells;
645325b6865aSVaclav Hapla 
645425b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells;
64559371c9d4SSatish Balay     else
64569371c9d4SSatish 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);
645725b6865aSVaclav Hapla   }
64589566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
645948a46eb9SPierre Jolivet   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
64609566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
64619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
6462b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
6463ad540459SPierre Jolivet     for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells;
6464b09969d6SVaclav Hapla   }
64659566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
64669566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
64679566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
64683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6469b09969d6SVaclav Hapla }
6470b09969d6SVaclav Hapla 
6471cc4c1da9SBarry Smith /*@
6472a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
6473a1cb98faSBarry Smith 
6474cc4c1da9SBarry Smith   Collective
6475b09969d6SVaclav Hapla 
6476b09969d6SVaclav Hapla   Input Parameters:
6477a1cb98faSBarry Smith + dm           - The `DM`
6478b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
6479b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6480b09969d6SVaclav Hapla 
6481b09969d6SVaclav Hapla   Level: advanced
6482b09969d6SVaclav Hapla 
64831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()`
6484b09969d6SVaclav Hapla @*/
6485d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[])
6486d71ae5a4SJacob Faibussowitsch {
6487b09969d6SVaclav Hapla   PetscSection coordSection;
6488b09969d6SVaclav Hapla   Vec          coordinates;
6489b09969d6SVaclav Hapla   DM           cdm;
6490b09969d6SVaclav Hapla   PetscScalar *coords;
64911edcf0b2SVaclav Hapla   PetscInt     v, vStart, vEnd, d;
6492b09969d6SVaclav Hapla 
6493b09969d6SVaclav Hapla   PetscFunctionBegin;
64949566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
64959566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
64961dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
64979566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
64989566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
64999566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
65009566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
65019566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
65021edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
65039566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
65049566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
6505b09969d6SVaclav Hapla   }
65069566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
6507b09969d6SVaclav Hapla 
65089566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
65099566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(cdm, &coordinates));
65109566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
65119566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
65129566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(coordinates, &coords));
65131edcf0b2SVaclav Hapla   for (v = 0; v < vEnd - vStart; ++v) {
6514ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d];
6515b09969d6SVaclav Hapla   }
65169566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
65179566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
65189566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
65199566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
65203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6521b09969d6SVaclav Hapla }
6522b09969d6SVaclav Hapla 
6523b09969d6SVaclav Hapla /*@
6524a1cb98faSBarry Smith   DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input
65253df08285SMatthew G. Knepley 
6526a1cb98faSBarry Smith   Collective
6527b09969d6SVaclav Hapla 
6528b09969d6SVaclav Hapla   Input Parameters:
6529b09969d6SVaclav Hapla + comm         - The communicator
6530b09969d6SVaclav Hapla . dim          - The topological dimension of the mesh
65313df08285SMatthew G. Knepley . numCells     - The number of cells, only on process 0
6532a1cb98faSBarry Smith . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0
65333df08285SMatthew G. Knepley . numCorners   - The number of vertices for each cell, only on process 0
6534b09969d6SVaclav Hapla . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
6535ce78bad3SBarry Smith . cells        - An array of $ numCells \times numCorners$ numbers, the vertices for each cell, only on process 0
6536b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
6537ce78bad3SBarry Smith - vertexCoords - An array of $ numVertices \times spaceDim$ numbers, the coordinates of each vertex, only on process 0
6538b09969d6SVaclav Hapla 
6539b09969d6SVaclav Hapla   Output Parameter:
6540a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0
654125b6865aSVaclav Hapla 
6542b09969d6SVaclav Hapla   Level: intermediate
6543b09969d6SVaclav Hapla 
6544a1cb98faSBarry Smith   Notes:
6545a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`,
6546a1cb98faSBarry Smith   `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()`
6547a1cb98faSBarry Smith 
6548a1cb98faSBarry Smith   See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters.
6549a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters.
6550a1cb98faSBarry Smith   See `DMPlexCreateFromCellListParallelPetsc()` for parallel input
6551a1cb98faSBarry Smith 
65521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
65539298eaa6SMatthew G Knepley @*/
6554d71ae5a4SJacob 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)
6555d71ae5a4SJacob Faibussowitsch {
65563df08285SMatthew G. Knepley   PetscMPIInt rank;
65579298eaa6SMatthew G Knepley 
65589298eaa6SMatthew G Knepley   PetscFunctionBegin;
655928b400f6SJacob 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.");
65609566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
65619566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
65629566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
65639566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
6564c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells));
65659566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL));
65669298eaa6SMatthew G Knepley   if (interpolate) {
65675fd9971aSMatthew G. Knepley     DM idm;
65689298eaa6SMatthew G Knepley 
65699566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
65709566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
65719298eaa6SMatthew G Knepley     *dm = idm;
65729298eaa6SMatthew G Knepley   }
6573c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords));
65749566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL));
65753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65769298eaa6SMatthew G Knepley }
65779298eaa6SMatthew G Knepley 
6578939f6067SMatthew G. Knepley /*@
657920f4b53cSBarry Smith   DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a `DM`
6580939f6067SMatthew G. Knepley 
6581939f6067SMatthew G. Knepley   Input Parameters:
658220f4b53cSBarry Smith + dm               - The empty `DM` object, usually from `DMCreate()` and `DMSetDimension()`
6583939f6067SMatthew G. Knepley . depth            - The depth of the DAG
6584ce78bad3SBarry Smith . numPoints        - Array of size $ depth + 1 $ containing the number of points at each `depth`
6585939f6067SMatthew G. Knepley . coneSize         - The cone size of each point
6586939f6067SMatthew G. Knepley . cones            - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
6587939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point
6588ce78bad3SBarry Smith - vertexCoords     - An array of $ numPoints[0] \times spacedim $ numbers representing the coordinates of each vertex, with `spacedim` the value set via `DMSetCoordinateDim()`
6589939f6067SMatthew G. Knepley 
6590939f6067SMatthew G. Knepley   Output Parameter:
659120f4b53cSBarry Smith . dm - The `DM`
659220f4b53cSBarry Smith 
659320f4b53cSBarry Smith   Level: advanced
6594939f6067SMatthew G. Knepley 
6595a1cb98faSBarry Smith   Note:
6596a1cb98faSBarry Smith   Two triangles sharing a face would have input
6597a1cb98faSBarry Smith .vb
6598a1cb98faSBarry Smith   depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
6599a1cb98faSBarry Smith   cones = [2 3 4  3 5 4], coneOrientations = [0 0 0  0 0 0]
6600a1cb98faSBarry Smith  vertexCoords = [-1.0 0.0  0.0 -1.0  0.0 1.0  1.0 0.0]
6601a1cb98faSBarry Smith .ve
6602939f6067SMatthew G. Knepley   which would result in the DMPlex
6603a1cb98faSBarry Smith .vb
6604a1cb98faSBarry Smith         4
6605a1cb98faSBarry Smith       / | \
6606a1cb98faSBarry Smith      /  |  \
6607a1cb98faSBarry Smith     /   |   \
6608a1cb98faSBarry Smith    2  0 | 1  5
6609a1cb98faSBarry Smith     \   |   /
6610a1cb98faSBarry Smith      \  |  /
6611a1cb98faSBarry Smith       \ | /
6612a1cb98faSBarry Smith         3
6613a1cb98faSBarry Smith .ve
6614a1cb98faSBarry Smith   Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()`
6615939f6067SMatthew G. Knepley 
6616ce78bad3SBarry Smith   Developer Note:
6617ce78bad3SBarry Smith   This does not create anything so should not have create in the name.
6618ce78bad3SBarry Smith 
66191cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
6620939f6067SMatthew G. Knepley @*/
6621d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
6622d71ae5a4SJacob Faibussowitsch {
66239298eaa6SMatthew G Knepley   Vec          coordinates;
66249298eaa6SMatthew G Knepley   PetscSection coordSection;
66259298eaa6SMatthew G Knepley   PetscScalar *coords;
6626811e8653SToby Isaac   PetscInt     coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off;
66279298eaa6SMatthew G Knepley 
66289298eaa6SMatthew G Knepley   PetscFunctionBegin;
66299566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
66309566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
663163a3b9bcSJacob Faibussowitsch   PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim);
66329298eaa6SMatthew G Knepley   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
66339566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, pStart, pEnd));
66349298eaa6SMatthew G Knepley   for (p = pStart; p < pEnd; ++p) {
66359566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart]));
6636ad540459SPierre Jolivet     if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart;
663797e052ccSToby Isaac   }
66381dca8a05SBarry Smith   PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]);
66399566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm)); /* Allocate space for cones */
66409298eaa6SMatthew G Knepley   for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) {
66419566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(dm, p, &cones[off]));
66429566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off]));
66439298eaa6SMatthew G Knepley   }
66449566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
66459566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
66469298eaa6SMatthew G Knepley   /* Build coordinates */
66479566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
66489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
66499566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
66509566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0]));
66519298eaa6SMatthew G Knepley   for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) {
66529566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
66539566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
66549298eaa6SMatthew G Knepley   }
66559566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
66569566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
66579566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
66589566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
66599566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
666058b7e2c1SStefano Zampini   PetscCall(VecSetBlockSize(coordinates, PetscMax(dimEmbed, 1)));
66619566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
66629318fe57SMatthew G. Knepley   if (vertexCoords) {
66639566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
66649298eaa6SMatthew G Knepley     for (v = 0; v < numPoints[0]; ++v) {
66659298eaa6SMatthew G Knepley       PetscInt off;
66669298eaa6SMatthew G Knepley 
66679566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off));
6668ad540459SPierre Jolivet       for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d];
66699298eaa6SMatthew G Knepley     }
66709318fe57SMatthew G. Knepley   }
66719566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
66729566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
66739566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
66743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66759298eaa6SMatthew G Knepley }
66768415267dSToby Isaac 
6677a4e35b19SJacob Faibussowitsch /*
6678a1cb98faSBarry Smith   DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file.
6679a1cb98faSBarry Smith 
6680a1cb98faSBarry Smith   Collective
66818ca92349SMatthew G. Knepley 
66828ca92349SMatthew G. Knepley + comm        - The MPI communicator
66838ca92349SMatthew G. Knepley . filename    - Name of the .dat file
66848ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
66858ca92349SMatthew G. Knepley 
66868ca92349SMatthew G. Knepley   Output Parameter:
6687a1cb98faSBarry Smith . dm  - The `DM` object representing the mesh
66888ca92349SMatthew G. Knepley 
66898ca92349SMatthew G. Knepley   Level: beginner
66908ca92349SMatthew G. Knepley 
6691a1cb98faSBarry Smith   Note:
6692a1cb98faSBarry Smith   The format is the simplest possible:
6693a1cb98faSBarry Smith .vb
6694d0812dedSMatthew G. Knepley   dim Ne Nv Nc Nl
6695d0812dedSMatthew G. Knepley   v_1 v_2 ... v_Nc
6696d0812dedSMatthew G. Knepley   ...
6697d0812dedSMatthew G. Knepley   x y z marker_1 ... marker_Nl
6698a1cb98faSBarry Smith .ve
6699a1cb98faSBarry Smith 
6700a1cb98faSBarry Smith   Developer Note:
6701a1cb98faSBarry Smith   Should use a `PetscViewer` not a filename
6702a1cb98faSBarry Smith 
67036afe31f6SMartin Diehl .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
6704a4e35b19SJacob Faibussowitsch */
6705ff6a9541SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
6706d71ae5a4SJacob Faibussowitsch {
67078ca92349SMatthew G. Knepley   DMLabel      marker;
67088ca92349SMatthew G. Knepley   PetscViewer  viewer;
67098ca92349SMatthew G. Knepley   Vec          coordinates;
67108ca92349SMatthew G. Knepley   PetscSection coordSection;
67118ca92349SMatthew G. Knepley   PetscScalar *coords;
67128ca92349SMatthew G. Knepley   char         line[PETSC_MAX_PATH_LEN];
6713d0812dedSMatthew G. Knepley   PetscInt     cdim, coordSize, v, c, d;
67148ca92349SMatthew G. Knepley   PetscMPIInt  rank;
6715d0812dedSMatthew G. Knepley   int          snum, dim, Nv, Nc, Ncn, Nl;
67168ca92349SMatthew G. Knepley 
67178ca92349SMatthew G. Knepley   PetscFunctionBegin;
67189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
67199566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
67209566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
67219566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
67229566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
6723dd400576SPatrick Sanan   if (rank == 0) {
6724d0812dedSMatthew G. Knepley     PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING));
6725d0812dedSMatthew G. Knepley     snum = sscanf(line, "%d %d %d %d %d", &dim, &Nc, &Nv, &Ncn, &Nl);
6726d0812dedSMatthew G. Knepley     PetscCheck(snum == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
672725ce1634SJed Brown   } else {
6728f8d5e320SMatthew G. Knepley     Nc = Nv = Ncn = Nl = 0;
67298ca92349SMatthew G. Knepley   }
6730d0812dedSMatthew G. Knepley   PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm));
6731835f2295SStefano Zampini   cdim = dim;
67329566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
67339566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
67349566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
6735835f2295SStefano Zampini   PetscCall(DMSetDimension(*dm, dim));
67369566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, cdim));
67378ca92349SMatthew G. Knepley   /* Read topology */
6738dd400576SPatrick Sanan   if (rank == 0) {
6739f8d5e320SMatthew G. Knepley     char     format[PETSC_MAX_PATH_LEN];
6740f8d5e320SMatthew G. Knepley     PetscInt cone[8];
67418ca92349SMatthew G. Knepley     int      vbuf[8], v;
67428ca92349SMatthew G. Knepley 
67439371c9d4SSatish Balay     for (c = 0; c < Ncn; ++c) {
67449371c9d4SSatish Balay       format[c * 3 + 0] = '%';
67459371c9d4SSatish Balay       format[c * 3 + 1] = 'd';
67469371c9d4SSatish Balay       format[c * 3 + 2] = ' ';
67479371c9d4SSatish Balay     }
6748f8d5e320SMatthew G. Knepley     format[Ncn * 3 - 1] = '\0';
67499566063dSJacob Faibussowitsch     for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn));
67509566063dSJacob Faibussowitsch     PetscCall(DMSetUp(*dm));
67518ca92349SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
67529566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING));
6753f8d5e320SMatthew G. Knepley       switch (Ncn) {
6754d71ae5a4SJacob Faibussowitsch       case 2:
6755d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1]);
6756d71ae5a4SJacob Faibussowitsch         break;
6757d71ae5a4SJacob Faibussowitsch       case 3:
6758d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]);
6759d71ae5a4SJacob Faibussowitsch         break;
6760d71ae5a4SJacob Faibussowitsch       case 4:
6761d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]);
6762d71ae5a4SJacob Faibussowitsch         break;
6763d71ae5a4SJacob Faibussowitsch       case 6:
6764d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]);
6765d71ae5a4SJacob Faibussowitsch         break;
6766d71ae5a4SJacob Faibussowitsch       case 8:
6767d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]);
6768d71ae5a4SJacob Faibussowitsch         break;
6769d71ae5a4SJacob Faibussowitsch       default:
6770d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn);
6771f8d5e320SMatthew G. Knepley       }
677208401ef6SPierre Jolivet       PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
6773f8d5e320SMatthew G. Knepley       for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc;
67748ca92349SMatthew G. Knepley       /* Hexahedra are inverted */
6775f8d5e320SMatthew G. Knepley       if (Ncn == 8) {
67768ca92349SMatthew G. Knepley         PetscInt tmp = cone[1];
67778ca92349SMatthew G. Knepley         cone[1]      = cone[3];
67788ca92349SMatthew G. Knepley         cone[3]      = tmp;
67798ca92349SMatthew G. Knepley       }
67809566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(*dm, c, cone));
67818ca92349SMatthew G. Knepley     }
67828ca92349SMatthew G. Knepley   }
67839566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
67849566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
67858ca92349SMatthew G. Knepley   /* Read coordinates */
67869566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
67879566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
67889566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
67899566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
67908ca92349SMatthew G. Knepley   for (v = Nc; v < Nc + Nv; ++v) {
67919566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
67929566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
67938ca92349SMatthew G. Knepley   }
67949566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
67959566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
67969566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
67979566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
67989566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
67999566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
68009566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
68019566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
6802dd400576SPatrick Sanan   if (rank == 0) {
6803f8d5e320SMatthew G. Knepley     char   format[PETSC_MAX_PATH_LEN];
68048ca92349SMatthew G. Knepley     double x[3];
6805f8d5e320SMatthew G. Knepley     int    l, val[3];
68068ca92349SMatthew G. Knepley 
6807f8d5e320SMatthew G. Knepley     if (Nl) {
68089371c9d4SSatish Balay       for (l = 0; l < Nl; ++l) {
68099371c9d4SSatish Balay         format[l * 3 + 0] = '%';
68109371c9d4SSatish Balay         format[l * 3 + 1] = 'd';
68119371c9d4SSatish Balay         format[l * 3 + 2] = ' ';
68129371c9d4SSatish Balay       }
6813f8d5e320SMatthew G. Knepley       format[Nl * 3 - 1] = '\0';
68149566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
68159566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &marker));
6816f8d5e320SMatthew G. Knepley     }
68178ca92349SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
68189566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING));
6819f8d5e320SMatthew G. Knepley       snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]);
682008401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
6821f8d5e320SMatthew G. Knepley       switch (Nl) {
6822d71ae5a4SJacob Faibussowitsch       case 0:
6823d71ae5a4SJacob Faibussowitsch         snum = 0;
6824d71ae5a4SJacob Faibussowitsch         break;
6825d71ae5a4SJacob Faibussowitsch       case 1:
6826d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0]);
6827d71ae5a4SJacob Faibussowitsch         break;
6828d71ae5a4SJacob Faibussowitsch       case 2:
6829d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1]);
6830d71ae5a4SJacob Faibussowitsch         break;
6831d71ae5a4SJacob Faibussowitsch       case 3:
6832d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1], &val[2]);
6833d71ae5a4SJacob Faibussowitsch         break;
6834d71ae5a4SJacob Faibussowitsch       default:
6835d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl);
6836f8d5e320SMatthew G. Knepley       }
683708401ef6SPierre Jolivet       PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
68388ca92349SMatthew G. Knepley       for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d];
68399566063dSJacob Faibussowitsch       for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l]));
68408ca92349SMatthew G. Knepley     }
68418ca92349SMatthew G. Knepley   }
68429566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
68439566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
68449566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
68459566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
68468ca92349SMatthew G. Knepley   if (interpolate) {
68478ca92349SMatthew G. Knepley     DM      idm;
68488ca92349SMatthew G. Knepley     DMLabel bdlabel;
68498ca92349SMatthew G. Knepley 
68509566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
68519566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
68528ca92349SMatthew G. Knepley     *dm = idm;
68538ca92349SMatthew G. Knepley 
6854f8d5e320SMatthew G. Knepley     if (!Nl) {
68559566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
68569566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &bdlabel));
68579566063dSJacob Faibussowitsch       PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel));
68589566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelComplete(*dm, bdlabel));
68598ca92349SMatthew G. Knepley     }
6860f8d5e320SMatthew G. Knepley   }
68613ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68628ca92349SMatthew G. Knepley }
68638ca92349SMatthew G. Knepley 
6864cc4c1da9SBarry Smith /*@
6865a1cb98faSBarry Smith   DMPlexCreateFromFile - This takes a filename and produces a `DM`
6866a1cb98faSBarry Smith 
6867a1cb98faSBarry Smith   Collective
6868ca522641SMatthew G. Knepley 
6869ca522641SMatthew G. Knepley   Input Parameters:
6870ca522641SMatthew G. Knepley + comm        - The communicator
6871ca522641SMatthew G. Knepley . filename    - A file name
6872a1cb98faSBarry Smith . plexname    - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats
6873ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
6874ca522641SMatthew G. Knepley 
6875ca522641SMatthew G. Knepley   Output Parameter:
6876a1cb98faSBarry Smith . dm - The `DM`
6877ca522641SMatthew G. Knepley 
6878a1cb98faSBarry Smith   Options Database Key:
6879a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5
688002ef0d99SVaclav Hapla 
6881b44f4de4SBarry Smith   Use `-dm_plex_create_ prefix` to pass options to the internal `PetscViewer`, e.g. `-dm_plex_create_viewer_hdf5_collective`
6882bca97951SVaclav Hapla 
6883ca522641SMatthew G. Knepley   Level: beginner
6884ca522641SMatthew G. Knepley 
6885a1cb98faSBarry Smith   Notes:
6886a1cb98faSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
6887a1cb98faSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
6888a1cb98faSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
6889a1cb98faSBarry Smith   The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally
6890a1cb98faSBarry Smith   calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats.
6891a1cb98faSBarry Smith 
68921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()`
6893ca522641SMatthew G. Knepley @*/
6894d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm)
6895d71ae5a4SJacob Faibussowitsch {
6896ef3a5affSJacob Faibussowitsch   const char  extGmsh[]      = ".msh";
6897ef3a5affSJacob Faibussowitsch   const char  extGmsh2[]     = ".msh2";
6898ef3a5affSJacob Faibussowitsch   const char  extGmsh4[]     = ".msh4";
6899ef3a5affSJacob Faibussowitsch   const char  extCGNS[]      = ".cgns";
6900ef3a5affSJacob Faibussowitsch   const char  extExodus[]    = ".exo";
6901ef3a5affSJacob Faibussowitsch   const char  extExodus_e[]  = ".e";
6902ef3a5affSJacob Faibussowitsch   const char  extGenesis[]   = ".gen";
6903ef3a5affSJacob Faibussowitsch   const char  extFluent[]    = ".cas";
6904ef3a5affSJacob Faibussowitsch   const char  extHDF5[]      = ".h5";
69056f2c871aSStefano Zampini   const char  extXDMFHDF5[]  = ".xdmf.h5";
6906ef3a5affSJacob Faibussowitsch   const char  extPLY[]       = ".ply";
69075552b385SBrandon   const char  extEGADSlite[] = ".egadslite";
6908ef3a5affSJacob Faibussowitsch   const char  extEGADS[]     = ".egads";
6909ef3a5affSJacob Faibussowitsch   const char  extIGES[]      = ".igs";
69105552b385SBrandon   const char  extIGES2[]     = ".iges";
6911ef3a5affSJacob Faibussowitsch   const char  extSTEP[]      = ".stp";
69125552b385SBrandon   const char  extSTEP2[]     = ".step";
69135552b385SBrandon   const char  extBREP[]      = ".brep";
6914ef3a5affSJacob Faibussowitsch   const char  extCV[]        = ".dat";
6915ca522641SMatthew G. Knepley   size_t      len;
69165552b385SBrandon   PetscBool   isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isPLY, isEGADSlite, isEGADS, isIGES, isIGES2, isSTEP, isSTEP2, isBREP, isCV, isXDMFHDF5;
6917ca522641SMatthew G. Knepley   PetscMPIInt rank;
6918ca522641SMatthew G. Knepley 
6919ca522641SMatthew G. Knepley   PetscFunctionBegin;
69204f572ea9SToby Isaac   PetscAssertPointer(filename, 2);
69214f572ea9SToby Isaac   if (plexname) PetscAssertPointer(plexname, 3);
69224f572ea9SToby Isaac   PetscAssertPointer(dm, 5);
69239566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
69249566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0));
69259566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
69269566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(filename, &len));
692728b400f6SJacob Faibussowitsch   PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path");
6928ef3a5affSJacob Faibussowitsch 
69299371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \
69309371c9d4SSatish Balay   do { \
6931274aaeaaSJacob Faibussowitsch     PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \
6932274aaeaaSJacob Faibussowitsch     /* don't count the null-terminator at the end */ \
6933274aaeaaSJacob Faibussowitsch     const size_t ext_len = sizeof(extension__) - 1; \
6934274aaeaaSJacob Faibussowitsch     if (len < ext_len) { \
6935ef3a5affSJacob Faibussowitsch       is_extension__ = PETSC_FALSE; \
6936ef3a5affSJacob Faibussowitsch     } else { \
6937274aaeaaSJacob Faibussowitsch       PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \
6938ef3a5affSJacob Faibussowitsch     } \
6939ef3a5affSJacob Faibussowitsch   } while (0)
6940ef3a5affSJacob Faibussowitsch 
6941ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh, isGmsh);
6942ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh2, isGmsh2);
6943ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh4, isGmsh4);
6944ef3a5affSJacob Faibussowitsch   CheckExtension(extCGNS, isCGNS);
6945ef3a5affSJacob Faibussowitsch   CheckExtension(extExodus, isExodus);
6946ef3a5affSJacob Faibussowitsch   if (!isExodus) CheckExtension(extExodus_e, isExodus);
6947ef3a5affSJacob Faibussowitsch   CheckExtension(extGenesis, isGenesis);
6948ef3a5affSJacob Faibussowitsch   CheckExtension(extFluent, isFluent);
6949ef3a5affSJacob Faibussowitsch   CheckExtension(extHDF5, isHDF5);
6950ef3a5affSJacob Faibussowitsch   CheckExtension(extPLY, isPLY);
69515552b385SBrandon   CheckExtension(extEGADSlite, isEGADSlite);
6952ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADS, isEGADS);
6953ef3a5affSJacob Faibussowitsch   CheckExtension(extIGES, isIGES);
69545552b385SBrandon   CheckExtension(extIGES2, isIGES2);
6955ef3a5affSJacob Faibussowitsch   CheckExtension(extSTEP, isSTEP);
69565552b385SBrandon   CheckExtension(extSTEP2, isSTEP2);
69575552b385SBrandon   CheckExtension(extBREP, isBREP);
6958ef3a5affSJacob Faibussowitsch   CheckExtension(extCV, isCV);
69596f2c871aSStefano Zampini   CheckExtension(extXDMFHDF5, isXDMFHDF5);
6960ef3a5affSJacob Faibussowitsch 
6961ef3a5affSJacob Faibussowitsch #undef CheckExtension
6962ef3a5affSJacob Faibussowitsch 
6963de78e4feSLisandro Dalcin   if (isGmsh || isGmsh2 || isGmsh4) {
69649566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm));
6965ca522641SMatthew G. Knepley   } else if (isCGNS) {
69669566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm));
696790c68965SMatthew G. Knepley   } else if (isExodus || isGenesis) {
69689566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm));
69692f0bd6dcSMichael Lange   } else if (isFluent) {
69709566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm));
6971cc2f8f65SMatthew G. Knepley   } else if (isHDF5) {
6972cc2f8f65SMatthew G. Knepley     PetscViewer viewer;
6973cc2f8f65SMatthew G. Knepley 
697443b242b4SVaclav 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 */
69756f2c871aSStefano Zampini     PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &isXDMFHDF5, NULL));
69769566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(comm, &viewer));
69779566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5));
69789566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_"));
69799566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetFromOptions(viewer));
69809566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
69819566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(viewer, filename));
6982cd7e8a5eSksagiyam 
69839566063dSJacob Faibussowitsch     PetscCall(DMCreate(comm, dm));
6984f4f49eeaSPierre Jolivet     PetscCall(PetscObjectSetName((PetscObject)*dm, plexname));
69859566063dSJacob Faibussowitsch     PetscCall(DMSetType(*dm, DMPLEX));
69866f2c871aSStefano Zampini     if (isXDMFHDF5) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF));
69879566063dSJacob Faibussowitsch     PetscCall(DMLoad(*dm, viewer));
69886f2c871aSStefano Zampini     if (isXDMFHDF5) PetscCall(PetscViewerPopFormat(viewer));
69899566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
69905fd9971aSMatthew G. Knepley 
69915fd9971aSMatthew G. Knepley     if (interpolate) {
69925fd9971aSMatthew G. Knepley       DM idm;
69935fd9971aSMatthew G. Knepley 
69949566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm));
69959566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
69965fd9971aSMatthew G. Knepley       *dm = idm;
69975fd9971aSMatthew G. Knepley     }
6998f2801cd6SMatthew G. Knepley   } else if (isPLY) {
69999566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm));
70005552b385SBrandon   } else if (isEGADSlite || isEGADS || isIGES || isIGES2 || isSTEP || isSTEP2 || isBREP) {
70015552b385SBrandon     PetscCall(DMPlexCreateGeomFromFile(comm, filename, dm, isEGADSlite));
70025552b385SBrandon 
70037bee2925SMatthew Knepley     if (!interpolate) {
70047bee2925SMatthew Knepley       DM udm;
70057bee2925SMatthew Knepley 
70069566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(*dm, &udm));
70079566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
70087bee2925SMatthew Knepley       *dm = udm;
70097bee2925SMatthew Knepley     }
70108ca92349SMatthew G. Knepley   } else if (isCV) {
70119566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm));
701298921bdaSJacob Faibussowitsch   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename);
70139566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(plexname, &len));
7014f4f49eeaSPierre Jolivet   if (len) PetscCall(PetscObjectSetName((PetscObject)*dm, plexname));
70159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0));
70163ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7017ca522641SMatthew G. Knepley }
701812b8a6daSStefano Zampini 
7019cc4c1da9SBarry Smith /*@
70209f6c5813SMatthew 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.
70219f6c5813SMatthew G. Knepley 
70220528010dSStefano Zampini   Input Parameters:
70230528010dSStefano Zampini + tr     - The `DMPlexTransform`
70240528010dSStefano Zampini - prefix - An options prefix, or NULL
70259f6c5813SMatthew G. Knepley 
70269f6c5813SMatthew G. Knepley   Output Parameter:
70279f6c5813SMatthew G. Knepley . dm - The `DM`
70289f6c5813SMatthew G. Knepley 
70299f6c5813SMatthew G. Knepley   Level: beginner
70309f6c5813SMatthew G. Knepley 
703120f4b53cSBarry Smith   Notes:
703220f4b53cSBarry 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.
703320f4b53cSBarry Smith 
70349f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
70359f6c5813SMatthew G. Knepley @*/
70360528010dSStefano Zampini PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, const char prefix[], DM *dm)
70379f6c5813SMatthew G. Knepley {
70380528010dSStefano Zampini   DM           bdm, bcdm, cdm;
70390528010dSStefano Zampini   Vec          coordinates, coordinatesNew;
70400528010dSStefano Zampini   PetscSection cs;
7041817b2c36SMatthew G. Knepley   PetscInt     cdim, Nl;
70429f6c5813SMatthew G. Knepley 
70439f6c5813SMatthew G. Knepley   PetscFunctionBegin;
70449f6c5813SMatthew G. Knepley   PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm));
70459f6c5813SMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
70460528010dSStefano Zampini   ((DM_Plex *)(*dm)->data)->interpolated = DMPLEX_INTERPOLATED_FULL;
70470528010dSStefano Zampini   // Handle coordinates
70480528010dSStefano Zampini   PetscCall(DMPlexTransformGetDM(tr, &bdm));
7049817b2c36SMatthew G. Knepley   PetscCall(DMPlexTransformSetDimensions(tr, bdm, *dm));
7050817b2c36SMatthew G. Knepley   PetscCall(DMGetCoordinateDim(*dm, &cdim));
70510528010dSStefano Zampini   PetscCall(DMGetCoordinateDM(bdm, &bcdm));
70520528010dSStefano Zampini   PetscCall(DMGetCoordinateDM(*dm, &cdm));
70530528010dSStefano Zampini   PetscCall(DMCopyDisc(bcdm, cdm));
70540528010dSStefano Zampini   PetscCall(DMGetLocalSection(cdm, &cs));
70550528010dSStefano Zampini   PetscCall(PetscSectionSetNumFields(cs, 1));
70560528010dSStefano Zampini   PetscCall(PetscSectionSetFieldComponents(cs, 0, cdim));
70570528010dSStefano Zampini   PetscCall(DMGetCoordinatesLocal(bdm, &coordinates));
70580528010dSStefano Zampini   PetscCall(VecDuplicate(coordinates, &coordinatesNew));
70590528010dSStefano Zampini   PetscCall(VecCopy(coordinates, coordinatesNew));
70600528010dSStefano Zampini   PetscCall(DMSetCoordinatesLocal(*dm, coordinatesNew));
70610528010dSStefano Zampini   PetscCall(VecDestroy(&coordinatesNew));
70629f6c5813SMatthew G. Knepley 
70639f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)tr));
70649f6c5813SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr));
70659f6c5813SMatthew G. Knepley   ((DM_Plex *)(*dm)->data)->tr = tr;
70660528010dSStefano Zampini   PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE));
70670528010dSStefano Zampini   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix));
70680528010dSStefano Zampini   PetscCall(DMSetFromOptions(*dm));
70699f6c5813SMatthew G. Knepley 
70709f6c5813SMatthew G. Knepley   PetscCall(DMGetNumLabels(bdm, &Nl));
70719f6c5813SMatthew G. Knepley   for (PetscInt l = 0; l < Nl; ++l) {
70729f6c5813SMatthew G. Knepley     DMLabel     label, labelNew;
70739f6c5813SMatthew G. Knepley     const char *lname;
70749f6c5813SMatthew G. Knepley     PetscBool   isDepth, isCellType;
70759f6c5813SMatthew G. Knepley 
70769f6c5813SMatthew G. Knepley     PetscCall(DMGetLabelName(bdm, l, &lname));
70779f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "depth", &isDepth));
70789f6c5813SMatthew G. Knepley     if (isDepth) continue;
70799f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "celltype", &isCellType));
70809f6c5813SMatthew G. Knepley     if (isCellType) continue;
70819f6c5813SMatthew G. Knepley     PetscCall(DMCreateLabel(*dm, lname));
70829f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(bdm, lname, &label));
70839f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(*dm, lname, &labelNew));
70849f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL));
70859f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetLabel(labelNew, label));
70869f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetTransform(labelNew, tr));
70879f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetUp(labelNew));
70889f6c5813SMatthew G. Knepley   }
70893ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
70909f6c5813SMatthew G. Knepley }
7091