xref: /petsc/src/dm/impls/plex/plexcreate.c (revision f536a3c1ff77ec5b1c69bc9cabc74b5fadba8398)
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`
2944c712d99Sksagiyam . localized - Flag to create a localized (DG) coordinate space
295e65c294aSksagiyam - project   - Flag to project current coordinates into the space
2969318fe57SMatthew G. Knepley 
2979318fe57SMatthew G. Knepley   Level: advanced
2989318fe57SMatthew G. Knepley 
299e65c294aSksagiyam .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPointFn`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()`, `DMPlexSetCoordinateMap()`
3009318fe57SMatthew G. Knepley @*/
301e65c294aSksagiyam PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscBool localized, PetscBool project)
302d71ae5a4SJacob Faibussowitsch {
303e44f6aebSMatthew G. Knepley   PetscFE  fe = NULL;
3049318fe57SMatthew G. Knepley   DM       cdm;
305ac9d17c7SMatthew G. Knepley   PetscInt dim, cdim, dE, qorder, height;
3069318fe57SMatthew G. Knepley 
307e44f6aebSMatthew G. Knepley   PetscFunctionBegin;
3089566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
309ac9d17c7SMatthew G. Knepley   cdim = dim;
3109566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
3119318fe57SMatthew G. Knepley   qorder = degree;
312e44f6aebSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
313d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)cdm);
314dc431b0cSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0));
315ac9d17c7SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_coordinate_dim", "Set the coordinate dimension", "DMPlexCreateCoordinateSpace", cdim, &cdim, NULL, dim));
316d0609cedSBarry Smith   PetscOptionsEnd();
3171df12153SMatthew G. Knepley   PetscCall(DMPlexGetVTKCellHeight(dm, &height));
318ac9d17c7SMatthew G. Knepley   if (cdim > dim) {
319ac9d17c7SMatthew G. Knepley     DM           cdm;
320ac9d17c7SMatthew G. Knepley     PetscSection cs, csNew;
321ac9d17c7SMatthew G. Knepley     Vec          coordinates, coordinatesNew;
322ac9d17c7SMatthew G. Knepley     VecType      vectype;
323ac9d17c7SMatthew G. Knepley     IS           idx;
324ac9d17c7SMatthew G. Knepley     PetscInt    *indices;
325ac9d17c7SMatthew G. Knepley     PetscInt     bs, n;
326ac9d17c7SMatthew G. Knepley 
327ac9d17c7SMatthew G. Knepley     // Recreate coordinate section
328ac9d17c7SMatthew G. Knepley     {
329ac9d17c7SMatthew G. Knepley       const char *fieldName = NULL, *compName = NULL;
330ac9d17c7SMatthew G. Knepley       PetscInt    Nc, pStart, pEnd;
331ac9d17c7SMatthew G. Knepley 
332ac9d17c7SMatthew G. Knepley       PetscCall(DMGetCoordinateDM(dm, &cdm));
333ac9d17c7SMatthew G. Knepley       PetscCall(DMGetLocalSection(cdm, &cs));
334ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cs), &csNew));
335ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetNumFields(csNew, 1));
336ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionGetFieldName(cs, 0, &fieldName));
337ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetFieldName(csNew, 0, fieldName));
338ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionGetFieldComponents(cs, 0, &Nc));
339ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetFieldComponents(csNew, 0, cdim));
340ac9d17c7SMatthew G. Knepley       for (PetscInt c = 0; c < Nc; ++c) {
341ac9d17c7SMatthew G. Knepley         PetscCall(PetscSectionGetComponentName(cs, 0, c, &compName));
342ac9d17c7SMatthew G. Knepley         PetscCall(PetscSectionSetComponentName(csNew, 0, c, compName));
343ac9d17c7SMatthew G. Knepley       }
344ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionGetChart(cs, &pStart, &pEnd));
345ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetChart(csNew, pStart, pEnd));
346ac9d17c7SMatthew G. Knepley       for (PetscInt p = pStart; p < pEnd; ++p) {
347530e699aSMatthew G. Knepley         PetscInt dof;
348530e699aSMatthew G. Knepley 
349530e699aSMatthew G. Knepley         PetscCall(PetscSectionGetDof(cs, p, &dof));
350530e699aSMatthew G. Knepley         if (dof) {
351ac9d17c7SMatthew G. Knepley           PetscCall(PetscSectionSetDof(csNew, p, cdim));
352ac9d17c7SMatthew G. Knepley           PetscCall(PetscSectionSetFieldDof(csNew, p, 0, cdim));
353ac9d17c7SMatthew G. Knepley         }
354530e699aSMatthew G. Knepley       }
355ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetUp(csNew));
356ac9d17c7SMatthew G. Knepley     }
357ac9d17c7SMatthew G. Knepley     PetscCall(DMSetLocalSection(cdm, csNew));
358ac9d17c7SMatthew G. Knepley     PetscCall(PetscSectionDestroy(&csNew));
359530e699aSMatthew G. Knepley     // Reset coordinate dimension for coordinate DM
360530e699aSMatthew G. Knepley     PetscCall(DMSetCoordinateDim(cdm, cdim));
361530e699aSMatthew G. Knepley     PetscCall(DMSetCoordinateField(cdm, NULL));
362ac9d17c7SMatthew G. Knepley     // Inject coordinates into higher dimension
363ac9d17c7SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
364ac9d17c7SMatthew G. Knepley     PetscCall(VecGetBlockSize(coordinates, &bs));
365ac9d17c7SMatthew G. Knepley     PetscCheck(bs == dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension");
366ac9d17c7SMatthew G. Knepley     PetscCall(VecCreate(PetscObjectComm((PetscObject)coordinates), &coordinatesNew));
367ac9d17c7SMatthew G. Knepley     PetscCall(VecGetType(coordinates, &vectype));
368ac9d17c7SMatthew G. Knepley     PetscCall(VecSetType(coordinatesNew, vectype));
369ac9d17c7SMatthew G. Knepley     PetscCall(VecGetLocalSize(coordinates, &n));
370ac9d17c7SMatthew G. Knepley     PetscCheck(!(n % bs), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension");
371ac9d17c7SMatthew G. Knepley     n /= bs;
372ac9d17c7SMatthew G. Knepley     PetscCall(VecSetSizes(coordinatesNew, n * cdim, PETSC_DETERMINE));
373ac9d17c7SMatthew G. Knepley     PetscCall(VecSetUp(coordinatesNew));
374ac9d17c7SMatthew G. Knepley     PetscCall(PetscMalloc1(n * bs, &indices));
375ac9d17c7SMatthew G. Knepley     for (PetscInt i = 0; i < n; ++i)
376ac9d17c7SMatthew G. Knepley       for (PetscInt b = 0; b < bs; ++b) indices[i * bs + b] = i * cdim + b;
377ac9d17c7SMatthew G. Knepley     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n * bs, indices, PETSC_OWN_POINTER, &idx));
378ac9d17c7SMatthew G. Knepley     PetscCall(VecISCopy(coordinatesNew, idx, SCATTER_FORWARD, coordinates));
379ac9d17c7SMatthew G. Knepley     PetscCall(ISDestroy(&idx));
380ac9d17c7SMatthew G. Knepley     PetscCall(DMSetCoordinatesLocal(dm, coordinatesNew));
381ac9d17c7SMatthew G. Knepley     PetscCall(VecDestroy(&coordinatesNew));
382ac9d17c7SMatthew G. Knepley     PetscCall(DMSetCoordinateDim(dm, cdim));
383ac9d17c7SMatthew G. Knepley     {
384ac9d17c7SMatthew G. Knepley       PetscInt gn;
385ac9d17c7SMatthew G. Knepley 
386ac9d17c7SMatthew G. Knepley       PetscCall(DMGetCoordinates(dm, &coordinatesNew));
387ac9d17c7SMatthew G. Knepley       PetscCall(VecGetLocalSize(coordinatesNew, &gn));
388ac9d17c7SMatthew 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);
389ac9d17c7SMatthew G. Knepley     }
390ac9d17c7SMatthew G. Knepley     dE      = cdim;
391530e699aSMatthew G. Knepley     project = PETSC_FALSE;
392ac9d17c7SMatthew G. Knepley   }
393e44f6aebSMatthew G. Knepley   if (degree >= 0) {
394e44f6aebSMatthew G. Knepley     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
395e44f6aebSMatthew G. Knepley     PetscInt       cStart, cEnd, gct;
396dc431b0cSMatthew G. Knepley 
3971df12153SMatthew G. Knepley     PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd));
398dc431b0cSMatthew G. Knepley     if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct));
399e44f6aebSMatthew G. Knepley     gct = (PetscInt)ct;
400462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &gct, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm)));
401e44f6aebSMatthew G. Knepley     ct = (DMPolytopeType)gct;
402e44f6aebSMatthew G. Knepley     // Work around current bug in PetscDualSpaceSetUp_Lagrange()
403e44f6aebSMatthew G. Knepley     //   Can be seen in plex_tutorials-ex10_1
4044c712d99Sksagiyam     if (ct != DM_POLYTOPE_SEG_PRISM_TENSOR && ct != DM_POLYTOPE_TRI_PRISM_TENSOR && ct != DM_POLYTOPE_QUAD_PRISM_TENSOR) {
4054c712d99Sksagiyam       PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe));
4064c712d99Sksagiyam       if (localized) {
4074c712d99Sksagiyam         PetscFE dgfe = NULL;
4084c712d99Sksagiyam 
4094c712d99Sksagiyam         PetscCall(PetscFECreateBrokenElement(fe, &dgfe));
4104c712d99Sksagiyam         PetscCall(PetscFEDestroy(&fe));
4114c712d99Sksagiyam         fe = dgfe;
4124f9ab2b4SJed Brown       }
4134c712d99Sksagiyam     }
4144c712d99Sksagiyam   }
4154c712d99Sksagiyam   PetscCall(DMSetCoordinateDisc(dm, fe, localized, project));
4169566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
4173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4189318fe57SMatthew G. Knepley }
4199318fe57SMatthew G. Knepley 
4201df5d5c5SMatthew G. Knepley /*@
4211df5d5c5SMatthew G. Knepley   DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement.
4221df5d5c5SMatthew G. Knepley 
423d083f849SBarry Smith   Collective
4241df5d5c5SMatthew G. Knepley 
4251df5d5c5SMatthew G. Knepley   Input Parameters:
426a1cb98faSBarry Smith + comm            - The communicator for the `DM` object
4271df5d5c5SMatthew G. Knepley . dim             - The spatial dimension
4281df5d5c5SMatthew G. Knepley . simplex         - Flag for simplicial cells, otherwise they are tensor product cells
4291df5d5c5SMatthew G. Knepley . interpolate     - Flag to create intermediate mesh pieces (edges, faces)
4301df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell
4311df5d5c5SMatthew G. Knepley 
4321df5d5c5SMatthew G. Knepley   Output Parameter:
43360225df5SJacob Faibussowitsch . newdm - The `DM` object
4341df5d5c5SMatthew G. Knepley 
4351df5d5c5SMatthew G. Knepley   Level: beginner
4361df5d5c5SMatthew G. Knepley 
4371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()`
4381df5d5c5SMatthew G. Knepley @*/
439d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm)
440d71ae5a4SJacob Faibussowitsch {
4411df5d5c5SMatthew G. Knepley   DM          dm;
4421df5d5c5SMatthew G. Knepley   PetscMPIInt rank;
4431df5d5c5SMatthew G. Knepley 
4441df5d5c5SMatthew G. Knepley   PetscFunctionBegin;
4459566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, &dm));
4469566063dSJacob Faibussowitsch   PetscCall(DMSetType(dm, DMPLEX));
4479566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
44846139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
4499566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
450ce78fa2fSMatthew G. Knepley   switch (dim) {
451ce78fa2fSMatthew G. Knepley   case 2:
4529566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular"));
4539566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral"));
454ce78fa2fSMatthew G. Knepley     break;
455ce78fa2fSMatthew G. Knepley   case 3:
4569566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral"));
4579566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral"));
458ce78fa2fSMatthew G. Knepley     break;
459d71ae5a4SJacob Faibussowitsch   default:
460d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
461ce78fa2fSMatthew G. Knepley   }
4621df5d5c5SMatthew G. Knepley   if (rank) {
4631df5d5c5SMatthew G. Knepley     PetscInt numPoints[2] = {0, 0};
4649566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL));
4651df5d5c5SMatthew G. Knepley   } else {
4661df5d5c5SMatthew G. Knepley     switch (dim) {
4671df5d5c5SMatthew G. Knepley     case 2:
4681df5d5c5SMatthew G. Knepley       if (simplex) {
4691df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {4, 2};
4701df5d5c5SMatthew G. Knepley         PetscInt    coneSize[6]         = {3, 3, 0, 0, 0, 0};
4711df5d5c5SMatthew G. Knepley         PetscInt    cones[6]            = {2, 3, 4, 5, 4, 3};
4721df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
4731df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[8]     = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5};
4741df5d5c5SMatthew G. Knepley 
4759566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
4761df5d5c5SMatthew G. Knepley       } else {
4771df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {6, 2};
4781df5d5c5SMatthew G. Knepley         PetscInt    coneSize[8]         = {4, 4, 0, 0, 0, 0, 0, 0};
4791df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {2, 3, 4, 5, 3, 6, 7, 4};
4801df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
4811df5d5c5SMatthew 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};
4821df5d5c5SMatthew G. Knepley 
4839566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
4841df5d5c5SMatthew G. Knepley       }
4851df5d5c5SMatthew G. Knepley       break;
4861df5d5c5SMatthew G. Knepley     case 3:
4871df5d5c5SMatthew G. Knepley       if (simplex) {
4881df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {5, 2};
4891df5d5c5SMatthew G. Knepley         PetscInt    coneSize[7]         = {4, 4, 0, 0, 0, 0, 0};
4901df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {4, 3, 5, 2, 5, 3, 4, 6};
4911df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
4921df5d5c5SMatthew 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};
4931df5d5c5SMatthew G. Knepley 
4949566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
4951df5d5c5SMatthew G. Knepley       } else {
4961df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]         = {12, 2};
4971df5d5c5SMatthew G. Knepley         PetscInt    coneSize[14]         = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
4981df5d5c5SMatthew G. Knepley         PetscInt    cones[16]            = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8};
4991df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
5009371c9d4SSatish 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};
5011df5d5c5SMatthew G. Knepley 
5029566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
5031df5d5c5SMatthew G. Knepley       }
5041df5d5c5SMatthew G. Knepley       break;
505d71ae5a4SJacob Faibussowitsch     default:
506d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
5071df5d5c5SMatthew G. Knepley     }
5081df5d5c5SMatthew G. Knepley   }
50946139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
5101df5d5c5SMatthew G. Knepley   *newdm = dm;
5111df5d5c5SMatthew G. Knepley   if (refinementLimit > 0.0) {
5121df5d5c5SMatthew G. Knepley     DM          rdm;
5131df5d5c5SMatthew G. Knepley     const char *name;
5141df5d5c5SMatthew G. Knepley 
5159566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE));
5169566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit));
5179566063dSJacob Faibussowitsch     PetscCall(DMRefine(*newdm, comm, &rdm));
5189566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)*newdm, &name));
5199566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)rdm, name));
5209566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
5211df5d5c5SMatthew G. Knepley     *newdm = rdm;
5221df5d5c5SMatthew G. Knepley   }
5231df5d5c5SMatthew G. Knepley   if (interpolate) {
5245fd9971aSMatthew G. Knepley     DM idm;
5251df5d5c5SMatthew G. Knepley 
5269566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*newdm, &idm));
5279566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
5281df5d5c5SMatthew G. Knepley     *newdm = idm;
5291df5d5c5SMatthew G. Knepley   }
5303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5311df5d5c5SMatthew G. Knepley }
5321df5d5c5SMatthew G. Knepley 
533d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
534d71ae5a4SJacob Faibussowitsch {
5359318fe57SMatthew G. Knepley   const PetscInt numVertices    = 2;
5369318fe57SMatthew G. Knepley   PetscInt       markerRight    = 1;
5379318fe57SMatthew G. Knepley   PetscInt       markerLeft     = 1;
5389318fe57SMatthew G. Knepley   PetscBool      markerSeparate = PETSC_FALSE;
5399318fe57SMatthew G. Knepley   Vec            coordinates;
5409318fe57SMatthew G. Knepley   PetscSection   coordSection;
5419318fe57SMatthew G. Knepley   PetscScalar   *coords;
5429318fe57SMatthew G. Knepley   PetscInt       coordSize;
5439318fe57SMatthew G. Knepley   PetscMPIInt    rank;
5449318fe57SMatthew G. Knepley   PetscInt       cdim = 1, v;
545552f7358SJed Brown 
5469318fe57SMatthew G. Knepley   PetscFunctionBegin;
5479566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
5489318fe57SMatthew G. Knepley   if (markerSeparate) {
5499318fe57SMatthew G. Knepley     markerRight = 2;
5509318fe57SMatthew G. Knepley     markerLeft  = 1;
5519318fe57SMatthew G. Knepley   }
5529566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
553c5853193SPierre Jolivet   if (rank == 0) {
5549566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numVertices));
5559566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
5569566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft));
5579566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight));
5589318fe57SMatthew G. Knepley   }
5599566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
5609566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
5619318fe57SMatthew G. Knepley   /* Build coordinates */
5629566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
5639566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
5649566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
5659566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, 0, numVertices));
5669566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
5679318fe57SMatthew G. Knepley   for (v = 0; v < numVertices; ++v) {
5689566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
5699566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
5709318fe57SMatthew G. Knepley   }
5719566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
5729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
5739566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
5749566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
5759566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
5769566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
5779566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
5789566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
5799318fe57SMatthew G. Knepley   coords[0] = lower[0];
5809318fe57SMatthew G. Knepley   coords[1] = upper[0];
5819566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
5829566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
5839566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
5843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5859318fe57SMatthew G. Knepley }
58626492d91SMatthew G. Knepley 
587d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
588d71ae5a4SJacob Faibussowitsch {
5891df21d24SMatthew G. Knepley   const PetscInt numVertices    = (edges[0] + 1) * (edges[1] + 1);
5901df21d24SMatthew G. Knepley   const PetscInt numEdges       = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1];
591552f7358SJed Brown   PetscInt       markerTop      = 1;
592552f7358SJed Brown   PetscInt       markerBottom   = 1;
593552f7358SJed Brown   PetscInt       markerRight    = 1;
594552f7358SJed Brown   PetscInt       markerLeft     = 1;
595552f7358SJed Brown   PetscBool      markerSeparate = PETSC_FALSE;
596552f7358SJed Brown   Vec            coordinates;
597552f7358SJed Brown   PetscSection   coordSection;
598552f7358SJed Brown   PetscScalar   *coords;
599552f7358SJed Brown   PetscInt       coordSize;
600552f7358SJed Brown   PetscMPIInt    rank;
601552f7358SJed Brown   PetscInt       v, vx, vy;
602552f7358SJed Brown 
603552f7358SJed Brown   PetscFunctionBegin;
6049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
605552f7358SJed Brown   if (markerSeparate) {
6061df21d24SMatthew G. Knepley     markerTop    = 3;
6071df21d24SMatthew G. Knepley     markerBottom = 1;
6081df21d24SMatthew G. Knepley     markerRight  = 2;
6091df21d24SMatthew G. Knepley     markerLeft   = 4;
610552f7358SJed Brown   }
6119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
612dd400576SPatrick Sanan   if (rank == 0) {
613552f7358SJed Brown     PetscInt e, ex, ey;
614552f7358SJed Brown 
6159566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices));
61648a46eb9SPierre Jolivet     for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
6179566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
618552f7358SJed Brown     for (vx = 0; vx <= edges[0]; vx++) {
619552f7358SJed Brown       for (ey = 0; ey < edges[1]; ey++) {
620552f7358SJed Brown         PetscInt edge   = vx * edges[1] + ey + edges[0] * (edges[1] + 1);
621552f7358SJed Brown         PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges;
622da80777bSKarl Rupp         PetscInt cone[2];
623552f7358SJed Brown 
6249371c9d4SSatish Balay         cone[0] = vertex;
6259371c9d4SSatish Balay         cone[1] = vertex + edges[0] + 1;
6269566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
627552f7358SJed Brown         if (vx == edges[0]) {
6289566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
6299566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
630552f7358SJed Brown           if (ey == edges[1] - 1) {
6319566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
6329566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight));
633552f7358SJed Brown           }
634552f7358SJed Brown         } else if (vx == 0) {
6359566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
6369566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
637552f7358SJed Brown           if (ey == edges[1] - 1) {
6389566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
6399566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft));
640552f7358SJed Brown           }
641552f7358SJed Brown         }
642552f7358SJed Brown       }
643552f7358SJed Brown     }
644552f7358SJed Brown     for (vy = 0; vy <= edges[1]; vy++) {
645552f7358SJed Brown       for (ex = 0; ex < edges[0]; ex++) {
646552f7358SJed Brown         PetscInt edge   = vy * edges[0] + ex;
647552f7358SJed Brown         PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges;
648da80777bSKarl Rupp         PetscInt cone[2];
649552f7358SJed Brown 
6509371c9d4SSatish Balay         cone[0] = vertex;
6519371c9d4SSatish Balay         cone[1] = vertex + 1;
6529566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
653552f7358SJed Brown         if (vy == edges[1]) {
6549566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
6559566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
656552f7358SJed Brown           if (ex == edges[0] - 1) {
6579566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
6589566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop));
659552f7358SJed Brown           }
660552f7358SJed Brown         } else if (vy == 0) {
6619566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
6629566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
663552f7358SJed Brown           if (ex == edges[0] - 1) {
6649566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
6659566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom));
666552f7358SJed Brown           }
667552f7358SJed Brown         }
668552f7358SJed Brown       }
669552f7358SJed Brown     }
670552f7358SJed Brown   }
6719566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
6729566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
673552f7358SJed Brown   /* Build coordinates */
6749566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 2));
6759566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
6769566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
6779566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices));
6789566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2));
679552f7358SJed Brown   for (v = numEdges; v < numEdges + numVertices; ++v) {
6809566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 2));
6819566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2));
682552f7358SJed Brown   }
6839566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
6849566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
6859566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
6869566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
6879566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
6889566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 2));
6899566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
6909566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
691552f7358SJed Brown   for (vy = 0; vy <= edges[1]; ++vy) {
692552f7358SJed Brown     for (vx = 0; vx <= edges[0]; ++vx) {
693552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx;
694552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy;
695552f7358SJed Brown     }
696552f7358SJed Brown   }
6979566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
6989566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
6999566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
7003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
701552f7358SJed Brown }
702552f7358SJed Brown 
703d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[])
704d71ae5a4SJacob Faibussowitsch {
7059e8abbc3SMichael Lange   PetscInt     vertices[3], numVertices;
7067b59f5a9SMichael Lange   PetscInt     numFaces       = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2];
707c2df9bbfSMatthew G. Knepley   PetscInt     markerTop      = 1;
708c2df9bbfSMatthew G. Knepley   PetscInt     markerBottom   = 1;
709c2df9bbfSMatthew G. Knepley   PetscInt     markerFront    = 1;
710c2df9bbfSMatthew G. Knepley   PetscInt     markerBack     = 1;
711c2df9bbfSMatthew G. Knepley   PetscInt     markerRight    = 1;
712c2df9bbfSMatthew G. Knepley   PetscInt     markerLeft     = 1;
713c2df9bbfSMatthew G. Knepley   PetscBool    markerSeparate = PETSC_FALSE;
714552f7358SJed Brown   Vec          coordinates;
715552f7358SJed Brown   PetscSection coordSection;
716552f7358SJed Brown   PetscScalar *coords;
717552f7358SJed Brown   PetscInt     coordSize;
718552f7358SJed Brown   PetscMPIInt  rank;
719552f7358SJed Brown   PetscInt     v, vx, vy, vz;
7207b59f5a9SMichael Lange   PetscInt     voffset, iface = 0, cone[4];
721552f7358SJed Brown 
722552f7358SJed Brown   PetscFunctionBegin;
7231dca8a05SBarry 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");
7249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
725c2df9bbfSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
726c2df9bbfSMatthew G. Knepley   if (markerSeparate) {
727c2df9bbfSMatthew G. Knepley     markerBottom = 1;
728c2df9bbfSMatthew G. Knepley     markerTop    = 2;
729c2df9bbfSMatthew G. Knepley     markerFront  = 3;
730c2df9bbfSMatthew G. Knepley     markerBack   = 4;
731c2df9bbfSMatthew G. Knepley     markerRight  = 5;
732c2df9bbfSMatthew G. Knepley     markerLeft   = 6;
733c2df9bbfSMatthew G. Knepley   }
7349371c9d4SSatish Balay   vertices[0] = faces[0] + 1;
7359371c9d4SSatish Balay   vertices[1] = faces[1] + 1;
7369371c9d4SSatish Balay   vertices[2] = faces[2] + 1;
7379e8abbc3SMichael Lange   numVertices = vertices[0] * vertices[1] * vertices[2];
738dd400576SPatrick Sanan   if (rank == 0) {
739552f7358SJed Brown     PetscInt f;
740552f7358SJed Brown 
7419566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices));
74248a46eb9SPierre Jolivet     for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
7439566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
7447b59f5a9SMichael Lange 
7457b59f5a9SMichael Lange     /* Side 0 (Top) */
7467b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
7477b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
7487b59f5a9SMichael Lange         voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx;
7499371c9d4SSatish Balay         cone[0] = voffset;
7509371c9d4SSatish Balay         cone[1] = voffset + 1;
7519371c9d4SSatish Balay         cone[2] = voffset + vertices[0] + 1;
7529371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
7539566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
754c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop));
755c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop));
756c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop));
757c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop));
758c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop));
7597b59f5a9SMichael Lange         iface++;
760552f7358SJed Brown       }
761552f7358SJed Brown     }
7627b59f5a9SMichael Lange 
7637b59f5a9SMichael Lange     /* Side 1 (Bottom) */
7647b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
7657b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
7667b59f5a9SMichael Lange         voffset = numFaces + vy * (faces[0] + 1) + vx;
7679371c9d4SSatish Balay         cone[0] = voffset + 1;
7689371c9d4SSatish Balay         cone[1] = voffset;
7699371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
7709371c9d4SSatish Balay         cone[3] = voffset + vertices[0] + 1;
7719566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
772c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom));
773c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom));
774c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom));
775c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom));
776c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom));
7777b59f5a9SMichael Lange         iface++;
778552f7358SJed Brown       }
779552f7358SJed Brown     }
7807b59f5a9SMichael Lange 
7817b59f5a9SMichael Lange     /* Side 2 (Front) */
7827b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
7837b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
7847b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vx;
7859371c9d4SSatish Balay         cone[0] = voffset;
7869371c9d4SSatish Balay         cone[1] = voffset + 1;
7879371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + 1;
7889371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1];
7899566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
790c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront));
791c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront));
792c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront));
793c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront));
794c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront));
7957b59f5a9SMichael Lange         iface++;
796552f7358SJed Brown       }
7977b59f5a9SMichael Lange     }
7987b59f5a9SMichael Lange 
7997b59f5a9SMichael Lange     /* Side 3 (Back) */
8007b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
8017b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
8027b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx;
8039371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
8049371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1] + 1;
8059371c9d4SSatish Balay         cone[2] = voffset + 1;
8069371c9d4SSatish Balay         cone[3] = voffset;
8079566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
808c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack));
809c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack));
810c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack));
811c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack));
812c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack));
8137b59f5a9SMichael Lange         iface++;
8147b59f5a9SMichael Lange       }
8157b59f5a9SMichael Lange     }
8167b59f5a9SMichael Lange 
8177b59f5a9SMichael Lange     /* Side 4 (Left) */
8187b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
8197b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
8207b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0];
8219371c9d4SSatish Balay         cone[0] = voffset;
8229371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1];
8239371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + vertices[0];
8249371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
8259566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
826c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft));
827c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft));
828c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft));
829c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft));
830c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft));
8317b59f5a9SMichael Lange         iface++;
8327b59f5a9SMichael Lange       }
8337b59f5a9SMichael Lange     }
8347b59f5a9SMichael Lange 
8357b59f5a9SMichael Lange     /* Side 5 (Right) */
8367b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
8377b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
838aab5bcd8SJed Brown         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0];
8399371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
8409371c9d4SSatish Balay         cone[1] = voffset;
8419371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
8429371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1] + vertices[0];
8439566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
844c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight));
845c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight));
846c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight));
847c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight));
848c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight));
8497b59f5a9SMichael Lange         iface++;
8507b59f5a9SMichael Lange       }
851552f7358SJed Brown     }
852552f7358SJed Brown   }
8539566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
8549566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
855552f7358SJed Brown   /* Build coordinates */
8569566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 3));
8579566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
8589566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
8599566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices));
8609566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3));
861552f7358SJed Brown   for (v = numFaces; v < numFaces + numVertices; ++v) {
8629566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 3));
8639566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3));
864552f7358SJed Brown   }
8659566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
8669566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
8679566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
8689566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
8699566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
8709566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 3));
8719566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
8729566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
873552f7358SJed Brown   for (vz = 0; vz <= faces[2]; ++vz) {
874552f7358SJed Brown     for (vy = 0; vy <= faces[1]; ++vy) {
875552f7358SJed Brown       for (vx = 0; vx <= faces[0]; ++vx) {
876552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx;
877552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy;
878552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz;
879552f7358SJed Brown       }
880552f7358SJed Brown     }
881552f7358SJed Brown   }
8829566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
8839566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
8849566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
8853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
886552f7358SJed Brown }
887552f7358SJed Brown 
888d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate)
889d71ae5a4SJacob Faibussowitsch {
8909318fe57SMatthew G. Knepley   PetscFunctionBegin;
8919318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
89246139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
8939566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim - 1));
8949566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim));
8959318fe57SMatthew G. Knepley   switch (dim) {
896d71ae5a4SJacob Faibussowitsch   case 1:
897d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces));
898d71ae5a4SJacob Faibussowitsch     break;
899d71ae5a4SJacob Faibussowitsch   case 2:
900d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces));
901d71ae5a4SJacob Faibussowitsch     break;
902d71ae5a4SJacob Faibussowitsch   case 3:
903d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces));
904d71ae5a4SJacob Faibussowitsch     break;
905d71ae5a4SJacob Faibussowitsch   default:
906d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim);
9079318fe57SMatthew G. Knepley   }
90846139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
9099566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
9103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9119318fe57SMatthew G. Knepley }
9129318fe57SMatthew G. Knepley 
9139318fe57SMatthew G. Knepley /*@C
9149318fe57SMatthew G. Knepley   DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra).
9159318fe57SMatthew G. Knepley 
9169318fe57SMatthew G. Knepley   Collective
9179318fe57SMatthew G. Knepley 
9189318fe57SMatthew G. Knepley   Input Parameters:
919a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
92020f4b53cSBarry Smith . dim         - The spatial dimension of the box, so the resulting mesh is has dimension `dim`-1
92120f4b53cSBarry Smith . faces       - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
92220f4b53cSBarry Smith . lower       - The lower left corner, or `NULL` for (0, 0, 0)
92320f4b53cSBarry Smith . upper       - The upper right corner, or `NULL` for (1, 1, 1)
9249318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
9259318fe57SMatthew G. Knepley 
9269318fe57SMatthew G. Knepley   Output Parameter:
927a1cb98faSBarry Smith . dm - The `DM` object
9289318fe57SMatthew G. Knepley 
9299318fe57SMatthew G. Knepley   Level: beginner
9309318fe57SMatthew G. Knepley 
9311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()`
9329318fe57SMatthew G. Knepley @*/
933d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm)
934d71ae5a4SJacob Faibussowitsch {
9359318fe57SMatthew G. Knepley   PetscInt  fac[3] = {1, 1, 1};
9369318fe57SMatthew G. Knepley   PetscReal low[3] = {0, 0, 0};
9379318fe57SMatthew G. Knepley   PetscReal upp[3] = {1, 1, 1};
9389318fe57SMatthew G. Knepley 
9399318fe57SMatthew G. Knepley   PetscFunctionBegin;
9409566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
9419566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
9429566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate));
9433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9449318fe57SMatthew G. Knepley }
9459318fe57SMatthew G. Knepley 
946d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd)
947d71ae5a4SJacob Faibussowitsch {
948fdbf62faSLisandro Dalcin   PetscInt     i, fStart, fEnd, numCells = 0, numVerts = 0;
949fdbf62faSLisandro Dalcin   PetscInt     numPoints[2], *coneSize, *cones, *coneOrientations;
950fdbf62faSLisandro Dalcin   PetscScalar *vertexCoords;
951fdbf62faSLisandro Dalcin   PetscReal    L, maxCell;
952fdbf62faSLisandro Dalcin   PetscBool    markerSeparate = PETSC_FALSE;
953fdbf62faSLisandro Dalcin   PetscInt     markerLeft = 1, faceMarkerLeft = 1;
954fdbf62faSLisandro Dalcin   PetscInt     markerRight = 1, faceMarkerRight = 2;
955fdbf62faSLisandro Dalcin   PetscBool    wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE;
956fdbf62faSLisandro Dalcin   PetscMPIInt  rank;
957fdbf62faSLisandro Dalcin 
958fdbf62faSLisandro Dalcin   PetscFunctionBegin;
9594f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
960fdbf62faSLisandro Dalcin 
9619566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, 1));
9629566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
9639566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
964fdbf62faSLisandro Dalcin 
9659566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
966dd400576SPatrick Sanan   if (rank == 0) numCells = segments;
967dd400576SPatrick Sanan   if (rank == 0) numVerts = segments + (wrap ? 0 : 1);
968fdbf62faSLisandro Dalcin 
9699371c9d4SSatish Balay   numPoints[0] = numVerts;
9709371c9d4SSatish Balay   numPoints[1] = numCells;
9719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords));
9729566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts));
973ad540459SPierre Jolivet   for (i = 0; i < numCells; ++i) coneSize[i] = 2;
974ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0;
9759371c9d4SSatish Balay   for (i = 0; i < numCells; ++i) {
9769371c9d4SSatish Balay     cones[2 * i]     = numCells + i % numVerts;
9779371c9d4SSatish Balay     cones[2 * i + 1] = numCells + (i + 1) % numVerts;
9789371c9d4SSatish Balay   }
979ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells);
9809566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
9819566063dSJacob Faibussowitsch   PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords));
982fdbf62faSLisandro Dalcin 
9839566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
9849371c9d4SSatish Balay   if (markerSeparate) {
9859371c9d4SSatish Balay     markerLeft  = faceMarkerLeft;
9869371c9d4SSatish Balay     markerRight = faceMarkerRight;
9879371c9d4SSatish Balay   }
988dd400576SPatrick Sanan   if (!wrap && rank == 0) {
9899566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
9909566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft));
9919566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight));
9929566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft));
9939566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight));
994fdbf62faSLisandro Dalcin   }
995fdbf62faSLisandro Dalcin   if (wrap) {
996fdbf62faSLisandro Dalcin     L       = upper - lower;
997fdbf62faSLisandro Dalcin     maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments));
9984fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L));
999fdbf62faSLisandro Dalcin   }
10009566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
10013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1002fdbf62faSLisandro Dalcin }
1003fdbf62faSLisandro Dalcin 
10044054ae39SJames Wright // Creates "Face Sets" label based on the standard box labeling conventions
1005d7d2d1d2SJames Wright static PetscErrorCode DMPlexSetBoxLabel_Internal(DM dm, const DMBoundaryType periodicity[])
10064054ae39SJames Wright {
10076ff49feeSJames Wright   DM              cdm;
10086ff49feeSJames Wright   PetscSection    csection;
10096ff49feeSJames Wright   Vec             coordinates;
10104054ae39SJames Wright   DMLabel         label;
10116ff49feeSJames Wright   IS              faces_is;
10122b4f33d9SJames Wright   PetscInt        dim, num_face = 0;
10134054ae39SJames Wright   const PetscInt *faces;
10144054ae39SJames Wright   PetscInt        faceMarkerBottom, faceMarkerTop, faceMarkerFront, faceMarkerBack, faceMarkerRight, faceMarkerLeft;
10154054ae39SJames Wright 
10164054ae39SJames Wright   PetscFunctionBeginUser;
10174054ae39SJames Wright   PetscCall(DMGetDimension(dm, &dim));
1018d7c1f440SPierre 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);
10194054ae39SJames Wright   // Get Face Sets label
10204054ae39SJames Wright   PetscCall(DMGetLabel(dm, "Face Sets", &label));
10214054ae39SJames Wright   if (label) {
10224054ae39SJames Wright     PetscCall(DMLabelReset(label));
10234054ae39SJames Wright   } else {
10244054ae39SJames Wright     PetscCall(DMCreateLabel(dm, "Face Sets"));
10254054ae39SJames Wright     PetscCall(DMGetLabel(dm, "Face Sets", &label));
10264054ae39SJames Wright   }
10274054ae39SJames Wright   PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label));
10286ff49feeSJames Wright   PetscCall(DMGetStratumIS(dm, "Face Sets", 1, &faces_is));
10294054ae39SJames Wright 
10304054ae39SJames Wright   switch (dim) {
10314054ae39SJames Wright   case 2:
10324054ae39SJames Wright     faceMarkerTop    = 3;
10334054ae39SJames Wright     faceMarkerBottom = 1;
10344054ae39SJames Wright     faceMarkerRight  = 2;
10354054ae39SJames Wright     faceMarkerLeft   = 4;
10364054ae39SJames Wright     break;
10374054ae39SJames Wright   case 3:
10384054ae39SJames Wright     faceMarkerBottom = 1;
10394054ae39SJames Wright     faceMarkerTop    = 2;
10404054ae39SJames Wright     faceMarkerFront  = 3;
10414054ae39SJames Wright     faceMarkerBack   = 4;
10424054ae39SJames Wright     faceMarkerRight  = 5;
10434054ae39SJames Wright     faceMarkerLeft   = 6;
10444054ae39SJames Wright     break;
10454054ae39SJames Wright   default:
10464054ae39SJames Wright     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
10474054ae39SJames Wright   }
10484054ae39SJames Wright 
10492b4f33d9SJames Wright   if (faces_is) PetscCall(ISGetLocalSize(faces_is, &num_face));
10502b4f33d9SJames Wright   if (faces_is) PetscCall(ISGetIndices(faces_is, &faces));
10516ff49feeSJames Wright   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
10526ff49feeSJames Wright   PetscCall(DMGetCoordinateDM(dm, &cdm));
10536ff49feeSJames Wright   PetscCall(DMGetLocalSection(cdm, &csection));
10544054ae39SJames Wright   for (PetscInt f = 0; f < num_face; ++f) {
10556ff49feeSJames Wright     PetscScalar *coords = NULL;
10566ff49feeSJames Wright     PetscInt     face = faces[f], flip = 1, label_value = -1, coords_size;
10574054ae39SJames Wright 
10584054ae39SJames Wright     { // Determine if orientation of face is flipped
10594054ae39SJames Wright       PetscInt        num_cells_support, num_faces, start = -1;
10604054ae39SJames Wright       const PetscInt *orients, *cell_faces, *cells;
10614054ae39SJames Wright 
10624054ae39SJames Wright       PetscCall(DMPlexGetSupport(dm, face, &cells));
10634054ae39SJames Wright       PetscCall(DMPlexGetSupportSize(dm, face, &num_cells_support));
10644054ae39SJames 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);
10654054ae39SJames Wright       PetscCall(DMPlexGetCone(dm, cells[0], &cell_faces));
10664054ae39SJames Wright       PetscCall(DMPlexGetConeSize(dm, cells[0], &num_faces));
10674054ae39SJames Wright       for (PetscInt i = 0; i < num_faces; i++) {
10684054ae39SJames Wright         if (cell_faces[i] == face) start = i;
10694054ae39SJames Wright       }
10704054ae39SJames Wright       PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Could not find face %" PetscInt_FMT " in cone of its support", face);
10714054ae39SJames Wright       PetscCall(DMPlexGetConeOrientation(dm, cells[0], &orients));
10724054ae39SJames Wright       if (orients[start] < 0) flip = -1;
10734054ae39SJames Wright     }
10744054ae39SJames Wright 
10756ff49feeSJames Wright     // Cannot use DMPlexComputeCellGeometryFVM() for high-order geometry, so must calculate normal vectors manually
10766ff49feeSJames Wright     // Use the vertices (depth 0) of coordinate DM to calculate normal vector
10776ff49feeSJames Wright     PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords));
10784054ae39SJames Wright     switch (dim) {
10794054ae39SJames Wright     case 2: {
10806ff49feeSJames Wright       PetscScalar vec[2];
10816ff49feeSJames Wright 
10826ff49feeSJames Wright       for (PetscInt d = 0; d < dim; ++d) vec[d] = flip * (PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]));
10836ff49feeSJames Wright       PetscScalar normal[] = {vec[1], -vec[0]};
10846ff49feeSJames Wright       if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) {
10856ff49feeSJames Wright         label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft;
10864054ae39SJames Wright       } else {
10876ff49feeSJames Wright         label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerTop : faceMarkerBottom;
10884054ae39SJames Wright       }
10894054ae39SJames Wright     } break;
10904054ae39SJames Wright     case 3: {
10916ff49feeSJames Wright       PetscScalar vec1[3], vec2[3], normal[3];
10926ff49feeSJames Wright 
10936ff49feeSJames Wright       for (PetscInt d = 0; d < dim; ++d) {
10946ff49feeSJames Wright         vec1[d] = PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]);
10956ff49feeSJames Wright         vec2[d] = PetscRealPart(coords[2 * dim + d]) - PetscRealPart(coords[1 * dim + d]);
10966ff49feeSJames Wright       }
10976ff49feeSJames Wright 
10986ff49feeSJames Wright       // Calculate normal vector via cross-product
10996ff49feeSJames Wright       normal[0] = flip * ((vec1[1] * vec2[2]) - (vec1[2] * vec2[1]));
11006ff49feeSJames Wright       normal[1] = flip * ((vec1[2] * vec2[0]) - (vec1[0] * vec2[2]));
11016ff49feeSJames Wright       normal[2] = flip * ((vec1[0] * vec2[1]) - (vec1[1] * vec2[0]));
11026ff49feeSJames Wright 
11036ff49feeSJames Wright       if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) {
11046ff49feeSJames Wright         if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[2])) {
11056ff49feeSJames Wright           label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft;
11064054ae39SJames Wright         } else {
11076ff49feeSJames Wright           label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom;
11084054ae39SJames Wright         }
11094054ae39SJames Wright       } else {
11106ff49feeSJames Wright         if (PetscAbsScalar(normal[1]) > PetscAbsScalar(normal[2])) {
11116ff49feeSJames Wright           label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerBack : faceMarkerFront;
11124054ae39SJames Wright         } else {
11136ff49feeSJames Wright           label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom;
11144054ae39SJames Wright         }
11154054ae39SJames Wright       }
11164054ae39SJames Wright     } break;
11174054ae39SJames Wright     }
11184054ae39SJames Wright 
11194054ae39SJames Wright     PetscInt previous_label_value; // always 1 due to DMPlexMarkBoundaryFaces call above
11204054ae39SJames Wright     PetscCall(DMGetLabelValue(dm, "Face Sets", face, &previous_label_value));
11214054ae39SJames Wright     PetscCall(DMClearLabelValue(dm, "Face Sets", face, previous_label_value));
11224054ae39SJames Wright     PetscCall(DMSetLabelValue(dm, "Face Sets", face, label_value));
11236ff49feeSJames Wright     PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords));
11244054ae39SJames Wright   }
11252b4f33d9SJames Wright   if (faces_is) PetscCall(ISRestoreIndices(faces_is, &faces));
11266ff49feeSJames Wright   PetscCall(ISDestroy(&faces_is));
1127d7d2d1d2SJames Wright 
1128d7d2d1d2SJames Wright   // Create Isoperiodic SF from newly-created face labels
1129d7d2d1d2SJames Wright   PetscSF     periodicsfs[3];
1130d7d2d1d2SJames Wright   PetscInt    periodic_sf_index  = 0;
1131d7d2d1d2SJames Wright   PetscScalar transform[3][4][4] = {{{0.}}};
1132d7d2d1d2SJames Wright   for (PetscInt d = 0; d < dim; d++) {
1133d7d2d1d2SJames Wright     IS              donor_is, periodic_is;
1134d7d2d1d2SJames Wright     const PetscInt *donor_faces = NULL, *periodic_faces = NULL;
1135d7d2d1d2SJames Wright     PetscInt        num_donor = 0, num_periodic = 0;
1136d7d2d1d2SJames Wright     PetscSF         centroidsf;
1137d7d2d1d2SJames Wright     PetscReal       donor_to_periodic_distance;
1138d7d2d1d2SJames Wright     const PetscInt  face_pairings[2][3][2] = {
1139d7d2d1d2SJames Wright       // 2D face pairings, {donor, periodic}
1140d7d2d1d2SJames Wright       {{4, 2}, {1, 3}},
1141d7d2d1d2SJames Wright       // 3D face pairings
1142d7d2d1d2SJames Wright       {{5, 6}, {3, 4}, {1, 2}}
1143d7d2d1d2SJames Wright     };
1144d7d2d1d2SJames Wright 
1145d7d2d1d2SJames Wright     if (periodicity[d] != DM_BOUNDARY_PERIODIC) continue;
1146d7d2d1d2SJames Wright     {
1147d7d2d1d2SJames Wright       // Compute centroidsf, which is the mapping from donor faces to periodic faces
1148d7d2d1d2SJames Wright       // Matches the centroid of the faces together, ignoring the periodic direction component (which should not match between donor and periodic face)
1149d7d2d1d2SJames Wright       PetscInt     coords_size, centroid_comps = dim - 1;
1150d7d2d1d2SJames Wright       PetscScalar *coords = NULL;
1151d7d2d1d2SJames Wright       PetscReal   *donor_centroids, *periodic_centroids;
1152d7d2d1d2SJames 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
1153d7d2d1d2SJames Wright 
1154d7d2d1d2SJames Wright       PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][0], &donor_is));
1155d7d2d1d2SJames Wright       PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][1], &periodic_is));
1156d7d2d1d2SJames Wright       if (donor_is) {
1157d7d2d1d2SJames Wright         PetscCall(ISGetLocalSize(donor_is, &num_donor));
1158d7d2d1d2SJames Wright         PetscCall(ISGetIndices(donor_is, &donor_faces));
1159d7d2d1d2SJames Wright       }
1160d7d2d1d2SJames Wright       if (periodic_is) {
1161d7d2d1d2SJames Wright         PetscCall(ISGetLocalSize(periodic_is, &num_periodic));
1162d7d2d1d2SJames Wright         PetscCall(ISGetIndices(periodic_is, &periodic_faces));
1163d7d2d1d2SJames Wright       }
1164d7d2d1d2SJames Wright       PetscCall(PetscCalloc2(num_donor * centroid_comps, &donor_centroids, num_periodic * centroid_comps, &periodic_centroids));
1165d7d2d1d2SJames Wright       for (PetscInt f = 0; f < num_donor; f++) {
1166d7d2d1d2SJames Wright         PetscInt face = donor_faces[f], num_coords;
1167d7d2d1d2SJames Wright         PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords));
1168d7d2d1d2SJames Wright         num_coords = coords_size / dim;
1169d7d2d1d2SJames Wright         for (PetscInt c = 0; c < num_coords; c++) {
1170d7d2d1d2SJames Wright           PetscInt comp_index = 0;
1171d7d2d1d2SJames Wright           loc_periodic[0]     = PetscRealPart(coords[c * dim + d]);
1172d7d2d1d2SJames Wright           for (PetscInt i = 0; i < dim; i++) {
1173d7d2d1d2SJames Wright             if (i == d) continue; // Periodic direction not used for centroid calculation
1174d7d2d1d2SJames Wright             donor_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords;
1175d7d2d1d2SJames Wright             comp_index++;
1176d7d2d1d2SJames Wright           }
1177d7d2d1d2SJames Wright         }
1178d7d2d1d2SJames Wright         PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords));
1179d7d2d1d2SJames Wright       }
1180d7d2d1d2SJames Wright 
1181d7d2d1d2SJames Wright       for (PetscInt f = 0; f < num_periodic; f++) {
1182d7d2d1d2SJames Wright         PetscInt face = periodic_faces[f], num_coords;
1183d7d2d1d2SJames Wright         PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords));
1184d7d2d1d2SJames Wright         num_coords = coords_size / dim;
1185d7d2d1d2SJames Wright         for (PetscInt c = 0; c < num_coords; c++) {
1186d7d2d1d2SJames Wright           PetscInt comp_index = 0;
1187d7d2d1d2SJames Wright           loc_periodic[1]     = PetscRealPart(coords[c * dim + d]);
1188d7d2d1d2SJames Wright           for (PetscInt i = 0; i < dim; i++) {
1189d7d2d1d2SJames Wright             if (i == d) continue; // Periodic direction not used for centroid calculation
1190d7d2d1d2SJames Wright             periodic_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords;
1191d7d2d1d2SJames Wright             comp_index++;
1192d7d2d1d2SJames Wright           }
1193d7d2d1d2SJames Wright         }
1194d7d2d1d2SJames Wright         PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords));
1195d7d2d1d2SJames Wright       }
1196d7d2d1d2SJames Wright       PetscCallMPI(MPIU_Allreduce(loc_periodic, loc_periodic_global, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm)));
1197d7d2d1d2SJames Wright       donor_to_periodic_distance = loc_periodic_global[1] - loc_periodic_global[0];
1198d7d2d1d2SJames Wright 
1199d7d2d1d2SJames Wright       PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &centroidsf));
1200d7d2d1d2SJames Wright       PetscCall(PetscSFSetGraphFromCoordinates(centroidsf, num_donor, num_periodic, centroid_comps, 1e-10, donor_centroids, periodic_centroids));
1201d7d2d1d2SJames Wright       PetscCall(PetscSFViewFromOptions(centroidsf, NULL, "-dm_plex_box_label_centroid_sf_view"));
1202d7d2d1d2SJames Wright       PetscCall(PetscFree2(donor_centroids, periodic_centroids));
1203d7d2d1d2SJames Wright     }
1204d7d2d1d2SJames Wright 
1205d7d2d1d2SJames Wright     { // Create Isoperiodic SF using centroidsSF
1206d7d2d1d2SJames Wright       PetscInt           pStart, pEnd;
1207d7d2d1d2SJames Wright       PetscInt          *leaf_faces;
1208d7d2d1d2SJames Wright       const PetscSFNode *firemote;
1209d7d2d1d2SJames Wright       PetscSFNode       *isoperiodic_leaves;
1210d7d2d1d2SJames Wright 
1211d7d2d1d2SJames Wright       PetscCall(PetscMalloc1(num_periodic, &leaf_faces));
1212d7d2d1d2SJames Wright       PetscCall(PetscSFBcastBegin(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE));
1213d7d2d1d2SJames Wright       PetscCall(PetscSFBcastEnd(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE));
1214d7d2d1d2SJames Wright 
1215d7d2d1d2SJames Wright       PetscCall(PetscMalloc1(num_periodic, &isoperiodic_leaves));
1216d7d2d1d2SJames Wright       PetscCall(PetscSFGetGraph(centroidsf, NULL, NULL, NULL, &firemote));
1217d7d2d1d2SJames Wright       for (PetscInt l = 0; l < num_periodic; ++l) {
1218d7d2d1d2SJames Wright         isoperiodic_leaves[l].index = leaf_faces[l];
1219d7d2d1d2SJames Wright         isoperiodic_leaves[l].rank  = firemote[l].rank;
1220d7d2d1d2SJames Wright       }
1221d7d2d1d2SJames Wright 
1222d7d2d1d2SJames Wright       PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
1223d7d2d1d2SJames Wright       PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &periodicsfs[periodic_sf_index]));
1224d7d2d1d2SJames Wright       PetscCall(PetscSFSetGraph(periodicsfs[periodic_sf_index], pEnd - pStart, num_periodic, (PetscInt *)periodic_faces, PETSC_COPY_VALUES, isoperiodic_leaves, PETSC_OWN_POINTER));
1225d7d2d1d2SJames Wright       PetscCall(PetscSFViewFromOptions(periodicsfs[periodic_sf_index], NULL, "-dm_plex_box_label_periodic_sf_view"));
1226d7d2d1d2SJames Wright       PetscCall(PetscFree(leaf_faces));
1227d7d2d1d2SJames Wright     }
1228d7d2d1d2SJames Wright 
1229d7d2d1d2SJames Wright     transform[periodic_sf_index][0][0] = 1;
1230d7d2d1d2SJames Wright     transform[periodic_sf_index][1][1] = 1;
1231d7d2d1d2SJames Wright     transform[periodic_sf_index][2][2] = 1;
1232d7d2d1d2SJames Wright     transform[periodic_sf_index][3][3] = 1;
1233d7d2d1d2SJames Wright     transform[periodic_sf_index][d][3] = donor_to_periodic_distance;
1234d7d2d1d2SJames Wright 
1235d7d2d1d2SJames Wright     periodic_sf_index++;
1236d7d2d1d2SJames Wright     PetscCall(PetscSFDestroy(&centroidsf));
1237d7d2d1d2SJames Wright     if (donor_is) {
1238d7d2d1d2SJames Wright       PetscCall(ISRestoreIndices(donor_is, &donor_faces));
1239d7d2d1d2SJames Wright       PetscCall(ISDestroy(&donor_is));
1240d7d2d1d2SJames Wright     }
1241d7d2d1d2SJames Wright     if (periodic_is) {
1242d7d2d1d2SJames Wright       PetscCall(ISRestoreIndices(periodic_is, &periodic_faces));
1243d7d2d1d2SJames Wright       PetscCall(ISDestroy(&periodic_is));
1244d7d2d1d2SJames Wright     }
1245d7d2d1d2SJames Wright     PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][0]));
1246d7d2d1d2SJames Wright     PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][1]));
1247d7d2d1d2SJames Wright   }
1248d7d2d1d2SJames Wright   PetscCall(DMPlexSetIsoperiodicFaceSF(dm, periodic_sf_index, periodicsfs));
1249d7d2d1d2SJames Wright   PetscCall(DMPlexSetIsoperiodicFaceTransform(dm, periodic_sf_index, (const PetscScalar *)transform));
1250d7d2d1d2SJames Wright   for (PetscInt p = 0; p < periodic_sf_index; p++) PetscCall(PetscSFDestroy(&periodicsfs[p]));
1251d7d2d1d2SJames Wright 
1252d7d2d1d2SJames Wright   { // Update coordinate DM with new Face Sets label
1253d7d2d1d2SJames Wright     DM      cdm;
1254d7d2d1d2SJames Wright     DMLabel oldFaceSets, newFaceSets;
1255d7d2d1d2SJames Wright     PetscCall(DMGetCoordinateDM(dm, &cdm));
1256d7d2d1d2SJames Wright     PetscCall(DMGetLabel(cdm, "Face Sets", &oldFaceSets));
1257d7d2d1d2SJames Wright     if (oldFaceSets) PetscCall(DMRemoveLabelBySelf(cdm, &oldFaceSets, PETSC_FALSE));
1258d7d2d1d2SJames Wright     PetscCall(DMLabelDuplicate(label, &newFaceSets));
1259d7d2d1d2SJames Wright     PetscCall(DMAddLabel(cdm, newFaceSets));
1260d7d2d1d2SJames Wright     PetscCall(DMLabelDestroy(&newFaceSets));
1261d7d2d1d2SJames Wright   }
12624054ae39SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
12634054ae39SJames Wright }
12644054ae39SJames Wright 
1265d698cf03SStefano Zampini static PetscErrorCode DMPlexCreateSquareMesh_Simplex_CrissCross(DM dm, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType bd[])
1266d698cf03SStefano Zampini {
1267d698cf03SStefano Zampini   PetscInt       markerTop = 1, faceMarkerTop = 3;
1268d698cf03SStefano Zampini   PetscInt       markerBottom = 1, faceMarkerBottom = 1;
1269d698cf03SStefano Zampini   PetscInt       markerRight = 1, faceMarkerRight = 2;
1270d698cf03SStefano Zampini   PetscInt       markerLeft = 1, faceMarkerLeft = 4;
1271d698cf03SStefano Zampini   PetscBool      markerSeparate = PETSC_FALSE;
1272d698cf03SStefano Zampini   DMBoundaryType bdX = bd[0], bdY = bd[1];
1273d698cf03SStefano Zampini   PetscMPIInt    rank;
1274d698cf03SStefano Zampini 
1275d698cf03SStefano Zampini   PetscFunctionBegin;
1276d698cf03SStefano Zampini   PetscCheck(bdX == DM_BOUNDARY_NONE || bdX == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdX]);
1277d698cf03SStefano Zampini   PetscCheck(bdY == DM_BOUNDARY_NONE || bdY == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdY]);
1278d698cf03SStefano Zampini   PetscCall(DMSetDimension(dm, 2));
1279d698cf03SStefano Zampini   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1280d698cf03SStefano Zampini   PetscCall(DMCreateLabel(dm, "marker"));
1281d698cf03SStefano Zampini   PetscCall(DMCreateLabel(dm, "Face Sets"));
1282d698cf03SStefano Zampini   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
1283d698cf03SStefano Zampini   if (markerSeparate) {
1284d698cf03SStefano Zampini     markerBottom = faceMarkerBottom;
1285d698cf03SStefano Zampini     markerTop    = faceMarkerTop;
1286d698cf03SStefano Zampini     markerRight  = faceMarkerRight;
1287d698cf03SStefano Zampini     markerLeft   = faceMarkerLeft;
1288d698cf03SStefano Zampini   }
1289d698cf03SStefano Zampini   {
1290d698cf03SStefano Zampini     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
1291d698cf03SStefano Zampini     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
1292d698cf03SStefano Zampini     const PetscInt numZEdges    = rank == 0 ? 4 * edges[0] * edges[1] : 0; /* Z-edges are the 4 internal edges per cell */
1293d698cf03SStefano Zampini     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC ? edges[0] : edges[0] + 1) : 0;
1294d698cf03SStefano Zampini     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC ? edges[1] : edges[1] + 1) : 0;
1295d698cf03SStefano Zampini     const PetscInt numZVertices = rank == 0 ? edges[0] * edges[1] : 0;
1296d698cf03SStefano Zampini     const PetscInt numCells     = 4 * numXEdges * numYEdges;
1297d698cf03SStefano Zampini     const PetscInt numTotXEdges = numXEdges * numYVertices;
1298d698cf03SStefano Zampini     const PetscInt numTotYEdges = numYEdges * numXVertices;
1299d698cf03SStefano Zampini     const PetscInt numVertices  = numXVertices * numYVertices + numZVertices;
1300d698cf03SStefano Zampini     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numZEdges;
1301d698cf03SStefano Zampini     const PetscInt firstVertex  = numCells;
1302d698cf03SStefano Zampini     const PetscInt firstXEdge   = numCells + numVertices;
1303d698cf03SStefano Zampini     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
1304d698cf03SStefano Zampini     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
1305d698cf03SStefano Zampini     Vec            coordinates;
1306d698cf03SStefano Zampini     PetscSection   coordSection;
1307d698cf03SStefano Zampini     PetscScalar   *coords;
1308d698cf03SStefano Zampini     PetscInt       coordSize;
1309d698cf03SStefano Zampini     PetscInt       v, vx, vy;
1310d698cf03SStefano Zampini     PetscInt       c, e, ex, ey;
1311d698cf03SStefano Zampini 
1312d698cf03SStefano Zampini     PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVertices));
1313d698cf03SStefano Zampini     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 3));
1314d698cf03SStefano Zampini     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
1315d698cf03SStefano Zampini     PetscCall(DMSetUp(dm));
1316d698cf03SStefano Zampini 
1317d698cf03SStefano Zampini     /* Build cells and Z-edges */
1318d698cf03SStefano Zampini     for (ey = 0; ey < numYEdges; ++ey) {
1319d698cf03SStefano Zampini       for (ex = 0; ex < numXEdges; ++ex) {
1320d698cf03SStefano Zampini         const PetscInt exp1 = (ex + 1) % numXVertices;
1321d698cf03SStefano Zampini         const PetscInt eyp1 = (ey + 1) % numYVertices;
1322d698cf03SStefano Zampini         const PetscInt ez   = firstZEdge + 4 * (ey * numXEdges + ex);
1323d698cf03SStefano Zampini         const PetscInt vc   = firstVertex + numXVertices * numYVertices + ey * numXEdges + ex;
1324d698cf03SStefano Zampini         const PetscInt v0   = firstVertex + ey * numXVertices + ex;
1325d698cf03SStefano Zampini         const PetscInt v1   = firstVertex + ey * numXVertices + exp1;
1326d698cf03SStefano Zampini         const PetscInt v2   = firstVertex + eyp1 * numXVertices + exp1;
1327d698cf03SStefano Zampini         const PetscInt v3   = firstVertex + eyp1 * numXVertices + ex;
1328d698cf03SStefano Zampini         const PetscInt e0   = firstXEdge + ey * numXEdges + ex;
1329d698cf03SStefano Zampini         const PetscInt e1   = firstYEdge + exp1 * numYEdges + ey;
1330d698cf03SStefano Zampini         const PetscInt e2   = firstXEdge + eyp1 * numXEdges + ex;
1331d698cf03SStefano Zampini         const PetscInt e3   = firstYEdge + ex * numYEdges + ey;
1332d698cf03SStefano Zampini 
1333d698cf03SStefano Zampini         const PetscInt cones[] = {ez, e0, ez + 1, ez + 1, e1, ez + 2, ez + 2, e2, ez + 3, ez + 3, e3, ez};
1334d698cf03SStefano Zampini         const PetscInt ornts[] = {-1, 0, 0, -1, 0, 0, -1, -1, 0, -1, -1, 0};
1335d698cf03SStefano Zampini         const PetscInt verts[] = {v0, vc, v1, vc, v2, vc, v3, vc};
1336d698cf03SStefano Zampini 
1337d698cf03SStefano Zampini         for (c = 0; c < 4; c++) {
1338d698cf03SStefano Zampini           PetscInt cell = 4 * (ey * numXEdges + ex) + c;
1339d698cf03SStefano Zampini           PetscInt edge = ez + c;
1340d698cf03SStefano Zampini 
1341d698cf03SStefano Zampini           PetscCall(DMPlexSetCone(dm, cell, cones + 3 * c));
1342d698cf03SStefano Zampini           PetscCall(DMPlexSetConeOrientation(dm, cell, ornts + 3 * c));
1343d698cf03SStefano Zampini           PetscCall(DMPlexSetCone(dm, edge, verts + 2 * c));
1344d698cf03SStefano Zampini         }
1345d698cf03SStefano Zampini       }
1346d698cf03SStefano Zampini     }
1347d698cf03SStefano Zampini 
1348d698cf03SStefano Zampini     /* Build Y edges*/
1349d698cf03SStefano Zampini     for (vx = 0; vx < numXVertices; vx++) {
1350d698cf03SStefano Zampini       for (ey = 0; ey < numYEdges; ey++) {
1351d698cf03SStefano Zampini         const PetscInt edge   = firstYEdge + vx * numYEdges + ey;
1352d698cf03SStefano Zampini         const PetscInt v0     = firstVertex + ey * numXVertices + vx;
1353d698cf03SStefano Zampini         const PetscInt v1     = firstVertex + ((ey + 1) % numYVertices) * numXVertices + vx;
1354d698cf03SStefano Zampini         const PetscInt cone[] = {v0, v1};
1355d698cf03SStefano Zampini 
1356d698cf03SStefano Zampini         PetscCall(DMPlexSetCone(dm, edge, cone));
1357d698cf03SStefano Zampini         if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
1358d698cf03SStefano Zampini           if (vx == numXVertices - 1) {
1359d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
1360d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1361d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1362d698cf03SStefano Zampini             if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1363d698cf03SStefano Zampini           } else if (vx == 0) {
1364d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
1365d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1366d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1367d698cf03SStefano Zampini             if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
1368d698cf03SStefano Zampini           }
1369d698cf03SStefano Zampini         }
1370d698cf03SStefano Zampini       }
1371d698cf03SStefano Zampini     }
1372d698cf03SStefano Zampini 
1373d698cf03SStefano Zampini     /* Build X edges*/
1374d698cf03SStefano Zampini     for (vy = 0; vy < numYVertices; vy++) {
1375d698cf03SStefano Zampini       for (ex = 0; ex < numXEdges; ex++) {
1376d698cf03SStefano Zampini         const PetscInt edge   = firstXEdge + vy * numXEdges + ex;
1377d698cf03SStefano Zampini         const PetscInt v0     = firstVertex + vy * numXVertices + ex;
1378d698cf03SStefano Zampini         const PetscInt v1     = firstVertex + vy * numXVertices + (ex + 1) % numXVertices;
1379d698cf03SStefano Zampini         const PetscInt cone[] = {v0, v1};
1380d698cf03SStefano Zampini 
1381d698cf03SStefano Zampini         PetscCall(DMPlexSetCone(dm, edge, cone));
1382d698cf03SStefano Zampini         if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
1383d698cf03SStefano Zampini           if (vy == numYVertices - 1) {
1384d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
1385d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1386d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1387d698cf03SStefano Zampini             if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1388d698cf03SStefano Zampini           } else if (vy == 0) {
1389d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
1390d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1391d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1392d698cf03SStefano Zampini             if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
1393d698cf03SStefano Zampini           }
1394d698cf03SStefano Zampini         }
1395d698cf03SStefano Zampini       }
1396d698cf03SStefano Zampini     }
1397d698cf03SStefano Zampini 
1398d698cf03SStefano Zampini     /* Compute support, stratify, and celltype label */
1399d698cf03SStefano Zampini     PetscCall(DMPlexSymmetrize(dm));
1400d698cf03SStefano Zampini     PetscCall(DMPlexStratify(dm));
1401d698cf03SStefano Zampini     PetscCall(DMPlexComputeCellTypes(dm));
1402d698cf03SStefano Zampini 
1403d698cf03SStefano Zampini     /* Build coordinates */
1404d698cf03SStefano Zampini     PetscCall(DMGetCoordinateSection(dm, &coordSection));
1405d698cf03SStefano Zampini     PetscCall(PetscSectionSetNumFields(coordSection, 1));
1406d698cf03SStefano Zampini     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2));
1407d698cf03SStefano Zampini     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
1408d698cf03SStefano Zampini     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
1409d698cf03SStefano Zampini       PetscCall(PetscSectionSetDof(coordSection, v, 2));
1410d698cf03SStefano Zampini       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2));
1411d698cf03SStefano Zampini     }
1412d698cf03SStefano Zampini     PetscCall(PetscSectionSetUp(coordSection));
1413d698cf03SStefano Zampini     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
1414d698cf03SStefano Zampini     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
1415d698cf03SStefano Zampini     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
1416d698cf03SStefano Zampini     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
1417d698cf03SStefano Zampini     PetscCall(VecSetBlockSize(coordinates, 2));
1418d698cf03SStefano Zampini     PetscCall(VecSetType(coordinates, VECSTANDARD));
1419d698cf03SStefano Zampini     PetscCall(VecGetArray(coordinates, &coords));
1420d698cf03SStefano Zampini     for (vy = 0; vy < numYVertices; ++vy) {
1421d698cf03SStefano Zampini       for (vx = 0; vx < numXVertices; ++vx) {
1422d698cf03SStefano Zampini         coords[2 * (vy * numXVertices + vx) + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
1423d698cf03SStefano Zampini         coords[2 * (vy * numXVertices + vx) + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
1424d698cf03SStefano Zampini       }
1425d698cf03SStefano Zampini     }
1426d698cf03SStefano Zampini     for (ey = 0; ey < numYEdges; ++ey) {
1427d698cf03SStefano Zampini       for (ex = 0; ex < numXEdges; ++ex) {
1428d698cf03SStefano Zampini         const PetscInt c = ey * numXEdges + ex + numYVertices * numXVertices;
1429d698cf03SStefano Zampini 
1430d698cf03SStefano Zampini         coords[2 * c + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * (ex + 0.5);
1431d698cf03SStefano Zampini         coords[2 * c + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * (ey + 0.5);
1432d698cf03SStefano Zampini       }
1433d698cf03SStefano Zampini     }
1434d698cf03SStefano Zampini     PetscCall(VecRestoreArray(coordinates, &coords));
1435d698cf03SStefano Zampini     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
1436d698cf03SStefano Zampini     PetscCall(VecDestroy(&coordinates));
1437d698cf03SStefano Zampini 
1438d698cf03SStefano Zampini     /* handle periodic BC */
1439d698cf03SStefano Zampini     if (bdX == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_PERIODIC) {
1440d698cf03SStefano Zampini       PetscReal L[2]       = {-1., -1.};
1441d698cf03SStefano Zampini       PetscReal maxCell[2] = {-1., -1.};
1442d698cf03SStefano Zampini 
1443d698cf03SStefano Zampini       for (PetscInt d = 0; d < 2; ++d) {
1444d698cf03SStefano Zampini         if (bd[d] != DM_BOUNDARY_NONE) {
1445d698cf03SStefano Zampini           L[d]       = upper[d] - lower[d];
1446d698cf03SStefano Zampini           maxCell[d] = 1.1 * (L[d] / PetscMax(1, edges[d]));
1447d698cf03SStefano Zampini         }
1448d698cf03SStefano Zampini       }
1449d698cf03SStefano Zampini       PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1450d698cf03SStefano Zampini     }
1451d698cf03SStefano Zampini   }
1452d698cf03SStefano Zampini   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
1453d698cf03SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
1454d698cf03SStefano Zampini }
1455d698cf03SStefano Zampini 
1456d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
1457d71ae5a4SJacob Faibussowitsch {
14589318fe57SMatthew G. Knepley   DM        boundary, vol;
1459c22d3578SMatthew G. Knepley   DMLabel   bdlabel;
1460d698cf03SStefano Zampini   PetscBool crisscross = PETSC_FALSE;
1461d6218766SMatthew G. Knepley 
1462d6218766SMatthew G. Knepley   PetscFunctionBegin;
14634f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
1464d698cf03SStefano Zampini   if (dim == 2) PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_box_crisscross", &crisscross, NULL));
1465d698cf03SStefano Zampini   if (crisscross) {
1466d698cf03SStefano Zampini     PetscCall(DMPlexCreateSquareMesh_Simplex_CrissCross(dm, faces, lower, upper, periodicity));
1467d698cf03SStefano Zampini   } else {
1468c22d3578SMatthew 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");
14699566063dSJacob Faibussowitsch     PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary));
14709566063dSJacob Faibussowitsch     PetscCall(DMSetType(boundary, DMPLEX));
1471d698cf03SStefano Zampini     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)boundary, ((PetscObject)dm)->prefix));
14729566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE));
14739566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol));
1474c22d3578SMatthew G. Knepley     PetscCall(DMGetLabel(vol, "marker", &bdlabel));
1475c22d3578SMatthew G. Knepley     if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel));
14765de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol));
147769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &vol));
1478d698cf03SStefano Zampini     PetscCall(DMDestroy(&boundary));
1479d698cf03SStefano Zampini   }
14804054ae39SJames Wright   if (interpolate) {
14814054ae39SJames Wright     PetscCall(DMPlexInterpolateInPlace_Internal(dm));
1482d7d2d1d2SJames Wright     PetscCall(DMPlexSetBoxLabel_Internal(dm, periodicity));
14834054ae39SJames Wright   }
14843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1485d6218766SMatthew G. Knepley }
1486d6218766SMatthew G. Knepley 
1487d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ)
1488d71ae5a4SJacob Faibussowitsch {
1489ed0e4b50SMatthew G. Knepley   DMLabel     cutLabel  = NULL;
1490f4eb4c5dSMatthew G. Knepley   PetscInt    markerTop = 1, faceMarkerTop = 1;
1491f4eb4c5dSMatthew G. Knepley   PetscInt    markerBottom = 1, faceMarkerBottom = 1;
1492f4eb4c5dSMatthew G. Knepley   PetscInt    markerFront = 1, faceMarkerFront = 1;
1493f4eb4c5dSMatthew G. Knepley   PetscInt    markerBack = 1, faceMarkerBack = 1;
1494f4eb4c5dSMatthew G. Knepley   PetscInt    markerRight = 1, faceMarkerRight = 1;
1495f4eb4c5dSMatthew G. Knepley   PetscInt    markerLeft = 1, faceMarkerLeft = 1;
14963dfda0b1SToby Isaac   PetscInt    dim;
1497d8211ee3SMatthew G. Knepley   PetscBool   markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE;
14983dfda0b1SToby Isaac   PetscMPIInt rank;
14993dfda0b1SToby Isaac 
15003dfda0b1SToby Isaac   PetscFunctionBegin;
15019566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
15029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
15039566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
15049566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
15059566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
15069371c9d4SSatish 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) {
15079371c9d4SSatish Balay     if (cutMarker) {
15089371c9d4SSatish Balay       PetscCall(DMCreateLabel(dm, "periodic_cut"));
15099371c9d4SSatish Balay       PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
15109371c9d4SSatish Balay     }
1511d8211ee3SMatthew G. Knepley   }
15123dfda0b1SToby Isaac   switch (dim) {
15133dfda0b1SToby Isaac   case 2:
1514f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 3;
1515f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
1516f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 2;
1517f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 4;
15183dfda0b1SToby Isaac     break;
15193dfda0b1SToby Isaac   case 3:
1520f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
1521f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 2;
1522f4eb4c5dSMatthew G. Knepley     faceMarkerFront  = 3;
1523f4eb4c5dSMatthew G. Knepley     faceMarkerBack   = 4;
1524f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 5;
1525f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 6;
15263dfda0b1SToby Isaac     break;
1527d71ae5a4SJacob Faibussowitsch   default:
1528d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
15293dfda0b1SToby Isaac   }
15309566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
1531f4eb4c5dSMatthew G. Knepley   if (markerSeparate) {
1532f4eb4c5dSMatthew G. Knepley     markerBottom = faceMarkerBottom;
1533f4eb4c5dSMatthew G. Knepley     markerTop    = faceMarkerTop;
1534f4eb4c5dSMatthew G. Knepley     markerFront  = faceMarkerFront;
1535f4eb4c5dSMatthew G. Knepley     markerBack   = faceMarkerBack;
1536f4eb4c5dSMatthew G. Knepley     markerRight  = faceMarkerRight;
1537f4eb4c5dSMatthew G. Knepley     markerLeft   = faceMarkerLeft;
15383dfda0b1SToby Isaac   }
15393dfda0b1SToby Isaac   {
1540dd400576SPatrick Sanan     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
1541dd400576SPatrick Sanan     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
1542dd400576SPatrick Sanan     const PetscInt numZEdges    = rank == 0 ? edges[2] : 0;
1543dd400576SPatrick Sanan     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0;
1544dd400576SPatrick Sanan     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0;
1545dd400576SPatrick Sanan     const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0;
15463dfda0b1SToby Isaac     const PetscInt numCells     = numXEdges * numYEdges * numZEdges;
15473dfda0b1SToby Isaac     const PetscInt numXFaces    = numYEdges * numZEdges;
15483dfda0b1SToby Isaac     const PetscInt numYFaces    = numXEdges * numZEdges;
15493dfda0b1SToby Isaac     const PetscInt numZFaces    = numXEdges * numYEdges;
15503dfda0b1SToby Isaac     const PetscInt numTotXFaces = numXVertices * numXFaces;
15513dfda0b1SToby Isaac     const PetscInt numTotYFaces = numYVertices * numYFaces;
15523dfda0b1SToby Isaac     const PetscInt numTotZFaces = numZVertices * numZFaces;
15533dfda0b1SToby Isaac     const PetscInt numFaces     = numTotXFaces + numTotYFaces + numTotZFaces;
15543dfda0b1SToby Isaac     const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices;
15553dfda0b1SToby Isaac     const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices;
15563dfda0b1SToby Isaac     const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices;
15573dfda0b1SToby Isaac     const PetscInt numVertices  = numXVertices * numYVertices * numZVertices;
15583dfda0b1SToby Isaac     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numTotZEdges;
15593dfda0b1SToby Isaac     const PetscInt firstVertex  = (dim == 2) ? numFaces : numCells;
15603dfda0b1SToby Isaac     const PetscInt firstXFace   = (dim == 2) ? 0 : numCells + numVertices;
15613dfda0b1SToby Isaac     const PetscInt firstYFace   = firstXFace + numTotXFaces;
15623dfda0b1SToby Isaac     const PetscInt firstZFace   = firstYFace + numTotYFaces;
15633dfda0b1SToby Isaac     const PetscInt firstXEdge   = numCells + numFaces + numVertices;
15643dfda0b1SToby Isaac     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
15653dfda0b1SToby Isaac     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
15663dfda0b1SToby Isaac     Vec            coordinates;
15673dfda0b1SToby Isaac     PetscSection   coordSection;
15683dfda0b1SToby Isaac     PetscScalar   *coords;
15693dfda0b1SToby Isaac     PetscInt       coordSize;
15703dfda0b1SToby Isaac     PetscInt       v, vx, vy, vz;
15713dfda0b1SToby Isaac     PetscInt       c, f, fx, fy, fz, e, ex, ey, ez;
15723dfda0b1SToby Isaac 
15739566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices));
157448a46eb9SPierre Jolivet     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
157548a46eb9SPierre Jolivet     for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
157648a46eb9SPierre Jolivet     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
15779566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
15783dfda0b1SToby Isaac     /* Build cells */
15793dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
15803dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
15813dfda0b1SToby Isaac         for (fx = 0; fx < numXEdges; ++fx) {
15823dfda0b1SToby Isaac           PetscInt cell  = (fz * numYEdges + fy) * numXEdges + fx;
15833dfda0b1SToby Isaac           PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
15843dfda0b1SToby Isaac           PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices);
15853dfda0b1SToby Isaac           PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
15863dfda0b1SToby Isaac           PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices);
15873dfda0b1SToby Isaac           PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
15883dfda0b1SToby Isaac           PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices);
15893dfda0b1SToby Isaac           /* B,  T,  F,  K,  R,  L */
1590b5a892a1SMatthew G. Knepley           PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */
159142206facSLisandro Dalcin           PetscInt cone[6];
15923dfda0b1SToby Isaac 
15933dfda0b1SToby Isaac           /* no boundary twisting in 3D */
15949371c9d4SSatish Balay           cone[0] = faceB;
15959371c9d4SSatish Balay           cone[1] = faceT;
15969371c9d4SSatish Balay           cone[2] = faceF;
15979371c9d4SSatish Balay           cone[3] = faceK;
15989371c9d4SSatish Balay           cone[4] = faceR;
15999371c9d4SSatish Balay           cone[5] = faceL;
16009566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, cell, cone));
16019566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, cell, ornt));
16029566063dSJacob Faibussowitsch           if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
16039566063dSJacob Faibussowitsch           if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
16049566063dSJacob Faibussowitsch           if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
16053dfda0b1SToby Isaac         }
16063dfda0b1SToby Isaac       }
16073dfda0b1SToby Isaac     }
16083dfda0b1SToby Isaac     /* Build x faces */
16093dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
16103dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
16113dfda0b1SToby Isaac         for (fx = 0; fx < numXVertices; ++fx) {
16123dfda0b1SToby Isaac           PetscInt face    = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
16133dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
16143dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz;
16153dfda0b1SToby Isaac           PetscInt edgeB   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
16163dfda0b1SToby Isaac           PetscInt edgeT   = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy;
1617b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
16183dfda0b1SToby Isaac           PetscInt cone[4];
16193dfda0b1SToby Isaac 
16203dfda0b1SToby Isaac           if (dim == 3) {
16213dfda0b1SToby Isaac             /* markers */
16223dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
16233dfda0b1SToby Isaac               if (fx == numXVertices - 1) {
16249566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight));
16259566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerRight));
16269371c9d4SSatish Balay               } else if (fx == 0) {
16279566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft));
16289566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft));
16293dfda0b1SToby Isaac               }
16303dfda0b1SToby Isaac             }
16313dfda0b1SToby Isaac           }
16329371c9d4SSatish Balay           cone[0] = edgeB;
16339371c9d4SSatish Balay           cone[1] = edgeR;
16349371c9d4SSatish Balay           cone[2] = edgeT;
16359371c9d4SSatish Balay           cone[3] = edgeL;
16369566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
16379566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
16383dfda0b1SToby Isaac         }
16393dfda0b1SToby Isaac       }
16403dfda0b1SToby Isaac     }
16413dfda0b1SToby Isaac     /* Build y faces */
16423dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
164342206facSLisandro Dalcin       for (fx = 0; fx < numXEdges; ++fx) {
16443dfda0b1SToby Isaac         for (fy = 0; fy < numYVertices; ++fy) {
16453dfda0b1SToby Isaac           PetscInt face    = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
16463dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
16473dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz;
16483dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
16493dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx;
1650b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
16513dfda0b1SToby Isaac           PetscInt cone[4];
16523dfda0b1SToby Isaac 
16533dfda0b1SToby Isaac           if (dim == 3) {
16543dfda0b1SToby Isaac             /* markers */
16553dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
16563dfda0b1SToby Isaac               if (fy == numYVertices - 1) {
16579566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack));
16589566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBack));
16599371c9d4SSatish Balay               } else if (fy == 0) {
16609566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront));
16619566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerFront));
16623dfda0b1SToby Isaac               }
16633dfda0b1SToby Isaac             }
16643dfda0b1SToby Isaac           }
16659371c9d4SSatish Balay           cone[0] = edgeB;
16669371c9d4SSatish Balay           cone[1] = edgeR;
16679371c9d4SSatish Balay           cone[2] = edgeT;
16689371c9d4SSatish Balay           cone[3] = edgeL;
16699566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
16709566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
16713dfda0b1SToby Isaac         }
16723dfda0b1SToby Isaac       }
16733dfda0b1SToby Isaac     }
16743dfda0b1SToby Isaac     /* Build z faces */
16753dfda0b1SToby Isaac     for (fy = 0; fy < numYEdges; ++fy) {
16763dfda0b1SToby Isaac       for (fx = 0; fx < numXEdges; ++fx) {
16773dfda0b1SToby Isaac         for (fz = 0; fz < numZVertices; fz++) {
16783dfda0b1SToby Isaac           PetscInt face    = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
16793dfda0b1SToby Isaac           PetscInt edgeL   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
16803dfda0b1SToby Isaac           PetscInt edgeR   = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy;
16813dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
16823dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx;
1683b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
16843dfda0b1SToby Isaac           PetscInt cone[4];
16853dfda0b1SToby Isaac 
16863dfda0b1SToby Isaac           if (dim == 2) {
16879371c9d4SSatish Balay             if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) {
16889371c9d4SSatish Balay               edgeR += numYEdges - 1 - 2 * fy;
16899371c9d4SSatish Balay               ornt[1] = -1;
16909371c9d4SSatish Balay             }
16919371c9d4SSatish Balay             if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) {
16929371c9d4SSatish Balay               edgeT += numXEdges - 1 - 2 * fx;
16939371c9d4SSatish Balay               ornt[2] = 0;
16949371c9d4SSatish Balay             }
16959566063dSJacob Faibussowitsch             if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
16969566063dSJacob Faibussowitsch             if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
1697d1c88043SMatthew G. Knepley           } else {
16983dfda0b1SToby Isaac             /* markers */
16993dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
17003dfda0b1SToby Isaac               if (fz == numZVertices - 1) {
17019566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop));
17029566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerTop));
17039371c9d4SSatish Balay               } else if (fz == 0) {
17049566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom));
17059566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom));
17063dfda0b1SToby Isaac               }
17073dfda0b1SToby Isaac             }
17083dfda0b1SToby Isaac           }
17099371c9d4SSatish Balay           cone[0] = edgeB;
17109371c9d4SSatish Balay           cone[1] = edgeR;
17119371c9d4SSatish Balay           cone[2] = edgeT;
17129371c9d4SSatish Balay           cone[3] = edgeL;
17139566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
17149566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
17153dfda0b1SToby Isaac         }
17163dfda0b1SToby Isaac       }
17173dfda0b1SToby Isaac     }
17183dfda0b1SToby Isaac     /* Build Z edges*/
17193dfda0b1SToby Isaac     for (vy = 0; vy < numYVertices; vy++) {
17203dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
17213dfda0b1SToby Isaac         for (ez = 0; ez < numZEdges; ez++) {
17223dfda0b1SToby Isaac           const PetscInt edge    = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez;
17233dfda0b1SToby Isaac           const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx;
17243dfda0b1SToby Isaac           const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx;
17253dfda0b1SToby Isaac           PetscInt       cone[2];
17263dfda0b1SToby Isaac 
17279371c9d4SSatish Balay           cone[0] = vertexB;
17289371c9d4SSatish Balay           cone[1] = vertexT;
1729c2df9bbfSMatthew G. Knepley           PetscCall(DMPlexSetCone(dm, edge, cone));
17303dfda0b1SToby Isaac           if (dim == 3) {
17313dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
17323dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
17339566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1734c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1735c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1736c2df9bbfSMatthew G. Knepley               } else if (vx == 0) {
17379566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1738c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1739c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
17403dfda0b1SToby Isaac               }
17413dfda0b1SToby Isaac             }
17423dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
17433dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
17449566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1745c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1746c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1747c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
17489566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1749c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1750c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
17513dfda0b1SToby Isaac               }
17523dfda0b1SToby Isaac             }
17533dfda0b1SToby Isaac           }
17543dfda0b1SToby Isaac         }
17553dfda0b1SToby Isaac       }
17563dfda0b1SToby Isaac     }
17573dfda0b1SToby Isaac     /* Build Y edges*/
17583dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
17593dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
17603dfda0b1SToby Isaac         for (ey = 0; ey < numYEdges; ey++) {
17613dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx;
17623dfda0b1SToby Isaac           const PetscInt edge    = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey;
17633dfda0b1SToby Isaac           const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx;
17643dfda0b1SToby Isaac           const PetscInt vertexK = firstVertex + nextv;
17653dfda0b1SToby Isaac           PetscInt       cone[2];
17663dfda0b1SToby Isaac 
17679371c9d4SSatish Balay           cone[0] = vertexF;
17689371c9d4SSatish Balay           cone[1] = vertexK;
17699566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
17703dfda0b1SToby Isaac           if (dim == 2) {
17713dfda0b1SToby Isaac             if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
17723dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
17739566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
17749566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
17759566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1776c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1777d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
17789566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
17799566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
17809566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1781c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
17823dfda0b1SToby Isaac               }
1783d8211ee3SMatthew G. Knepley             } else {
17844c67ea77SStefano Zampini               if (vx == 0 && cutLabel) {
17859566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
17869566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1787c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
17883dfda0b1SToby Isaac               }
1789d8211ee3SMatthew G. Knepley             }
1790d8211ee3SMatthew G. Knepley           } else {
17913dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
17923dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
17939566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1794c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1795c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1796d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
17979566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1798c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1799c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
18003dfda0b1SToby Isaac               }
18013dfda0b1SToby Isaac             }
18023dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
18033dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
18049566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1805c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1806c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1807d8211ee3SMatthew G. Knepley               } else if (vz == 0) {
18089566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1809c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1810c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
18113dfda0b1SToby Isaac               }
18123dfda0b1SToby Isaac             }
18133dfda0b1SToby Isaac           }
18143dfda0b1SToby Isaac         }
18153dfda0b1SToby Isaac       }
18163dfda0b1SToby Isaac     }
18173dfda0b1SToby Isaac     /* Build X edges*/
18183dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
18193dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; vy++) {
18203dfda0b1SToby Isaac         for (ex = 0; ex < numXEdges; ex++) {
18213dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices;
18223dfda0b1SToby Isaac           const PetscInt edge    = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex;
18233dfda0b1SToby Isaac           const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex;
18243dfda0b1SToby Isaac           const PetscInt vertexR = firstVertex + nextv;
18253dfda0b1SToby Isaac           PetscInt       cone[2];
18263dfda0b1SToby Isaac 
18279371c9d4SSatish Balay           cone[0] = vertexL;
18289371c9d4SSatish Balay           cone[1] = vertexR;
18299566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
18303dfda0b1SToby Isaac           if (dim == 2) {
18313dfda0b1SToby Isaac             if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
18323dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
18339566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
18349566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
18359566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1836c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1837d8211ee3SMatthew G. Knepley               } else if (vy == 0) {
18389566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
18399566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
18409566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1841c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
18423dfda0b1SToby Isaac               }
1843d8211ee3SMatthew G. Knepley             } else {
18444c67ea77SStefano Zampini               if (vy == 0 && cutLabel) {
18459566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
18469566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1847c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
18483dfda0b1SToby Isaac               }
1849d8211ee3SMatthew G. Knepley             }
1850d8211ee3SMatthew G. Knepley           } else {
18513dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
18523dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
18539566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1854c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1855c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1856c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
18579566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1858c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1859c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
18603dfda0b1SToby Isaac               }
18613dfda0b1SToby Isaac             }
18623dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
18633dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
18649566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1865c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1866c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1867c2df9bbfSMatthew G. Knepley               } else if (vz == 0) {
18689566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1869c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1870c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
18713dfda0b1SToby Isaac               }
18723dfda0b1SToby Isaac             }
18733dfda0b1SToby Isaac           }
18743dfda0b1SToby Isaac         }
18753dfda0b1SToby Isaac       }
18763dfda0b1SToby Isaac     }
18779566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
18789566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
18793dfda0b1SToby Isaac     /* Build coordinates */
18809566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
18819566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
18829566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
18839566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
18843dfda0b1SToby Isaac     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
18859566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
18869566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
18873dfda0b1SToby Isaac     }
18889566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
18899566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
18909566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
18919566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
18929566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
18939566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
18949566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
18959566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
18963dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; ++vz) {
18973dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; ++vy) {
18983dfda0b1SToby Isaac         for (vx = 0; vx < numXVertices; ++vx) {
18993dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
19003dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
1901ad540459SPierre Jolivet           if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz;
19023dfda0b1SToby Isaac         }
19033dfda0b1SToby Isaac       }
19043dfda0b1SToby Isaac     }
19059566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
19069566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
19079566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
19083dfda0b1SToby Isaac   }
19093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19103dfda0b1SToby Isaac }
19113dfda0b1SToby Isaac 
1912d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1913d71ae5a4SJacob Faibussowitsch {
19149318fe57SMatthew G. Knepley   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
19159318fe57SMatthew G. Knepley   PetscInt       fac[3] = {0, 0, 0}, d;
1916552f7358SJed Brown 
1917552f7358SJed Brown   PetscFunctionBegin;
19184f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
19199318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
19209566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
19219371c9d4SSatish Balay   for (d = 0; d < dim; ++d) {
19229371c9d4SSatish Balay     fac[d] = faces[d];
19239371c9d4SSatish Balay     bdt[d] = periodicity[d];
19249371c9d4SSatish Balay   }
19259566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2]));
19269371c9d4SSatish 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))) {
19276858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
19286858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1929552f7358SJed Brown 
19309318fe57SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
19316858538eSMatthew G. Knepley       if (periodicity[d] != DM_BOUNDARY_NONE) {
19329318fe57SMatthew G. Knepley         L[d]       = upper[d] - lower[d];
19339318fe57SMatthew G. Knepley         maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d]));
1934768d5fceSMatthew G. Knepley       }
19356858538eSMatthew G. Knepley     }
19364fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1937768d5fceSMatthew G. Knepley   }
19389566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
19393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19409318fe57SMatthew G. Knepley }
19419318fe57SMatthew G. Knepley 
19425dca41c3SJed 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)
1943d71ae5a4SJacob Faibussowitsch {
19449318fe57SMatthew G. Knepley   PetscFunctionBegin;
194546139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
19465dca41c3SJed Brown   if (shape == DM_SHAPE_ZBOX) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
19476725e60dSJed Brown   else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0]));
19489566063dSJacob Faibussowitsch   else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
19499566063dSJacob Faibussowitsch   else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity));
19509318fe57SMatthew G. Knepley   if (!interpolate && dim > 1 && !simplex) {
1951768d5fceSMatthew G. Knepley     DM udm;
1952768d5fceSMatthew G. Knepley 
19539566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(dm, &udm));
19549566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, udm));
195569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &udm));
1956768d5fceSMatthew G. Knepley   }
195746139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
19583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1959c8c68bd8SToby Isaac }
1960c8c68bd8SToby Isaac 
19615d83a8b1SBarry Smith /*@
1962768d5fceSMatthew G. Knepley   DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra).
1963768d5fceSMatthew G. Knepley 
1964d083f849SBarry Smith   Collective
1965768d5fceSMatthew G. Knepley 
1966768d5fceSMatthew G. Knepley   Input Parameters:
1967a1cb98faSBarry Smith + comm               - The communicator for the `DM` object
1968768d5fceSMatthew G. Knepley . dim                - The spatial dimension
1969a1cb98faSBarry Smith . simplex            - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells
197020f4b53cSBarry Smith . faces              - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
197120f4b53cSBarry Smith . lower              - The lower left corner, or `NULL` for (0, 0, 0)
197220f4b53cSBarry Smith . upper              - The upper right corner, or `NULL` for (1, 1, 1)
197320f4b53cSBarry Smith . periodicity        - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE`
197442108689Sksagiyam . interpolate        - Flag to create intermediate mesh pieces (edges, faces)
197542108689Sksagiyam . localizationHeight - Flag to localize edges and faces in addition to cells; only significant for periodic meshes
197642108689Sksagiyam - sparseLocalize     - Flag to localize coordinates only for cells near the periodic boundary; only significant for periodic meshes
1977768d5fceSMatthew G. Knepley 
1978768d5fceSMatthew G. Knepley   Output Parameter:
1979a1cb98faSBarry Smith . dm - The `DM` object
1980768d5fceSMatthew G. Knepley 
1981768d5fceSMatthew G. Knepley   Level: beginner
1982768d5fceSMatthew G. Knepley 
1983a1cb98faSBarry Smith   Note:
1984a1cb98faSBarry Smith   To customize this mesh using options, use
1985a1cb98faSBarry Smith .vb
1986a1cb98faSBarry Smith   DMCreate(comm, &dm);
1987a1cb98faSBarry Smith   DMSetType(dm, DMPLEX);
1988a1cb98faSBarry Smith   DMSetFromOptions(dm);
1989a1cb98faSBarry Smith .ve
1990a1cb98faSBarry Smith   and use the options in `DMSetFromOptions()`.
1991a1cb98faSBarry Smith 
1992a4e35b19SJacob Faibussowitsch   Here is the numbering returned for 2 faces in each direction for tensor cells\:
1993a1cb98faSBarry Smith .vb
1994a1cb98faSBarry Smith  10---17---11---18----12
1995a1cb98faSBarry Smith   |         |         |
1996a1cb98faSBarry Smith   |         |         |
1997a1cb98faSBarry Smith  20    2   22    3    24
1998a1cb98faSBarry Smith   |         |         |
1999a1cb98faSBarry Smith   |         |         |
2000a1cb98faSBarry Smith   7---15----8---16----9
2001a1cb98faSBarry Smith   |         |         |
2002a1cb98faSBarry Smith   |         |         |
2003a1cb98faSBarry Smith  19    0   21    1   23
2004a1cb98faSBarry Smith   |         |         |
2005a1cb98faSBarry Smith   |         |         |
2006a1cb98faSBarry Smith   4---13----5---14----6
2007a1cb98faSBarry Smith .ve
2008a1cb98faSBarry Smith   and for simplicial cells
2009a1cb98faSBarry Smith .vb
2010a1cb98faSBarry Smith  14----8---15----9----16
2011a1cb98faSBarry Smith   |\     5  |\      7 |
2012a1cb98faSBarry Smith   | \       | \       |
2013a1cb98faSBarry Smith  13   2    14    3    15
2014a1cb98faSBarry Smith   | 4   \   | 6   \   |
2015a1cb98faSBarry Smith   |       \ |       \ |
2016a1cb98faSBarry Smith  11----6---12----7----13
2017a1cb98faSBarry Smith   |\        |\        |
2018a1cb98faSBarry Smith   | \    1  | \     3 |
2019a1cb98faSBarry Smith  10   0    11    1    12
2020a1cb98faSBarry Smith   | 0   \   | 2   \   |
2021a1cb98faSBarry Smith   |       \ |       \ |
2022a1cb98faSBarry Smith   8----4----9----5----10
2023a1cb98faSBarry Smith .ve
2024a1cb98faSBarry Smith 
20251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
2026768d5fceSMatthew G. Knepley @*/
202742108689Sksagiyam 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)
2028d71ae5a4SJacob Faibussowitsch {
20299318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
2030fdbf62faSLisandro Dalcin   PetscReal      low[3] = {0, 0, 0};
2031fdbf62faSLisandro Dalcin   PetscReal      upp[3] = {1, 1, 1};
2032fdbf62faSLisandro Dalcin   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
2033552f7358SJed Brown 
2034768d5fceSMatthew G. Knepley   PetscFunctionBegin;
20359566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
20369566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
20375dca41c3SJed Brown   PetscCall(DMPlexCreateBoxMesh_Internal(*dm, DM_SHAPE_BOX, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate));
203842108689Sksagiyam   if (periodicity) {
203942108689Sksagiyam     DM cdm;
204042108689Sksagiyam 
204142108689Sksagiyam     PetscCall(DMGetCoordinateDM(*dm, &cdm));
204242108689Sksagiyam     PetscCall(DMPlexSetMaxProjectionHeight(cdm, localizationHeight));
204342108689Sksagiyam     PetscCall(DMSetSparseLocalize(*dm, sparseLocalize));
204442108689Sksagiyam     PetscCall(DMLocalizeCoordinates(*dm));
204542108689Sksagiyam   }
20463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20479318fe57SMatthew G. Knepley }
2048fdbf62faSLisandro Dalcin 
2049d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
2050d71ae5a4SJacob Faibussowitsch {
20519318fe57SMatthew G. Knepley   DM       bdm, vol;
20529318fe57SMatthew G. Knepley   PetscInt i;
20539318fe57SMatthew G. Knepley 
20549318fe57SMatthew G. Knepley   PetscFunctionBegin;
20551fcf445aSMatthew G. Knepley   // TODO Now we can support periodicity
205608401ef6SPierre Jolivet   for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported");
20579566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm));
20589566063dSJacob Faibussowitsch   PetscCall(DMSetType(bdm, DMPLEX));
20599566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(bdm, 2));
206046139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, bdm, 0, 0, 0));
20619566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE));
20621fcf445aSMatthew G. Knepley   PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, NULL, NULL, &vol));
206346139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, bdm, 0, 0, 0));
20649566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&bdm));
206569d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
20669318fe57SMatthew G. Knepley   if (lower[2] != 0.0) {
20679318fe57SMatthew G. Knepley     Vec          v;
20689318fe57SMatthew G. Knepley     PetscScalar *x;
20699318fe57SMatthew G. Knepley     PetscInt     cDim, n;
20709318fe57SMatthew G. Knepley 
20719566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &v));
20729566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(v, &cDim));
20739566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(v, &n));
20749566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v, &x));
20759318fe57SMatthew G. Knepley     x += cDim;
20769318fe57SMatthew G. Knepley     for (i = 0; i < n; i += cDim) x[i] += lower[2];
20779566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v, &x));
20789566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, v));
20799318fe57SMatthew G. Knepley   }
20803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2081552f7358SJed Brown }
2082552f7358SJed Brown 
208300dabe28SStefano Zampini /*@
208439f4f5dbSPierre Jolivet   DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tessellating the (x,y) plane and extruding in the third direction using wedge cells.
208500dabe28SStefano Zampini 
2086d083f849SBarry Smith   Collective
208700dabe28SStefano Zampini 
208800dabe28SStefano Zampini   Input Parameters:
2089a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
209020f4b53cSBarry Smith . faces       - Number of faces per dimension, or `NULL` for (1, 1, 1)
209120f4b53cSBarry Smith . lower       - The lower left corner, or `NULL` for (0, 0, 0)
209220f4b53cSBarry Smith . upper       - The upper right corner, or `NULL` for (1, 1, 1)
209320f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE`
2094a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first
209500dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces)
209600dabe28SStefano Zampini 
209700dabe28SStefano Zampini   Output Parameter:
2098a1cb98faSBarry Smith . dm - The `DM` object
209900dabe28SStefano Zampini 
210000dabe28SStefano Zampini   Level: beginner
210100dabe28SStefano Zampini 
21021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
210300dabe28SStefano Zampini @*/
2104d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm)
2105d71ae5a4SJacob Faibussowitsch {
21069318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
210700dabe28SStefano Zampini   PetscReal      low[3] = {0, 0, 0};
210800dabe28SStefano Zampini   PetscReal      upp[3] = {1, 1, 1};
210900dabe28SStefano Zampini   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
211000dabe28SStefano Zampini 
211100dabe28SStefano Zampini   PetscFunctionBegin;
21129566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
21139566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
21149566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt));
2115d410b0cfSMatthew G. Knepley   if (!interpolate) {
2116d410b0cfSMatthew G. Knepley     DM udm;
211700dabe28SStefano Zampini 
21189566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(*dm, &udm));
211969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(*dm, &udm));
212000dabe28SStefano Zampini   }
21217ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
21223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
212300dabe28SStefano Zampini }
212400dabe28SStefano Zampini 
2125cfb853baSMatthew G. Knepley /*
2126cfb853baSMatthew 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.
2127cfb853baSMatthew G. Knepley 
2128cfb853baSMatthew G. Knepley   Input Parameters:
2129cfb853baSMatthew G. Knepley + len - The length of the tuple
2130cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max)
2131cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition
2132cfb853baSMatthew G. Knepley 
2133cfb853baSMatthew G. Knepley   Output Parameter:
213420f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max`
2135cfb853baSMatthew G. Knepley 
2136cfb853baSMatthew G. Knepley   Level: developer
2137cfb853baSMatthew G. Knepley 
213820f4b53cSBarry Smith   Note:
213920f4b53cSBarry Smith   Ordering is lexicographic with lowest index as least significant in ordering.
214020f4b53cSBarry 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}.
214120f4b53cSBarry Smith 
2142cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal()
2143cfb853baSMatthew G. Knepley */
2144cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[])
2145cfb853baSMatthew G. Knepley {
2146cfb853baSMatthew G. Knepley   PetscInt i;
2147cfb853baSMatthew G. Knepley 
2148cfb853baSMatthew G. Knepley   PetscFunctionBegin;
2149cfb853baSMatthew G. Knepley   for (i = 0; i < len; ++i) {
2150cfb853baSMatthew G. Knepley     if (tup[i] < max[i] - 1) {
2151cfb853baSMatthew G. Knepley       break;
2152cfb853baSMatthew G. Knepley     } else {
2153cfb853baSMatthew G. Knepley       tup[i] = 0;
2154cfb853baSMatthew G. Knepley     }
2155cfb853baSMatthew G. Knepley   }
2156cfb853baSMatthew G. Knepley   if (i == len) tup[i - 1] = max[i - 1];
2157cfb853baSMatthew G. Knepley   else ++tup[i];
21583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2159cfb853baSMatthew G. Knepley }
2160cfb853baSMatthew G. Knepley 
2161cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[])
2162cfb853baSMatthew G. Knepley {
21638d2ec52aSSatish Balay   PetscInt idx = tup[len - 1];
2164cfb853baSMatthew G. Knepley 
21658d2ec52aSSatish Balay   for (PetscInt i = len - 2; i >= 0; --i) {
2166cfb853baSMatthew G. Knepley     idx *= max[i];
2167cfb853baSMatthew G. Knepley     idx += tup[i];
2168cfb853baSMatthew G. Knepley   }
2169cfb853baSMatthew G. Knepley   return idx;
2170cfb853baSMatthew G. Knepley }
2171cfb853baSMatthew G. Knepley 
21728d2ec52aSSatish Balay static void IndexToTuple_Private(PetscInt len, const PetscInt max[], PetscInt idx, PetscInt tup[])
2173cfb853baSMatthew G. Knepley {
21748d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
21758d2ec52aSSatish Balay     tup[i] = idx % max[i];
21768d2ec52aSSatish Balay     idx    = (idx - tup[i]) / max[i];
21778d2ec52aSSatish Balay   }
21788d2ec52aSSatish Balay }
21798d2ec52aSSatish Balay 
21808d2ec52aSSatish Balay static void TupleToRanks_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt tup[], PetscInt ranks[])
21818d2ec52aSSatish Balay {
21828d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
21838d2ec52aSSatish Balay     const PetscInt div = max[i] / procs[i];
21848d2ec52aSSatish Balay     const PetscInt rem = max[i] % procs[i];
21858d2ec52aSSatish Balay     const PetscInt idx = (tup[i] < 0 ? max[i] + tup[i] : tup[i]) % max[i];
21868d2ec52aSSatish Balay 
21878d2ec52aSSatish Balay     if (idx < rem * (div + 1)) ranks[i] = idx / (div + 1);
21888d2ec52aSSatish Balay     else ranks[i] = rem + (idx - rem * (div + 1)) / div;
21898d2ec52aSSatish Balay   }
21908d2ec52aSSatish Balay }
21918d2ec52aSSatish Balay 
21928d2ec52aSSatish Balay static void RanksToSizes_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt ranks[], PetscInt sizes[])
21938d2ec52aSSatish Balay {
21948d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
21958d2ec52aSSatish Balay     const PetscInt div = max[i] / procs[i];
21968d2ec52aSSatish Balay     const PetscInt rem = max[i] % procs[i];
21978d2ec52aSSatish Balay 
21988d2ec52aSSatish Balay     sizes[i] = ranks[i] < rem ? div + 1 : div;
21998d2ec52aSSatish Balay   }
22008d2ec52aSSatish Balay }
22018d2ec52aSSatish Balay 
22028d2ec52aSSatish Balay /*
22038d2ec52aSSatish 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.
22048d2ec52aSSatish Balay 
22058d2ec52aSSatish 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.
22068d2ec52aSSatish Balay 
22078d2ec52aSSatish 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.
2208dfe9cfe5SMatthew Knepley 
2209dfe9cfe5SMatthew Knepley   Parallel Layout:
2210dfe9cfe5SMatthew Knepley 
2211dfe9cfe5SMatthew 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.
22128d2ec52aSSatish Balay */
22138d2ec52aSSatish Balay static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], PetscInt overlap, const DMBoundaryType bd[])
22148d2ec52aSSatish Balay {
22158d2ec52aSSatish Balay   const PetscInt debug = ((DM_Plex *)dm->data)->printAdj;
22168d2ec52aSSatish Balay   PetscSF        sf;
2217cfb853baSMatthew G. Knepley   Vec            coordinates;
2218cfb853baSMatthew G. Knepley   PetscSection   coordSection;
2219cfb853baSMatthew G. Knepley   DMLabel        cutLabel    = NULL;
2220cfb853baSMatthew G. Knepley   PetscBool      cutMarker   = PETSC_FALSE;
2221cfb853baSMatthew G. Knepley   PetscBool      periodic    = PETSC_FALSE;
22228d2ec52aSSatish Balay   PetscInt       numCells    = 1;
22238d2ec52aSSatish Balay   PetscInt       numVertices = 1;
22248d2ec52aSSatish Balay   PetscSFNode   *remotes;
2225cfb853baSMatthew G. Knepley   PetscScalar   *coords;
22268d2ec52aSSatish Balay   PetscInt      *procs;     // The number of processes along each dimension
22278d2ec52aSSatish Balay   PetscInt      *lrank;     // Rank in each dimension, lrank[d] \in [0, procs[d])
22288d2ec52aSSatish Balay   PetscInt      *ledges;    // The number of edges along each dimension for this process
22298d2ec52aSSatish Balay   PetscInt      *vstart;    // The first vertex along each dimension on this processes
22308d2ec52aSSatish Balay   PetscInt      *vertices;  // The number of vertices along each dimension on this process
22318d2ec52aSSatish Balay   PetscInt      *rvert;     // The global (not local) vertex number along each dimension
22328d2ec52aSSatish Balay   PetscInt      *rrank;     // The rank along each dimension for the process owning rvert[]
22338d2ec52aSSatish Balay   PetscInt      *rvertices; // The number of vertices along each dimension for the process rrank[]
22348d2ec52aSSatish Balay   PetscInt      *vert, *vtmp, *supp, cone[2], *leaves;
22358d2ec52aSSatish Balay   PetscInt       cell = 0, coordSize, Nl = 0, Nl2 = 0;
22368d2ec52aSSatish Balay   PetscMPIInt    rank, size;
22378d2ec52aSSatish Balay   MPI_Comm       comm;
2238cfb853baSMatthew G. Knepley 
2239cfb853baSMatthew G. Knepley   PetscFunctionBegin;
22408d2ec52aSSatish Balay   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
22418d2ec52aSSatish Balay   PetscCallMPI(MPI_Comm_rank(comm, &rank));
22428d2ec52aSSatish Balay   PetscCallMPI(MPI_Comm_size(comm, &size));
2243cfb853baSMatthew G. Knepley   PetscCall(DMSetDimension(dm, dim));
22448d2ec52aSSatish Balay   PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
22458d2ec52aSSatish Balay   PetscCall(PetscCalloc4(dim, &procs, dim, &lrank, dim, &rrank, 2 * dim, &supp));
22468d2ec52aSSatish Balay   PetscCall(PetscCalloc7(dim, &ledges, dim, &vertices, dim, &rvertices, dim, &vert, dim, &rvert, dim, &vstart, dim, &vtmp));
2247cfb853baSMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "marker"));
2248cfb853baSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
22498d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE;
2250cfb853baSMatthew G. Knepley   if (periodic && cutMarker) {
2251cfb853baSMatthew G. Knepley     PetscCall(DMCreateLabel(dm, "periodic_cut"));
2252cfb853baSMatthew G. Knepley     PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
2253cfb853baSMatthew G. Knepley   }
22548d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, comm, PETSC_ERR_SUP, "Hypercubic mesh must be periodic now");
22558d2ec52aSSatish Balay   overlap = overlap == PETSC_DETERMINE ? 1 : overlap;
22568d2ec52aSSatish Balay   PetscCheck(overlap >= 1, comm, PETSC_ERR_SUP, "Overlap %" PetscInt_FMT " must be greater than 0", overlap);
22578d2ec52aSSatish Balay   if (size > 1) {
22588d2ec52aSSatish Balay     PetscInt Npr = 1;
22598d2ec52aSSatish Balay 
22608d2ec52aSSatish Balay     // Make process grid
22618d2ec52aSSatish Balay     if (debug) PetscCall(PetscPrintf(comm, "Process grid:"));
22628d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
22638d2ec52aSSatish Balay       procs[d] = PetscRintReal(PetscPowReal(size, 1. / dim));
22648d2ec52aSSatish Balay       Npr *= procs[d];
22658d2ec52aSSatish Balay       if (debug) PetscCall(PetscPrintf(comm, " %" PetscInt_FMT, procs[d]));
22668d2ec52aSSatish Balay     }
22678d2ec52aSSatish Balay     if (debug) PetscCall(PetscPrintf(comm, "\n"));
22688d2ec52aSSatish Balay     PetscCheck(Npr == size, comm, PETSC_ERR_PLIB, "Process grid size %" PetscInt_FMT " != %d comm size", Npr, size);
22698d2ec52aSSatish Balay     IndexToTuple_Private(dim, procs, rank, lrank);
22708d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
22718d2ec52aSSatish Balay       ledges[d] = edges[d] / procs[d] + (edges[d] % procs[d] > lrank[d] ? 1 : 0);
22728d2ec52aSSatish Balay       vstart[d] = 0;
22738d2ec52aSSatish Balay       for (PetscInt r = 0; r < lrank[d]; ++r) vstart[d] += edges[d] / procs[d] + (edges[d] % procs[d] > r ? 1 : 0);
22748d2ec52aSSatish Balay       vstart[d] -= overlap; // For halo
22758d2ec52aSSatish Balay     }
22768d2ec52aSSatish Balay   } else {
22778d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
22788d2ec52aSSatish Balay       procs[d]  = 1;
22798d2ec52aSSatish Balay       ledges[d] = edges[d];
22808d2ec52aSSatish Balay     }
22818d2ec52aSSatish Balay   }
22828d2ec52aSSatish Balay   // Calculate local patch size
22838d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) {
22848d2ec52aSSatish Balay     vertices[d] = ledges[d] + (procs[d] > 1 ? 2 * overlap : 0);
2285cfb853baSMatthew G. Knepley     numVertices *= vertices[d];
2286cfb853baSMatthew G. Knepley   }
2287cfb853baSMatthew G. Knepley   numCells = numVertices * dim;
2288cfb853baSMatthew G. Knepley   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
22898d2ec52aSSatish Balay   for (PetscInt c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2));
22908d2ec52aSSatish Balay   for (PetscInt v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim));
2291cfb853baSMatthew G. Knepley   PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */
2292cfb853baSMatthew G. Knepley   /* Build cell cones and vertex supports */
2293cfb853baSMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "celltype"));
22948d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Topology for rank %d:\n", rank));
2295cfb853baSMatthew G. Knepley   while (vert[dim - 1] < vertices[dim - 1]) {
2296cfb853baSMatthew G. Knepley     const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells;
2297cfb853baSMatthew G. Knepley     PetscInt       s      = 0;
22988d2ec52aSSatish Balay     PetscBool      leaf   = PETSC_FALSE;
2299cfb853baSMatthew G. Knepley 
23008d2ec52aSSatish Balay     if (debug) {
23018d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex));
23028d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d]));
23038d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "\n"));
23048d2ec52aSSatish Balay     }
2305cfb853baSMatthew G. Knepley     PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT));
23068d2ec52aSSatish Balay     // Define edge cones
23078d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
23088d2ec52aSSatish Balay       for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e];
2309cfb853baSMatthew G. Knepley       vtmp[d] = (vert[d] + 1) % vertices[d];
2310cfb853baSMatthew G. Knepley       cone[0] = vertex;
2311cfb853baSMatthew G. Knepley       cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells;
23128d2ec52aSSatish Balay       if (debug) {
23138d2ec52aSSatish Balay         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ":", cone[1]));
23148d2ec52aSSatish Balay         for (PetscInt e = 0; e < dim; ++e) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vtmp[e]));
23158d2ec52aSSatish Balay         PetscCall(PetscSynchronizedPrintf(comm, "\n"));
23168d2ec52aSSatish Balay       }
2317cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetCone(dm, cell, cone));
2318cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT));
23198d2ec52aSSatish Balay       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1]));
2320cfb853baSMatthew G. Knepley       ++cell;
23218d2ec52aSSatish Balay       // Shared vertices are any in the first or last overlap layers
23228d2ec52aSSatish Balay       if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE;
2323cfb853baSMatthew G. Knepley     }
23248d2ec52aSSatish Balay     if (size > 1 && leaf) ++Nl;
23258d2ec52aSSatish Balay     // Define vertex supports
23268d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
23278d2ec52aSSatish Balay       for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e];
2328cfb853baSMatthew G. Knepley       vtmp[d]   = (vert[d] + vertices[d] - 1) % vertices[d];
2329cfb853baSMatthew G. Knepley       supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d;
2330cfb853baSMatthew G. Knepley       supp[s++] = (vertex - numCells) * dim + d;
2331cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetSupport(dm, vertex, supp));
2332cfb853baSMatthew G. Knepley     }
2333cfb853baSMatthew G. Knepley     PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert));
2334cfb853baSMatthew G. Knepley   }
23358d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
2336cfb853baSMatthew G. Knepley   PetscCall(DMPlexStratify(dm));
23378d2ec52aSSatish Balay   // Allocate for SF
23388d2ec52aSSatish Balay   PetscCall(PetscMalloc1(Nl, &leaves));
23398d2ec52aSSatish Balay   PetscCall(PetscMalloc1(Nl, &remotes));
23408d2ec52aSSatish Balay   // Build coordinates
2341cfb853baSMatthew G. Knepley   PetscCall(DMGetCoordinateSection(dm, &coordSection));
2342cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetNumFields(coordSection, 1));
2343cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
2344cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
23458d2ec52aSSatish Balay   for (PetscInt v = numCells; v < numCells + numVertices; ++v) {
2346cfb853baSMatthew G. Knepley     PetscCall(PetscSectionSetDof(coordSection, v, dim));
2347cfb853baSMatthew G. Knepley     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
2348cfb853baSMatthew G. Knepley   }
2349cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetUp(coordSection));
2350cfb853baSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
23518d2ec52aSSatish Balay   PetscCall(VecCreate(comm, &coordinates));
2352cfb853baSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
2353cfb853baSMatthew G. Knepley   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
2354cfb853baSMatthew G. Knepley   PetscCall(VecSetBlockSize(coordinates, dim));
2355cfb853baSMatthew G. Knepley   PetscCall(VecSetType(coordinates, VECSTANDARD));
2356cfb853baSMatthew G. Knepley   PetscCall(VecGetArray(coordinates, &coords));
23578d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Geometry for rank %d:\n", rank));
23588d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) vert[d] = 0;
2359cfb853baSMatthew G. Knepley   while (vert[dim - 1] < vertices[dim - 1]) {
2360cfb853baSMatthew G. Knepley     const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert);
23618d2ec52aSSatish Balay     PetscBool      leaf   = PETSC_FALSE;
2362cfb853baSMatthew G. Knepley 
23638d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
23648d2ec52aSSatish Balay       coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / edges[d]) * (vert[d] + vstart[d]);
23658d2ec52aSSatish Balay       if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE;
23668d2ec52aSSatish Balay     }
23678d2ec52aSSatish Balay     if (size > 1 && leaf) {
23688d2ec52aSSatish Balay       PetscInt rnumCells = 1;
23698d2ec52aSSatish Balay 
23708d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) rvert[d] = vert[d] + vstart[d];
23718d2ec52aSSatish Balay       TupleToRanks_Private(dim, edges, procs, rvert, rrank);
23728d2ec52aSSatish Balay       leaves[Nl2]       = vertex + numCells;
23738d2ec52aSSatish Balay       remotes[Nl2].rank = TupleToIndex_Private(dim, procs, rrank);
23748d2ec52aSSatish Balay       RanksToSizes_Private(dim, edges, procs, rrank, rvertices);
23758d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) {
23768d2ec52aSSatish Balay         rvertices[d] += 2 * overlap; // Add halo
23778d2ec52aSSatish Balay         rnumCells *= rvertices[d];
23788d2ec52aSSatish Balay       }
23798d2ec52aSSatish Balay       rnumCells *= dim;
23808d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) {
23818d2ec52aSSatish Balay         const PetscInt diff = rrank[d] - lrank[d];
23828d2ec52aSSatish Balay 
23838d2ec52aSSatish Balay         if (!diff) rvert[d] = vert[d];                                     // Vertex is local
23848d2ec52aSSatish Balay         else if (rvert[d] < 0) rvert[d] = rvertices[d] - 1 + rvert[d];     // Wrap around at the bottom
23858d2ec52aSSatish Balay         else if (rvert[d] >= edges[d]) rvert[d] = rvert[d] - edges[d] + 1; // Wrap around at the top
23868d2ec52aSSatish Balay         else if (diff == -1) rvert[d] = rvertices[d] - 1 + (vert[d] - overlap);
23878d2ec52aSSatish Balay         else if (diff == 1) rvert[d] = (vertices[d] - vert[d] - 1) + overlap;
23888d2ec52aSSatish Balay         else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Process distance %" PetscInt_FMT " in direction %" PetscInt_FMT " should not be possible", diff, d);
23898d2ec52aSSatish Balay       }
23908d2ec52aSSatish Balay       remotes[Nl2].index = TupleToIndex_Private(dim, rvertices, rvert) + rnumCells;
23918d2ec52aSSatish Balay       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Shared Vertex %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", leaves[Nl2], remotes[Nl2].rank, remotes[Nl2].index));
23928d2ec52aSSatish Balay       ++Nl2;
23938d2ec52aSSatish Balay     }
23948d2ec52aSSatish Balay     if (debug) {
23958d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex));
23968d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d] + vstart[d]));
23978d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %g", (double)PetscRealPart(coords[vertex * dim + d])));
23988d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "\n"));
23998d2ec52aSSatish Balay     }
2400cfb853baSMatthew G. Knepley     PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert));
2401cfb853baSMatthew G. Knepley   }
24028d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
2403cfb853baSMatthew G. Knepley   PetscCall(VecRestoreArray(coordinates, &coords));
2404cfb853baSMatthew G. Knepley   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
2405cfb853baSMatthew G. Knepley   PetscCall(VecDestroy(&coordinates));
24068d2ec52aSSatish Balay   // Build SF
24078d2ec52aSSatish Balay   PetscCheck(Nl == Nl2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Initial number of leaves %" PetscInt_FMT " != %" PetscInt_FMT " final number", Nl, Nl2);
24088d2ec52aSSatish Balay   PetscCall(DMGetPointSF(dm, &sf));
24098d2ec52aSSatish Balay   PetscCall(PetscSFSetGraph(sf, numCells + numVertices, Nl, leaves, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER));
24108d2ec52aSSatish Balay   if (debug) PetscCall(PetscSFView(sf, PETSC_VIEWER_STDOUT_WORLD));
2411cfb853baSMatthew G. Knepley   //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper));
2412cfb853baSMatthew G. Knepley   // Attach the extent
2413cfb853baSMatthew G. Knepley   {
2414cfb853baSMatthew G. Knepley     PetscContainer c;
24158d2ec52aSSatish Balay     PetscInt      *extent, *lextent;
2416cfb853baSMatthew G. Knepley 
2417cfb853baSMatthew G. Knepley     PetscCall(PetscMalloc1(dim, &extent));
24188d2ec52aSSatish Balay     PetscCall(PetscMalloc1(dim, &lextent));
24198d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
24208d2ec52aSSatish Balay       extent[d]  = edges[d];
24218d2ec52aSSatish Balay       lextent[d] = ledges[d];
24228d2ec52aSSatish Balay     }
2423cfb853baSMatthew G. Knepley     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c));
242449abdd8aSBarry Smith     PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault));
2425cfb853baSMatthew G. Knepley     PetscCall(PetscContainerSetPointer(c, extent));
2426cfb853baSMatthew G. Knepley     PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c));
2427cfb853baSMatthew G. Knepley     PetscCall(PetscContainerDestroy(&c));
24288d2ec52aSSatish Balay     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c));
24298d2ec52aSSatish Balay     PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault));
24308d2ec52aSSatish Balay     PetscCall(PetscContainerSetPointer(c, lextent));
24318d2ec52aSSatish Balay     PetscCall(PetscObjectCompose((PetscObject)dm, "_lextent", (PetscObject)c));
24328d2ec52aSSatish Balay     PetscCall(PetscContainerDestroy(&c));
2433cfb853baSMatthew G. Knepley   }
24348d2ec52aSSatish Balay   PetscCall(PetscFree4(procs, lrank, rrank, supp));
24358d2ec52aSSatish Balay   PetscCall(PetscFree7(ledges, vertices, rvertices, vert, rvert, vstart, vtmp));
24363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2437cfb853baSMatthew G. Knepley }
2438cfb853baSMatthew G. Knepley 
2439cfb853baSMatthew G. Knepley /*@C
2440aaa8cc7dSPierre Jolivet   DMPlexCreateHypercubicMesh - Creates a periodic mesh on the tensor product of unit intervals using only vertices and edges.
2441cfb853baSMatthew G. Knepley 
2442cfb853baSMatthew G. Knepley   Collective
2443cfb853baSMatthew G. Knepley 
2444cfb853baSMatthew G. Knepley   Input Parameters:
24458d2ec52aSSatish Balay + comm    - The communicator for the `DM` object
2446cfb853baSMatthew G. Knepley . dim     - The spatial dimension
244720f4b53cSBarry Smith . edges   - Number of edges per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
244820f4b53cSBarry Smith . lower   - The lower left corner, or `NULL` for (0, 0, 0)
24498d2ec52aSSatish Balay . upper   - The upper right corner, or `NULL` for (1, 1, 1)
24508d2ec52aSSatish Balay - overlap - The number of vertices in each direction to include in the overlap (default is 1)
2451cfb853baSMatthew G. Knepley 
2452cfb853baSMatthew G. Knepley   Output Parameter:
2453cfb853baSMatthew G. Knepley . dm - The DM object
2454cfb853baSMatthew G. Knepley 
245520f4b53cSBarry Smith   Level: beginner
245620f4b53cSBarry Smith 
245720f4b53cSBarry Smith   Note:
245820f4b53cSBarry Smith   If you want to customize this mesh using options, you just need to
245920f4b53cSBarry Smith .vb
246020f4b53cSBarry Smith   DMCreate(comm, &dm);
246120f4b53cSBarry Smith   DMSetType(dm, DMPLEX);
246220f4b53cSBarry Smith   DMSetFromOptions(dm);
246320f4b53cSBarry Smith .ve
246420f4b53cSBarry Smith   and use the options on the `DMSetFromOptions()` page.
2465cfb853baSMatthew G. Knepley 
2466cfb853baSMatthew G. Knepley   The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively,
246720f4b53cSBarry Smith .vb
246820f4b53cSBarry Smith  18--0-19--2-20--4-18
246920f4b53cSBarry Smith   |     |     |     |
247020f4b53cSBarry Smith  13    15    17    13
247120f4b53cSBarry Smith   |     |     |     |
247220f4b53cSBarry Smith  24-12-25-14-26-16-24
247320f4b53cSBarry Smith   |     |     |     |
247420f4b53cSBarry Smith   7     9    11     7
247520f4b53cSBarry Smith   |     |     |     |
247620f4b53cSBarry Smith  21--6-22--8-23-10-21
247720f4b53cSBarry Smith   |     |     |     |
247820f4b53cSBarry Smith   1     3     5     1
247920f4b53cSBarry Smith   |     |     |     |
248020f4b53cSBarry Smith  18--0-19--2-20--4-18
248120f4b53cSBarry Smith .ve
2482cfb853baSMatthew G. Knepley 
248376fbde31SPierre Jolivet .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
2484cfb853baSMatthew G. Knepley @*/
24858d2ec52aSSatish Balay PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], PetscInt overlap, DM *dm)
2486cfb853baSMatthew G. Knepley {
2487cfb853baSMatthew G. Knepley   PetscInt       *edg;
2488cfb853baSMatthew G. Knepley   PetscReal      *low, *upp;
2489cfb853baSMatthew G. Knepley   DMBoundaryType *bdt;
2490cfb853baSMatthew G. Knepley   PetscInt        d;
2491cfb853baSMatthew G. Knepley 
2492cfb853baSMatthew G. Knepley   PetscFunctionBegin;
2493cfb853baSMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
2494cfb853baSMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
2495cfb853baSMatthew G. Knepley   PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt));
2496cfb853baSMatthew G. Knepley   for (d = 0; d < dim; ++d) {
2497cfb853baSMatthew G. Knepley     edg[d] = edges ? edges[d] : 1;
2498cfb853baSMatthew G. Knepley     low[d] = lower ? lower[d] : 0.;
2499cfb853baSMatthew G. Knepley     upp[d] = upper ? upper[d] : 1.;
2500cfb853baSMatthew G. Knepley     bdt[d] = DM_BOUNDARY_PERIODIC;
2501cfb853baSMatthew G. Knepley   }
25028d2ec52aSSatish Balay   PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, overlap, bdt));
2503cfb853baSMatthew G. Knepley   PetscCall(PetscFree4(edg, low, upp, bdt));
25043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2505cfb853baSMatthew G. Knepley }
2506cfb853baSMatthew G. Knepley 
2507cc4c1da9SBarry Smith /*@
2508a1cb98faSBarry Smith   DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database.
2509a9074c1eSMatthew G. Knepley 
251020f4b53cSBarry Smith   Logically Collective
2511a9074c1eSMatthew G. Knepley 
2512a9074c1eSMatthew G. Knepley   Input Parameters:
251320f4b53cSBarry Smith + dm     - the `DM` context
2514a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names
2515a9074c1eSMatthew G. Knepley 
2516a1cb98faSBarry Smith   Level: advanced
2517a1cb98faSBarry Smith 
2518a1cb98faSBarry Smith   Note:
2519a9074c1eSMatthew G. Knepley   A hyphen (-) must NOT be given at the beginning of the prefix name.
2520a9074c1eSMatthew G. Knepley   The first character of all runtime options is AUTOMATICALLY the hyphen.
2521a9074c1eSMatthew G. Knepley 
25221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()`
2523a9074c1eSMatthew G. Knepley @*/
2524d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[])
2525d71ae5a4SJacob Faibussowitsch {
2526a9074c1eSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
2527a9074c1eSMatthew G. Knepley 
2528a9074c1eSMatthew G. Knepley   PetscFunctionBegin;
2529a9074c1eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
25309566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
25319566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix));
25323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2533a9074c1eSMatthew G. Knepley }
2534a9074c1eSMatthew G. Knepley 
25359318fe57SMatthew G. Knepley /* Remap geometry to cylinder
253661a622f3SMatthew G. Knepley    TODO: This only works for a single refinement, then it is broken
253761a622f3SMatthew G. Knepley 
25389318fe57SMatthew G. Knepley      Interior square: Linear interpolation is correct
25399318fe57SMatthew G. Knepley      The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing
25409318fe57SMatthew G. Knepley      such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance
25410510c589SMatthew G. Knepley 
25429318fe57SMatthew G. Knepley        phi     = arctan(y/x)
25439318fe57SMatthew G. Knepley        d_close = sqrt(1/8 + 1/4 sin^2(phi))
25449318fe57SMatthew G. Knepley        d_far   = sqrt(1/2 + sin^2(phi))
25450510c589SMatthew G. Knepley 
25469318fe57SMatthew G. Knepley      so we remap them using
25470510c589SMatthew G. Knepley 
25489318fe57SMatthew G. Knepley        x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close)
25499318fe57SMatthew G. Knepley        y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close)
25500510c589SMatthew G. Knepley 
25519318fe57SMatthew G. Knepley      If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y.
25529318fe57SMatthew G. Knepley */
2553d71ae5a4SJacob 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[])
2554d71ae5a4SJacob Faibussowitsch {
25559318fe57SMatthew G. Knepley   const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
25569318fe57SMatthew G. Knepley   const PetscReal ds2 = 0.5 * dis;
255722cc497dSMatthew G. Knepley 
25589318fe57SMatthew G. Knepley   if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) {
25599318fe57SMatthew G. Knepley     f0[0] = u[0];
25609318fe57SMatthew G. Knepley     f0[1] = u[1];
25619318fe57SMatthew G. Knepley   } else {
25629318fe57SMatthew G. Knepley     PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc;
25630510c589SMatthew G. Knepley 
25649318fe57SMatthew G. Knepley     x    = PetscRealPart(u[0]);
25659318fe57SMatthew G. Knepley     y    = PetscRealPart(u[1]);
25669318fe57SMatthew G. Knepley     phi  = PetscAtan2Real(y, x);
25679318fe57SMatthew G. Knepley     sinp = PetscSinReal(phi);
25689318fe57SMatthew G. Knepley     cosp = PetscCosReal(phi);
25699318fe57SMatthew G. Knepley     if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) {
25709318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / sinp);
25719318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / sinp);
25729318fe57SMatthew G. Knepley       xc = ds2 * x / PetscAbsReal(y);
25739318fe57SMatthew G. Knepley       yc = ds2 * PetscSignReal(y);
25749318fe57SMatthew G. Knepley     } else {
25759318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / cosp);
25769318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / cosp);
25779318fe57SMatthew G. Knepley       xc = ds2 * PetscSignReal(x);
25789318fe57SMatthew G. Knepley       yc = ds2 * y / PetscAbsReal(x);
25799318fe57SMatthew G. Knepley     }
25809318fe57SMatthew G. Knepley     f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc);
25819318fe57SMatthew G. Knepley     f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc);
25829318fe57SMatthew G. Knepley   }
25839318fe57SMatthew G. Knepley   f0[2] = u[2];
25849318fe57SMatthew G. Knepley }
25850510c589SMatthew G. Knepley 
258649704ca5SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ, PetscInt Nr)
2587d71ae5a4SJacob Faibussowitsch {
25880510c589SMatthew G. Knepley   const PetscInt dim = 3;
25899318fe57SMatthew G. Knepley   PetscInt       numCells, numVertices;
2590d8c47e87SMatthew G. Knepley   PetscMPIInt    rank;
25910510c589SMatthew G. Knepley 
25920510c589SMatthew G. Knepley   PetscFunctionBegin;
259346139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
25949566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
25959566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
25960510c589SMatthew G. Knepley   /* Create topology */
25970510c589SMatthew G. Knepley   {
25980510c589SMatthew G. Knepley     PetscInt cone[8], c;
25990510c589SMatthew G. Knepley 
2600dd400576SPatrick Sanan     numCells    = rank == 0 ? 5 : 0;
2601dd400576SPatrick Sanan     numVertices = rank == 0 ? 16 : 0;
2602006a8963SMatthew G. Knepley     if (periodicZ == DM_BOUNDARY_PERIODIC) {
2603ae8bcbbbSMatthew G. Knepley       numCells *= 3;
2604dd400576SPatrick Sanan       numVertices = rank == 0 ? 24 : 0;
2605006a8963SMatthew G. Knepley     }
26069566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
26079566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8));
26089566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
2609dd400576SPatrick Sanan     if (rank == 0) {
2610006a8963SMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
26119371c9d4SSatish Balay         cone[0] = 15;
26129371c9d4SSatish Balay         cone[1] = 18;
26139371c9d4SSatish Balay         cone[2] = 17;
26149371c9d4SSatish Balay         cone[3] = 16;
26159371c9d4SSatish Balay         cone[4] = 31;
26169371c9d4SSatish Balay         cone[5] = 32;
26179371c9d4SSatish Balay         cone[6] = 33;
26189371c9d4SSatish Balay         cone[7] = 34;
26199566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
26209371c9d4SSatish Balay         cone[0] = 16;
26219371c9d4SSatish Balay         cone[1] = 17;
26229371c9d4SSatish Balay         cone[2] = 24;
26239371c9d4SSatish Balay         cone[3] = 23;
26249371c9d4SSatish Balay         cone[4] = 32;
26259371c9d4SSatish Balay         cone[5] = 36;
26269371c9d4SSatish Balay         cone[6] = 37;
26279371c9d4SSatish Balay         cone[7] = 33; /* 22 25 26 21 */
26289566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
26299371c9d4SSatish Balay         cone[0] = 18;
26309371c9d4SSatish Balay         cone[1] = 27;
26319371c9d4SSatish Balay         cone[2] = 24;
26329371c9d4SSatish Balay         cone[3] = 17;
26339371c9d4SSatish Balay         cone[4] = 34;
26349371c9d4SSatish Balay         cone[5] = 33;
26359371c9d4SSatish Balay         cone[6] = 37;
26369371c9d4SSatish Balay         cone[7] = 38;
26379566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
26389371c9d4SSatish Balay         cone[0] = 29;
26399371c9d4SSatish Balay         cone[1] = 27;
26409371c9d4SSatish Balay         cone[2] = 18;
26419371c9d4SSatish Balay         cone[3] = 15;
26429371c9d4SSatish Balay         cone[4] = 35;
26439371c9d4SSatish Balay         cone[5] = 31;
26449371c9d4SSatish Balay         cone[6] = 34;
26459371c9d4SSatish Balay         cone[7] = 38;
26469566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
26479371c9d4SSatish Balay         cone[0] = 29;
26489371c9d4SSatish Balay         cone[1] = 15;
26499371c9d4SSatish Balay         cone[2] = 16;
26509371c9d4SSatish Balay         cone[3] = 23;
26519371c9d4SSatish Balay         cone[4] = 35;
26529371c9d4SSatish Balay         cone[5] = 36;
26539371c9d4SSatish Balay         cone[6] = 32;
26549371c9d4SSatish Balay         cone[7] = 31;
26559566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
2656006a8963SMatthew G. Knepley 
26579371c9d4SSatish Balay         cone[0] = 31;
26589371c9d4SSatish Balay         cone[1] = 34;
26599371c9d4SSatish Balay         cone[2] = 33;
26609371c9d4SSatish Balay         cone[3] = 32;
26619371c9d4SSatish Balay         cone[4] = 19;
26629371c9d4SSatish Balay         cone[5] = 22;
26639371c9d4SSatish Balay         cone[6] = 21;
26649371c9d4SSatish Balay         cone[7] = 20;
26659566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
26669371c9d4SSatish Balay         cone[0] = 32;
26679371c9d4SSatish Balay         cone[1] = 33;
26689371c9d4SSatish Balay         cone[2] = 37;
26699371c9d4SSatish Balay         cone[3] = 36;
26709371c9d4SSatish Balay         cone[4] = 22;
26719371c9d4SSatish Balay         cone[5] = 25;
26729371c9d4SSatish Balay         cone[6] = 26;
26739371c9d4SSatish Balay         cone[7] = 21;
26749566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 6, cone));
26759371c9d4SSatish Balay         cone[0] = 34;
26769371c9d4SSatish Balay         cone[1] = 38;
26779371c9d4SSatish Balay         cone[2] = 37;
26789371c9d4SSatish Balay         cone[3] = 33;
26799371c9d4SSatish Balay         cone[4] = 20;
26809371c9d4SSatish Balay         cone[5] = 21;
26819371c9d4SSatish Balay         cone[6] = 26;
26829371c9d4SSatish Balay         cone[7] = 28;
26839566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 7, cone));
26849371c9d4SSatish Balay         cone[0] = 35;
26859371c9d4SSatish Balay         cone[1] = 38;
26869371c9d4SSatish Balay         cone[2] = 34;
26879371c9d4SSatish Balay         cone[3] = 31;
26889371c9d4SSatish Balay         cone[4] = 30;
26899371c9d4SSatish Balay         cone[5] = 19;
26909371c9d4SSatish Balay         cone[6] = 20;
26919371c9d4SSatish Balay         cone[7] = 28;
26929566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 8, cone));
26939371c9d4SSatish Balay         cone[0] = 35;
26949371c9d4SSatish Balay         cone[1] = 31;
26959371c9d4SSatish Balay         cone[2] = 32;
26969371c9d4SSatish Balay         cone[3] = 36;
26979371c9d4SSatish Balay         cone[4] = 30;
26989371c9d4SSatish Balay         cone[5] = 25;
26999371c9d4SSatish Balay         cone[6] = 22;
27009371c9d4SSatish Balay         cone[7] = 19;
27019566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 9, cone));
2702ae8bcbbbSMatthew G. Knepley 
27039371c9d4SSatish Balay         cone[0] = 19;
27049371c9d4SSatish Balay         cone[1] = 20;
27059371c9d4SSatish Balay         cone[2] = 21;
27069371c9d4SSatish Balay         cone[3] = 22;
27079371c9d4SSatish Balay         cone[4] = 15;
27089371c9d4SSatish Balay         cone[5] = 16;
27099371c9d4SSatish Balay         cone[6] = 17;
27109371c9d4SSatish Balay         cone[7] = 18;
27119566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 10, cone));
27129371c9d4SSatish Balay         cone[0] = 22;
27139371c9d4SSatish Balay         cone[1] = 21;
27149371c9d4SSatish Balay         cone[2] = 26;
27159371c9d4SSatish Balay         cone[3] = 25;
27169371c9d4SSatish Balay         cone[4] = 16;
27179371c9d4SSatish Balay         cone[5] = 23;
27189371c9d4SSatish Balay         cone[6] = 24;
27199371c9d4SSatish Balay         cone[7] = 17;
27209566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 11, cone));
27219371c9d4SSatish Balay         cone[0] = 20;
27229371c9d4SSatish Balay         cone[1] = 28;
27239371c9d4SSatish Balay         cone[2] = 26;
27249371c9d4SSatish Balay         cone[3] = 21;
27259371c9d4SSatish Balay         cone[4] = 18;
27269371c9d4SSatish Balay         cone[5] = 17;
27279371c9d4SSatish Balay         cone[6] = 24;
27289371c9d4SSatish Balay         cone[7] = 27;
27299566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 12, cone));
27309371c9d4SSatish Balay         cone[0] = 30;
27319371c9d4SSatish Balay         cone[1] = 28;
27329371c9d4SSatish Balay         cone[2] = 20;
27339371c9d4SSatish Balay         cone[3] = 19;
27349371c9d4SSatish Balay         cone[4] = 29;
27359371c9d4SSatish Balay         cone[5] = 15;
27369371c9d4SSatish Balay         cone[6] = 18;
27379371c9d4SSatish Balay         cone[7] = 27;
27389566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 13, cone));
27399371c9d4SSatish Balay         cone[0] = 30;
27409371c9d4SSatish Balay         cone[1] = 19;
27419371c9d4SSatish Balay         cone[2] = 22;
27429371c9d4SSatish Balay         cone[3] = 25;
27439371c9d4SSatish Balay         cone[4] = 29;
27449371c9d4SSatish Balay         cone[5] = 23;
27459371c9d4SSatish Balay         cone[6] = 16;
27469371c9d4SSatish Balay         cone[7] = 15;
27479566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
2748006a8963SMatthew G. Knepley       } else {
27499371c9d4SSatish Balay         cone[0] = 5;
27509371c9d4SSatish Balay         cone[1] = 8;
27519371c9d4SSatish Balay         cone[2] = 7;
27529371c9d4SSatish Balay         cone[3] = 6;
27539371c9d4SSatish Balay         cone[4] = 9;
27549371c9d4SSatish Balay         cone[5] = 12;
27559371c9d4SSatish Balay         cone[6] = 11;
27569371c9d4SSatish Balay         cone[7] = 10;
27579566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
27589371c9d4SSatish Balay         cone[0] = 6;
27599371c9d4SSatish Balay         cone[1] = 7;
27609371c9d4SSatish Balay         cone[2] = 14;
27619371c9d4SSatish Balay         cone[3] = 13;
27629371c9d4SSatish Balay         cone[4] = 12;
27639371c9d4SSatish Balay         cone[5] = 15;
27649371c9d4SSatish Balay         cone[6] = 16;
27659371c9d4SSatish Balay         cone[7] = 11;
27669566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
27679371c9d4SSatish Balay         cone[0] = 8;
27689371c9d4SSatish Balay         cone[1] = 17;
27699371c9d4SSatish Balay         cone[2] = 14;
27709371c9d4SSatish Balay         cone[3] = 7;
27719371c9d4SSatish Balay         cone[4] = 10;
27729371c9d4SSatish Balay         cone[5] = 11;
27739371c9d4SSatish Balay         cone[6] = 16;
27749371c9d4SSatish Balay         cone[7] = 18;
27759566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
27769371c9d4SSatish Balay         cone[0] = 19;
27779371c9d4SSatish Balay         cone[1] = 17;
27789371c9d4SSatish Balay         cone[2] = 8;
27799371c9d4SSatish Balay         cone[3] = 5;
27809371c9d4SSatish Balay         cone[4] = 20;
27819371c9d4SSatish Balay         cone[5] = 9;
27829371c9d4SSatish Balay         cone[6] = 10;
27839371c9d4SSatish Balay         cone[7] = 18;
27849566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
27859371c9d4SSatish Balay         cone[0] = 19;
27869371c9d4SSatish Balay         cone[1] = 5;
27879371c9d4SSatish Balay         cone[2] = 6;
27889371c9d4SSatish Balay         cone[3] = 13;
27899371c9d4SSatish Balay         cone[4] = 20;
27909371c9d4SSatish Balay         cone[5] = 15;
27919371c9d4SSatish Balay         cone[6] = 12;
27929371c9d4SSatish Balay         cone[7] = 9;
27939566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
2794006a8963SMatthew G. Knepley       }
2795d8c47e87SMatthew G. Knepley     }
27969566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
27979566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
27980510c589SMatthew G. Knepley   }
2799dbc1dc17SMatthew G. Knepley   /* Create cube geometry */
28000510c589SMatthew G. Knepley   {
28010510c589SMatthew G. Knepley     Vec             coordinates;
28020510c589SMatthew G. Knepley     PetscSection    coordSection;
28030510c589SMatthew G. Knepley     PetscScalar    *coords;
28040510c589SMatthew G. Knepley     PetscInt        coordSize, v;
28050510c589SMatthew G. Knepley     const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
28060510c589SMatthew G. Knepley     const PetscReal ds2 = dis / 2.0;
28070510c589SMatthew G. Knepley 
28080510c589SMatthew G. Knepley     /* Build coordinates */
28099566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
28109566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
28119566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
28129566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
28130510c589SMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
28149566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
28159566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
28160510c589SMatthew G. Knepley     }
28179566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
28189566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
28199566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
28209566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
28219566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
28229566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
28239566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
28249566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
2825dd400576SPatrick Sanan     if (rank == 0) {
28269371c9d4SSatish Balay       coords[0 * dim + 0]  = -ds2;
28279371c9d4SSatish Balay       coords[0 * dim + 1]  = -ds2;
28289371c9d4SSatish Balay       coords[0 * dim + 2]  = 0.0;
28299371c9d4SSatish Balay       coords[1 * dim + 0]  = ds2;
28309371c9d4SSatish Balay       coords[1 * dim + 1]  = -ds2;
28319371c9d4SSatish Balay       coords[1 * dim + 2]  = 0.0;
28329371c9d4SSatish Balay       coords[2 * dim + 0]  = ds2;
28339371c9d4SSatish Balay       coords[2 * dim + 1]  = ds2;
28349371c9d4SSatish Balay       coords[2 * dim + 2]  = 0.0;
28359371c9d4SSatish Balay       coords[3 * dim + 0]  = -ds2;
28369371c9d4SSatish Balay       coords[3 * dim + 1]  = ds2;
28379371c9d4SSatish Balay       coords[3 * dim + 2]  = 0.0;
28389371c9d4SSatish Balay       coords[4 * dim + 0]  = -ds2;
28399371c9d4SSatish Balay       coords[4 * dim + 1]  = -ds2;
28409371c9d4SSatish Balay       coords[4 * dim + 2]  = 1.0;
28419371c9d4SSatish Balay       coords[5 * dim + 0]  = -ds2;
28429371c9d4SSatish Balay       coords[5 * dim + 1]  = ds2;
28439371c9d4SSatish Balay       coords[5 * dim + 2]  = 1.0;
28449371c9d4SSatish Balay       coords[6 * dim + 0]  = ds2;
28459371c9d4SSatish Balay       coords[6 * dim + 1]  = ds2;
28469371c9d4SSatish Balay       coords[6 * dim + 2]  = 1.0;
28479371c9d4SSatish Balay       coords[7 * dim + 0]  = ds2;
28489371c9d4SSatish Balay       coords[7 * dim + 1]  = -ds2;
28499371c9d4SSatish Balay       coords[7 * dim + 2]  = 1.0;
28509371c9d4SSatish Balay       coords[8 * dim + 0]  = dis;
28519371c9d4SSatish Balay       coords[8 * dim + 1]  = -dis;
28529371c9d4SSatish Balay       coords[8 * dim + 2]  = 0.0;
28539371c9d4SSatish Balay       coords[9 * dim + 0]  = dis;
28549371c9d4SSatish Balay       coords[9 * dim + 1]  = dis;
28559371c9d4SSatish Balay       coords[9 * dim + 2]  = 0.0;
28569371c9d4SSatish Balay       coords[10 * dim + 0] = dis;
28579371c9d4SSatish Balay       coords[10 * dim + 1] = -dis;
28589371c9d4SSatish Balay       coords[10 * dim + 2] = 1.0;
28599371c9d4SSatish Balay       coords[11 * dim + 0] = dis;
28609371c9d4SSatish Balay       coords[11 * dim + 1] = dis;
28619371c9d4SSatish Balay       coords[11 * dim + 2] = 1.0;
28629371c9d4SSatish Balay       coords[12 * dim + 0] = -dis;
28639371c9d4SSatish Balay       coords[12 * dim + 1] = dis;
28649371c9d4SSatish Balay       coords[12 * dim + 2] = 0.0;
28659371c9d4SSatish Balay       coords[13 * dim + 0] = -dis;
28669371c9d4SSatish Balay       coords[13 * dim + 1] = dis;
28679371c9d4SSatish Balay       coords[13 * dim + 2] = 1.0;
28689371c9d4SSatish Balay       coords[14 * dim + 0] = -dis;
28699371c9d4SSatish Balay       coords[14 * dim + 1] = -dis;
28709371c9d4SSatish Balay       coords[14 * dim + 2] = 0.0;
28719371c9d4SSatish Balay       coords[15 * dim + 0] = -dis;
28729371c9d4SSatish Balay       coords[15 * dim + 1] = -dis;
28739371c9d4SSatish Balay       coords[15 * dim + 2] = 1.0;
2874ae8bcbbbSMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
28759371c9d4SSatish Balay         /* 15 31 19 */ coords[16 * dim + 0] = -ds2;
28769371c9d4SSatish Balay         coords[16 * dim + 1]                = -ds2;
28779371c9d4SSatish Balay         coords[16 * dim + 2]                = 0.5;
28789371c9d4SSatish Balay         /* 16 32 22 */ coords[17 * dim + 0] = ds2;
28799371c9d4SSatish Balay         coords[17 * dim + 1]                = -ds2;
28809371c9d4SSatish Balay         coords[17 * dim + 2]                = 0.5;
28819371c9d4SSatish Balay         /* 17 33 21 */ coords[18 * dim + 0] = ds2;
28829371c9d4SSatish Balay         coords[18 * dim + 1]                = ds2;
28839371c9d4SSatish Balay         coords[18 * dim + 2]                = 0.5;
28849371c9d4SSatish Balay         /* 18 34 20 */ coords[19 * dim + 0] = -ds2;
28859371c9d4SSatish Balay         coords[19 * dim + 1]                = ds2;
28869371c9d4SSatish Balay         coords[19 * dim + 2]                = 0.5;
28879371c9d4SSatish Balay         /* 29 35 30 */ coords[20 * dim + 0] = -dis;
28889371c9d4SSatish Balay         coords[20 * dim + 1]                = -dis;
28899371c9d4SSatish Balay         coords[20 * dim + 2]                = 0.5;
28909371c9d4SSatish Balay         /* 23 36 25 */ coords[21 * dim + 0] = dis;
28919371c9d4SSatish Balay         coords[21 * dim + 1]                = -dis;
28929371c9d4SSatish Balay         coords[21 * dim + 2]                = 0.5;
28939371c9d4SSatish Balay         /* 24 37 26 */ coords[22 * dim + 0] = dis;
28949371c9d4SSatish Balay         coords[22 * dim + 1]                = dis;
28959371c9d4SSatish Balay         coords[22 * dim + 2]                = 0.5;
28969371c9d4SSatish Balay         /* 27 38 28 */ coords[23 * dim + 0] = -dis;
28979371c9d4SSatish Balay         coords[23 * dim + 1]                = dis;
28989371c9d4SSatish Balay         coords[23 * dim + 2]                = 0.5;
2899ae8bcbbbSMatthew G. Knepley       }
2900d8c47e87SMatthew G. Knepley     }
29019566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
29029566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
29039566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
29040510c589SMatthew G. Knepley   }
2905006a8963SMatthew G. Knepley   /* Create periodicity */
2906006a8963SMatthew G. Knepley   if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) {
29076858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
29086858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
2909006a8963SMatthew G. Knepley     PetscReal lower[3]   = {0.0, 0.0, 0.0};
2910ae8bcbbbSMatthew G. Knepley     PetscReal upper[3]   = {1.0, 1.0, 1.5};
29116858538eSMatthew G. Knepley     PetscInt  numZCells  = 3;
2912006a8963SMatthew G. Knepley 
29136858538eSMatthew G. Knepley     L[2]       = upper[2] - lower[2];
29146858538eSMatthew G. Knepley     maxCell[2] = 1.1 * (L[2] / numZCells);
29154fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
2916006a8963SMatthew G. Knepley   }
2917dbc1dc17SMatthew G. Knepley   {
29189318fe57SMatthew G. Knepley     DM          cdm;
29199318fe57SMatthew G. Knepley     PetscDS     cds;
29209318fe57SMatthew G. Knepley     PetscScalar c[2] = {1.0, 1.0};
2921dbc1dc17SMatthew G. Knepley 
2922e65c294aSksagiyam     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE));
29239566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
29249566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
29259566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 2, c));
2926dbc1dc17SMatthew G. Knepley   }
292746139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
292846139095SJed Brown 
29299318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
29309566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(dm));
293149704ca5SMatthew G. Knepley 
293249704ca5SMatthew G. Knepley   char        oldprefix[PETSC_MAX_PATH_LEN];
293349704ca5SMatthew G. Knepley   const char *prefix;
293449704ca5SMatthew G. Knepley 
293549704ca5SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
293649704ca5SMatthew G. Knepley   PetscCall(PetscStrncpy(oldprefix, prefix, PETSC_MAX_PATH_LEN));
293749704ca5SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, "petsc_cyl_ref_"));
293849704ca5SMatthew G. Knepley   for (PetscInt r = 0; r < PetscMax(0, Nr); ++r) {
293949704ca5SMatthew G. Knepley     DM rdm;
294049704ca5SMatthew G. Knepley 
294149704ca5SMatthew G. Knepley     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
294249704ca5SMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &rdm));
294349704ca5SMatthew G. Knepley   }
294449704ca5SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldprefix));
294549704ca5SMatthew G. Knepley   PetscCall(DMPlexRemapGeometry(dm, 0.0, snapToCylinder));
294649704ca5SMatthew G. Knepley 
294749704ca5SMatthew G. Knepley   DMLabel         bdlabel, edgelabel;
294849704ca5SMatthew G. Knepley   IS              faceIS;
294949704ca5SMatthew G. Knepley   const PetscInt *faces;
295049704ca5SMatthew G. Knepley   PetscInt        Nf;
295149704ca5SMatthew G. Knepley 
295249704ca5SMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "marker"));
295349704ca5SMatthew G. Knepley   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
295449704ca5SMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "generatrix"));
295549704ca5SMatthew G. Knepley   PetscCall(DMGetLabel(dm, "generatrix", &edgelabel));
295649704ca5SMatthew G. Knepley   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
295749704ca5SMatthew G. Knepley   // Remove faces on top and bottom
295849704ca5SMatthew G. Knepley   PetscCall(DMLabelGetStratumIS(bdlabel, 1, &faceIS));
2959ba1b3593SJeremy L Thompson   if (faceIS) {
296049704ca5SMatthew G. Knepley     PetscCall(ISGetLocalSize(faceIS, &Nf));
296149704ca5SMatthew G. Knepley     PetscCall(ISGetIndices(faceIS, &faces));
296249704ca5SMatthew G. Knepley     for (PetscInt f = 0; f < Nf; ++f) {
296349704ca5SMatthew G. Knepley       PetscReal vol, normal[3];
296449704ca5SMatthew G. Knepley 
296549704ca5SMatthew G. Knepley       PetscCall(DMPlexComputeCellGeometryFVM(dm, faces[f], &vol, NULL, normal));
296649704ca5SMatthew G. Knepley       if (PetscAbsReal(normal[2]) < PETSC_SMALL) PetscCall(DMLabelSetValue(edgelabel, faces[f], 1));
296749704ca5SMatthew G. Knepley     }
296849704ca5SMatthew G. Knepley     PetscCall(ISRestoreIndices(faceIS, &faces));
296949704ca5SMatthew G. Knepley     PetscCall(ISDestroy(&faceIS));
2970ba1b3593SJeremy L Thompson   }
297149704ca5SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(dm, bdlabel));
297249704ca5SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(dm, edgelabel));
29733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29740510c589SMatthew G. Knepley }
29750510c589SMatthew G. Knepley 
297624119c2aSMatthew G. Knepley /*@
29779318fe57SMatthew G. Knepley   DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra.
297824119c2aSMatthew G. Knepley 
2979d083f849SBarry Smith   Collective
298024119c2aSMatthew G. Knepley 
298124119c2aSMatthew G. Knepley   Input Parameters:
2982a1cb98faSBarry Smith + comm      - The communicator for the `DM` object
298349704ca5SMatthew G. Knepley . periodicZ - The boundary type for the Z direction
298449704ca5SMatthew G. Knepley - Nr        - The number of refinements to carry out
298524119c2aSMatthew G. Knepley 
298624119c2aSMatthew G. Knepley   Output Parameter:
298720f4b53cSBarry Smith . dm - The `DM` object
298824119c2aSMatthew G. Knepley 
298924119c2aSMatthew G. Knepley   Level: beginner
299024119c2aSMatthew G. Knepley 
2991a1cb98faSBarry Smith   Note:
2992a4e35b19SJacob Faibussowitsch   Here is the output numbering looking from the bottom of the cylinder\:
2993a1cb98faSBarry Smith .vb
2994a1cb98faSBarry Smith        17-----14
2995a1cb98faSBarry Smith         |     |
2996a1cb98faSBarry Smith         |  2  |
2997a1cb98faSBarry Smith         |     |
2998a1cb98faSBarry Smith  17-----8-----7-----14
2999a1cb98faSBarry Smith   |     |     |     |
3000a1cb98faSBarry Smith   |  3  |  0  |  1  |
3001a1cb98faSBarry Smith   |     |     |     |
3002a1cb98faSBarry Smith  19-----5-----6-----13
3003a1cb98faSBarry Smith         |     |
3004a1cb98faSBarry Smith         |  4  |
3005a1cb98faSBarry Smith         |     |
3006a1cb98faSBarry Smith        19-----13
3007a1cb98faSBarry Smith 
3008a1cb98faSBarry Smith  and up through the top
3009a1cb98faSBarry Smith 
3010a1cb98faSBarry Smith        18-----16
3011a1cb98faSBarry Smith         |     |
3012a1cb98faSBarry Smith         |  2  |
3013a1cb98faSBarry Smith         |     |
3014a1cb98faSBarry Smith  18----10----11-----16
3015a1cb98faSBarry Smith   |     |     |     |
3016a1cb98faSBarry Smith   |  3  |  0  |  1  |
3017a1cb98faSBarry Smith   |     |     |     |
3018a1cb98faSBarry Smith  20-----9----12-----15
3019a1cb98faSBarry Smith         |     |
3020a1cb98faSBarry Smith         |  4  |
3021a1cb98faSBarry Smith         |     |
3022a1cb98faSBarry Smith        20-----15
3023a1cb98faSBarry Smith .ve
3024a1cb98faSBarry Smith 
30251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
302624119c2aSMatthew G. Knepley @*/
302749704ca5SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, PetscInt Nr, DM *dm)
3028d71ae5a4SJacob Faibussowitsch {
30299318fe57SMatthew G. Knepley   PetscFunctionBegin;
303049704ca5SMatthew G. Knepley   PetscAssertPointer(dm, 4);
30319566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
30329566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
303349704ca5SMatthew G. Knepley   PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ, Nr));
30343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30359318fe57SMatthew G. Knepley }
30369318fe57SMatthew G. Knepley 
3037d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate)
3038d71ae5a4SJacob Faibussowitsch {
303924119c2aSMatthew G. Knepley   const PetscInt dim = 3;
3040412e9a14SMatthew G. Knepley   PetscInt       numCells, numVertices, v;
30419fe9f049SMatthew G. Knepley   PetscMPIInt    rank;
304224119c2aSMatthew G. Knepley 
304324119c2aSMatthew G. Knepley   PetscFunctionBegin;
304463a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n);
304546139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
30469566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
30479566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
3048412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
30499566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
305024119c2aSMatthew G. Knepley   /* Create topology */
305124119c2aSMatthew G. Knepley   {
305224119c2aSMatthew G. Knepley     PetscInt cone[6], c;
305324119c2aSMatthew G. Knepley 
3054dd400576SPatrick Sanan     numCells    = rank == 0 ? n : 0;
3055dd400576SPatrick Sanan     numVertices = rank == 0 ? 2 * (n + 1) : 0;
30569566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
30579566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
30589566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
305924119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
30609371c9d4SSatish Balay       cone[0] = c + n * 1;
30619371c9d4SSatish Balay       cone[1] = (c + 1) % n + n * 1;
30629371c9d4SSatish Balay       cone[2] = 0 + 3 * n;
30639371c9d4SSatish Balay       cone[3] = c + n * 2;
30649371c9d4SSatish Balay       cone[4] = (c + 1) % n + n * 2;
30659371c9d4SSatish Balay       cone[5] = 1 + 3 * n;
30669566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(dm, c, cone));
30679566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR));
306824119c2aSMatthew G. Knepley     }
30699566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
30709566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
307124119c2aSMatthew G. Knepley   }
307248a46eb9SPierre Jolivet   for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT));
307324119c2aSMatthew G. Knepley   /* Create cylinder geometry */
307424119c2aSMatthew G. Knepley   {
307524119c2aSMatthew G. Knepley     Vec          coordinates;
307624119c2aSMatthew G. Knepley     PetscSection coordSection;
307724119c2aSMatthew G. Knepley     PetscScalar *coords;
3078412e9a14SMatthew G. Knepley     PetscInt     coordSize, c;
307924119c2aSMatthew G. Knepley 
308024119c2aSMatthew G. Knepley     /* Build coordinates */
30819566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
30829566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
30839566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
30849566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
308524119c2aSMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
30869566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
30879566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
308824119c2aSMatthew G. Knepley     }
30899566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
30909566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
30919566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
30929566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
30939566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
30949566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
30959566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
30969566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
309724119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
30989371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
30999371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
31009371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 2] = 1.0;
31019371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
31029371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
31039371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 2] = 0.0;
310424119c2aSMatthew G. Knepley     }
3105dd400576SPatrick Sanan     if (rank == 0) {
31069371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 0] = 0.0;
31079371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 1] = 0.0;
31089371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 2] = 1.0;
31099371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 0] = 0.0;
31109371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 1] = 0.0;
31119371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 2] = 0.0;
31129fe9f049SMatthew G. Knepley     }
31139566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
31149566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
31159566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
311624119c2aSMatthew G. Knepley   }
311746139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
31189318fe57SMatthew G. Knepley   /* Interpolate */
31199566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
31203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
31219318fe57SMatthew G. Knepley }
31229318fe57SMatthew G. Knepley 
31239318fe57SMatthew G. Knepley /*@
31249318fe57SMatthew G. Knepley   DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges.
31259318fe57SMatthew G. Knepley 
31269318fe57SMatthew G. Knepley   Collective
31279318fe57SMatthew G. Knepley 
31289318fe57SMatthew G. Knepley   Input Parameters:
3129a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
31309318fe57SMatthew G. Knepley . n           - The number of wedges around the origin
31319318fe57SMatthew G. Knepley - interpolate - Create edges and faces
31329318fe57SMatthew G. Knepley 
31339318fe57SMatthew G. Knepley   Output Parameter:
3134a1cb98faSBarry Smith . dm - The `DM` object
31359318fe57SMatthew G. Knepley 
31369318fe57SMatthew G. Knepley   Level: beginner
31379318fe57SMatthew G. Knepley 
31381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
31399318fe57SMatthew G. Knepley @*/
3140d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm)
3141d71ae5a4SJacob Faibussowitsch {
31429318fe57SMatthew G. Knepley   PetscFunctionBegin;
31434f572ea9SToby Isaac   PetscAssertPointer(dm, 4);
31449566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
31459566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
31469566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate));
31473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
314824119c2aSMatthew G. Knepley }
314924119c2aSMatthew G. Knepley 
3150d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
3151d71ae5a4SJacob Faibussowitsch {
315265a81367SMatthew G. Knepley   PetscReal prod = 0.0;
315365a81367SMatthew G. Knepley   PetscInt  i;
315465a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]);
315565a81367SMatthew G. Knepley   return PetscSqrtReal(prod);
315665a81367SMatthew G. Knepley }
3157dd2b43ebSStefano Zampini 
3158d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
3159d71ae5a4SJacob Faibussowitsch {
316065a81367SMatthew G. Knepley   PetscReal prod = 0.0;
316165a81367SMatthew G. Knepley   PetscInt  i;
316265a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += x[i] * y[i];
316365a81367SMatthew G. Knepley   return prod;
316465a81367SMatthew G. Knepley }
316565a81367SMatthew G. Knepley 
316651a74b61SMatthew G. Knepley /* The first constant is the sphere radius */
3167d71ae5a4SJacob 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[])
3168d71ae5a4SJacob Faibussowitsch {
316951a74b61SMatthew G. Knepley   PetscReal r     = PetscRealPart(constants[0]);
317051a74b61SMatthew G. Knepley   PetscReal norm2 = 0.0, fac;
317151a74b61SMatthew G. Knepley   PetscInt  n     = uOff[1] - uOff[0], d;
317251a74b61SMatthew G. Knepley 
317351a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d]));
317451a74b61SMatthew G. Knepley   fac = r / PetscSqrtReal(norm2);
317551a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) f0[d] = u[d] * fac;
317651a74b61SMatthew G. Knepley }
317751a74b61SMatthew G. Knepley 
3178d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R)
3179d71ae5a4SJacob Faibussowitsch {
318065a81367SMatthew G. Knepley   const PetscInt embedDim = dim + 1;
318165a81367SMatthew G. Knepley   PetscSection   coordSection;
318265a81367SMatthew G. Knepley   Vec            coordinates;
318365a81367SMatthew G. Knepley   PetscScalar   *coords;
318465a81367SMatthew G. Knepley   PetscReal     *coordsIn;
318507c565c5SJose E. Roman   PetscInt       numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, e;
318665a81367SMatthew G. Knepley   PetscMPIInt    rank;
318765a81367SMatthew G. Knepley 
318865a81367SMatthew G. Knepley   PetscFunctionBegin;
31899318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, simplex, 3);
319046139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
31919566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
31929566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim + 1));
31939566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
319465a81367SMatthew G. Knepley   switch (dim) {
31955c344501SMatthew G. Knepley   case 1:
31965c344501SMatthew G. Knepley     numCells = 16;
31975c344501SMatthew G. Knepley     numVerts = numCells;
31985c344501SMatthew G. Knepley 
31995c344501SMatthew G. Knepley     // Build Topology
32005c344501SMatthew G. Knepley     PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
32015c344501SMatthew G. Knepley     for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
32025c344501SMatthew G. Knepley     PetscCall(DMSetUp(dm));
32035c344501SMatthew G. Knepley     for (PetscInt c = 0; c < numCells; ++c) {
32045c344501SMatthew G. Knepley       PetscInt cone[2];
32055c344501SMatthew G. Knepley 
32065c344501SMatthew G. Knepley       cone[0] = c + numCells;
32075c344501SMatthew G. Knepley       cone[1] = (c + 1) % numVerts + numCells;
32085c344501SMatthew G. Knepley       PetscCall(DMPlexSetCone(dm, c, cone));
32095c344501SMatthew G. Knepley     }
32105c344501SMatthew G. Knepley     PetscCall(DMPlexSymmetrize(dm));
32115c344501SMatthew G. Knepley     PetscCall(DMPlexStratify(dm));
32125c344501SMatthew G. Knepley     PetscCall(PetscMalloc1(numVerts * embedDim, &coordsIn));
32135c344501SMatthew G. Knepley     for (PetscInt v = 0; v < numVerts; ++v) {
32145c344501SMatthew G. Knepley       const PetscReal rad = 2. * PETSC_PI * v / numVerts;
32155c344501SMatthew G. Knepley 
32165c344501SMatthew G. Knepley       coordsIn[v * embedDim + 0] = PetscCosReal(rad);
32175c344501SMatthew G. Knepley       coordsIn[v * embedDim + 1] = PetscSinReal(rad);
32185c344501SMatthew G. Knepley     }
32195c344501SMatthew G. Knepley     break;
322065a81367SMatthew G. Knepley   case 2:
322165a81367SMatthew G. Knepley     if (simplex) {
322251a74b61SMatthew G. Knepley       const PetscReal radius    = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI);
322351a74b61SMatthew G. Knepley       const PetscReal edgeLen   = 2.0 / (1.0 + PETSC_PHI) * (R / radius);
322465a81367SMatthew G. Knepley       const PetscInt  degree    = 5;
322551a74b61SMatthew G. Knepley       PetscReal       vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)};
322665a81367SMatthew G. Knepley       PetscInt        s[3]      = {1, 1, 1};
322765a81367SMatthew G. Knepley       PetscInt        cone[3];
322807c565c5SJose E. Roman       PetscInt       *graph;
322965a81367SMatthew G. Knepley 
32309371c9d4SSatish Balay       vertex[0] *= R / radius;
32319371c9d4SSatish Balay       vertex[1] *= R / radius;
32329371c9d4SSatish Balay       vertex[2] *= R / radius;
3233dd400576SPatrick Sanan       numCells    = rank == 0 ? 20 : 0;
3234dd400576SPatrick Sanan       numVerts    = rank == 0 ? 12 : 0;
323565a81367SMatthew G. Knepley       firstVertex = numCells;
323651a74b61SMatthew G. Knepley       /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of
323765a81367SMatthew G. Knepley 
323865a81367SMatthew G. Knepley            (0, \pm 1/\phi+1, \pm \phi/\phi+1)
323965a81367SMatthew G. Knepley 
324065a81367SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
324151a74b61SMatthew G. Knepley          length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393.
324265a81367SMatthew G. Knepley       */
324365a81367SMatthew G. Knepley       /* Construct vertices */
32449566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3245dd400576SPatrick Sanan       if (rank == 0) {
324607c565c5SJose E. Roman         for (PetscInt p = 0, i = 0; p < embedDim; ++p) {
324765a81367SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
324865a81367SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
324965a81367SMatthew G. Knepley               for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim];
325065a81367SMatthew G. Knepley               ++i;
325165a81367SMatthew G. Knepley             }
325265a81367SMatthew G. Knepley           }
325365a81367SMatthew G. Knepley         }
325445da822fSValeria Barra       }
325565a81367SMatthew G. Knepley       /* Construct graph */
32569566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
325707c565c5SJose E. Roman       for (PetscInt i = 0; i < numVerts; ++i) {
325807c565c5SJose E. Roman         PetscInt k = 0;
325907c565c5SJose E. Roman         for (PetscInt j = 0; j < numVerts; ++j) {
32609371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
32619371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
32629371c9d4SSatish Balay             ++k;
32639371c9d4SSatish Balay           }
326465a81367SMatthew G. Knepley         }
326563a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
326665a81367SMatthew G. Knepley       }
326765a81367SMatthew G. Knepley       /* Build Topology */
32689566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
326907c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
32709566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
327165a81367SMatthew G. Knepley       /* Cells */
327207c565c5SJose E. Roman       for (PetscInt i = 0, c = 0; i < numVerts; ++i) {
327307c565c5SJose E. Roman         for (PetscInt j = 0; j < i; ++j) {
327407c565c5SJose E. Roman           for (PetscInt k = 0; k < j; ++k) {
327565a81367SMatthew G. Knepley             if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) {
32769371c9d4SSatish Balay               cone[0] = firstVertex + i;
32779371c9d4SSatish Balay               cone[1] = firstVertex + j;
32789371c9d4SSatish Balay               cone[2] = firstVertex + k;
327965a81367SMatthew G. Knepley               /* Check orientation */
328065a81367SMatthew G. Knepley               {
32819371c9d4SSatish Balay                 const PetscInt epsilon[3][3][3] = {
32829371c9d4SSatish Balay                   {{0, 0, 0},  {0, 0, 1},  {0, -1, 0}},
32839371c9d4SSatish Balay                   {{0, 0, -1}, {0, 0, 0},  {1, 0, 0} },
32849371c9d4SSatish Balay                   {{0, 1, 0},  {-1, 0, 0}, {0, 0, 0} }
32859371c9d4SSatish Balay                 };
328665a81367SMatthew G. Knepley                 PetscReal normal[3];
328765a81367SMatthew G. Knepley                 PetscInt  e, f;
328865a81367SMatthew G. Knepley 
328965a81367SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) {
329065a81367SMatthew G. Knepley                   normal[d] = 0.0;
329165a81367SMatthew G. Knepley                   for (e = 0; e < embedDim; ++e) {
3292ad540459SPierre 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]);
329365a81367SMatthew G. Knepley                   }
329465a81367SMatthew G. Knepley                 }
32959371c9d4SSatish Balay                 if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
32969371c9d4SSatish Balay                   PetscInt tmp = cone[1];
32979371c9d4SSatish Balay                   cone[1]      = cone[2];
32989371c9d4SSatish Balay                   cone[2]      = tmp;
329965a81367SMatthew G. Knepley                 }
330065a81367SMatthew G. Knepley               }
33019566063dSJacob Faibussowitsch               PetscCall(DMPlexSetCone(dm, c++, cone));
330265a81367SMatthew G. Knepley             }
330365a81367SMatthew G. Knepley           }
330465a81367SMatthew G. Knepley         }
330565a81367SMatthew G. Knepley       }
33069566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
33079566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
33089566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
330965a81367SMatthew G. Knepley     } else {
33102829fed8SMatthew G. Knepley       /*
33112829fed8SMatthew G. Knepley         12-21--13
33122829fed8SMatthew G. Knepley          |     |
33132829fed8SMatthew G. Knepley         25  4  24
33142829fed8SMatthew G. Knepley          |     |
33152829fed8SMatthew G. Knepley   12-25--9-16--8-24--13
33162829fed8SMatthew G. Knepley    |     |     |     |
33172829fed8SMatthew G. Knepley   23  5 17  0 15  3  22
33182829fed8SMatthew G. Knepley    |     |     |     |
33192829fed8SMatthew G. Knepley   10-20--6-14--7-19--11
33202829fed8SMatthew G. Knepley          |     |
33212829fed8SMatthew G. Knepley         20  1  19
33222829fed8SMatthew G. Knepley          |     |
33232829fed8SMatthew G. Knepley         10-18--11
33242829fed8SMatthew G. Knepley          |     |
33252829fed8SMatthew G. Knepley         23  2  22
33262829fed8SMatthew G. Knepley          |     |
33272829fed8SMatthew G. Knepley         12-21--13
33282829fed8SMatthew G. Knepley        */
33292829fed8SMatthew G. Knepley       PetscInt cone[4], ornt[4];
33302829fed8SMatthew G. Knepley 
3331dd400576SPatrick Sanan       numCells    = rank == 0 ? 6 : 0;
3332dd400576SPatrick Sanan       numEdges    = rank == 0 ? 12 : 0;
3333dd400576SPatrick Sanan       numVerts    = rank == 0 ? 8 : 0;
333465a81367SMatthew G. Knepley       firstVertex = numCells;
333565a81367SMatthew G. Knepley       firstEdge   = numCells + numVerts;
33362829fed8SMatthew G. Knepley       /* Build Topology */
33379566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts));
333807c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4));
333948a46eb9SPierre Jolivet       for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
33409566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3341dd400576SPatrick Sanan       if (rank == 0) {
33422829fed8SMatthew G. Knepley         /* Cell 0 */
33439371c9d4SSatish Balay         cone[0] = 14;
33449371c9d4SSatish Balay         cone[1] = 15;
33459371c9d4SSatish Balay         cone[2] = 16;
33469371c9d4SSatish Balay         cone[3] = 17;
33479566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
33489371c9d4SSatish Balay         ornt[0] = 0;
33499371c9d4SSatish Balay         ornt[1] = 0;
33509371c9d4SSatish Balay         ornt[2] = 0;
33519371c9d4SSatish Balay         ornt[3] = 0;
33529566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 0, ornt));
33532829fed8SMatthew G. Knepley         /* Cell 1 */
33549371c9d4SSatish Balay         cone[0] = 18;
33559371c9d4SSatish Balay         cone[1] = 19;
33569371c9d4SSatish Balay         cone[2] = 14;
33579371c9d4SSatish Balay         cone[3] = 20;
33589566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
33599371c9d4SSatish Balay         ornt[0] = 0;
33609371c9d4SSatish Balay         ornt[1] = 0;
33619371c9d4SSatish Balay         ornt[2] = -1;
33629371c9d4SSatish Balay         ornt[3] = 0;
33639566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 1, ornt));
33642829fed8SMatthew G. Knepley         /* Cell 2 */
33659371c9d4SSatish Balay         cone[0] = 21;
33669371c9d4SSatish Balay         cone[1] = 22;
33679371c9d4SSatish Balay         cone[2] = 18;
33689371c9d4SSatish Balay         cone[3] = 23;
33699566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
33709371c9d4SSatish Balay         ornt[0] = 0;
33719371c9d4SSatish Balay         ornt[1] = 0;
33729371c9d4SSatish Balay         ornt[2] = -1;
33739371c9d4SSatish Balay         ornt[3] = 0;
33749566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 2, ornt));
33752829fed8SMatthew G. Knepley         /* Cell 3 */
33769371c9d4SSatish Balay         cone[0] = 19;
33779371c9d4SSatish Balay         cone[1] = 22;
33789371c9d4SSatish Balay         cone[2] = 24;
33799371c9d4SSatish Balay         cone[3] = 15;
33809566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
33819371c9d4SSatish Balay         ornt[0] = -1;
33829371c9d4SSatish Balay         ornt[1] = -1;
33839371c9d4SSatish Balay         ornt[2] = 0;
33849371c9d4SSatish Balay         ornt[3] = -1;
33859566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 3, ornt));
33862829fed8SMatthew G. Knepley         /* Cell 4 */
33879371c9d4SSatish Balay         cone[0] = 16;
33889371c9d4SSatish Balay         cone[1] = 24;
33899371c9d4SSatish Balay         cone[2] = 21;
33909371c9d4SSatish Balay         cone[3] = 25;
33919566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
33929371c9d4SSatish Balay         ornt[0] = -1;
33939371c9d4SSatish Balay         ornt[1] = -1;
33949371c9d4SSatish Balay         ornt[2] = -1;
33959371c9d4SSatish Balay         ornt[3] = 0;
33969566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 4, ornt));
33972829fed8SMatthew G. Knepley         /* Cell 5 */
33989371c9d4SSatish Balay         cone[0] = 20;
33999371c9d4SSatish Balay         cone[1] = 17;
34009371c9d4SSatish Balay         cone[2] = 25;
34019371c9d4SSatish Balay         cone[3] = 23;
34029566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
34039371c9d4SSatish Balay         ornt[0] = -1;
34049371c9d4SSatish Balay         ornt[1] = -1;
34059371c9d4SSatish Balay         ornt[2] = -1;
34069371c9d4SSatish Balay         ornt[3] = -1;
34079566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 5, ornt));
34082829fed8SMatthew G. Knepley         /* Edges */
34099371c9d4SSatish Balay         cone[0] = 6;
34109371c9d4SSatish Balay         cone[1] = 7;
34119566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
34129371c9d4SSatish Balay         cone[0] = 7;
34139371c9d4SSatish Balay         cone[1] = 8;
34149566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 15, cone));
34159371c9d4SSatish Balay         cone[0] = 8;
34169371c9d4SSatish Balay         cone[1] = 9;
34179566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 16, cone));
34189371c9d4SSatish Balay         cone[0] = 9;
34199371c9d4SSatish Balay         cone[1] = 6;
34209566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 17, cone));
34219371c9d4SSatish Balay         cone[0] = 10;
34229371c9d4SSatish Balay         cone[1] = 11;
34239566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 18, cone));
34249371c9d4SSatish Balay         cone[0] = 11;
34259371c9d4SSatish Balay         cone[1] = 7;
34269566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 19, cone));
34279371c9d4SSatish Balay         cone[0] = 6;
34289371c9d4SSatish Balay         cone[1] = 10;
34299566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 20, cone));
34309371c9d4SSatish Balay         cone[0] = 12;
34319371c9d4SSatish Balay         cone[1] = 13;
34329566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 21, cone));
34339371c9d4SSatish Balay         cone[0] = 13;
34349371c9d4SSatish Balay         cone[1] = 11;
34359566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 22, cone));
34369371c9d4SSatish Balay         cone[0] = 10;
34379371c9d4SSatish Balay         cone[1] = 12;
34389566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 23, cone));
34399371c9d4SSatish Balay         cone[0] = 13;
34409371c9d4SSatish Balay         cone[1] = 8;
34419566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 24, cone));
34429371c9d4SSatish Balay         cone[0] = 12;
34439371c9d4SSatish Balay         cone[1] = 9;
34449566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 25, cone));
344545da822fSValeria Barra       }
34469566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
34479566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
34482829fed8SMatthew G. Knepley       /* Build coordinates */
34499566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3450dd400576SPatrick Sanan       if (rank == 0) {
34519371c9d4SSatish Balay         coordsIn[0 * embedDim + 0] = -R;
34529371c9d4SSatish Balay         coordsIn[0 * embedDim + 1] = R;
34539371c9d4SSatish Balay         coordsIn[0 * embedDim + 2] = -R;
34549371c9d4SSatish Balay         coordsIn[1 * embedDim + 0] = R;
34559371c9d4SSatish Balay         coordsIn[1 * embedDim + 1] = R;
34569371c9d4SSatish Balay         coordsIn[1 * embedDim + 2] = -R;
34579371c9d4SSatish Balay         coordsIn[2 * embedDim + 0] = R;
34589371c9d4SSatish Balay         coordsIn[2 * embedDim + 1] = -R;
34599371c9d4SSatish Balay         coordsIn[2 * embedDim + 2] = -R;
34609371c9d4SSatish Balay         coordsIn[3 * embedDim + 0] = -R;
34619371c9d4SSatish Balay         coordsIn[3 * embedDim + 1] = -R;
34629371c9d4SSatish Balay         coordsIn[3 * embedDim + 2] = -R;
34639371c9d4SSatish Balay         coordsIn[4 * embedDim + 0] = -R;
34649371c9d4SSatish Balay         coordsIn[4 * embedDim + 1] = R;
34659371c9d4SSatish Balay         coordsIn[4 * embedDim + 2] = R;
34669371c9d4SSatish Balay         coordsIn[5 * embedDim + 0] = R;
34679371c9d4SSatish Balay         coordsIn[5 * embedDim + 1] = R;
34689371c9d4SSatish Balay         coordsIn[5 * embedDim + 2] = R;
34699371c9d4SSatish Balay         coordsIn[6 * embedDim + 0] = -R;
34709371c9d4SSatish Balay         coordsIn[6 * embedDim + 1] = -R;
34719371c9d4SSatish Balay         coordsIn[6 * embedDim + 2] = R;
34729371c9d4SSatish Balay         coordsIn[7 * embedDim + 0] = R;
34739371c9d4SSatish Balay         coordsIn[7 * embedDim + 1] = -R;
34749371c9d4SSatish Balay         coordsIn[7 * embedDim + 2] = R;
347565a81367SMatthew G. Knepley       }
347645da822fSValeria Barra     }
347765a81367SMatthew G. Knepley     break;
347865a81367SMatthew G. Knepley   case 3:
3479116ded15SMatthew G. Knepley     if (simplex) {
3480116ded15SMatthew G. Knepley       const PetscReal edgeLen         = 1.0 / PETSC_PHI;
348151a74b61SMatthew G. Knepley       PetscReal       vertexA[4]      = {0.5, 0.5, 0.5, 0.5};
348251a74b61SMatthew G. Knepley       PetscReal       vertexB[4]      = {1.0, 0.0, 0.0, 0.0};
348351a74b61SMatthew G. Knepley       PetscReal       vertexC[4]      = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0};
3484116ded15SMatthew G. Knepley       const PetscInt  degree          = 12;
3485116ded15SMatthew G. Knepley       PetscInt        s[4]            = {1, 1, 1};
34869371c9d4SSatish Balay       PetscInt        evenPerm[12][4] = {
34879371c9d4SSatish Balay         {0, 1, 2, 3},
34889371c9d4SSatish Balay         {0, 2, 3, 1},
34899371c9d4SSatish Balay         {0, 3, 1, 2},
34909371c9d4SSatish Balay         {1, 0, 3, 2},
34919371c9d4SSatish Balay         {1, 2, 0, 3},
34929371c9d4SSatish Balay         {1, 3, 2, 0},
34939371c9d4SSatish Balay         {2, 0, 1, 3},
34949371c9d4SSatish Balay         {2, 1, 3, 0},
34959371c9d4SSatish Balay         {2, 3, 0, 1},
34969371c9d4SSatish Balay         {3, 0, 2, 1},
34979371c9d4SSatish Balay         {3, 1, 0, 2},
34989371c9d4SSatish Balay         {3, 2, 1, 0}
34999371c9d4SSatish Balay       };
3500116ded15SMatthew G. Knepley       PetscInt  cone[4];
3501116ded15SMatthew G. Knepley       PetscInt *graph, p, i, j, k, l;
3502116ded15SMatthew G. Knepley 
35039371c9d4SSatish Balay       vertexA[0] *= R;
35049371c9d4SSatish Balay       vertexA[1] *= R;
35059371c9d4SSatish Balay       vertexA[2] *= R;
35069371c9d4SSatish Balay       vertexA[3] *= R;
35079371c9d4SSatish Balay       vertexB[0] *= R;
35089371c9d4SSatish Balay       vertexB[1] *= R;
35099371c9d4SSatish Balay       vertexB[2] *= R;
35109371c9d4SSatish Balay       vertexB[3] *= R;
35119371c9d4SSatish Balay       vertexC[0] *= R;
35129371c9d4SSatish Balay       vertexC[1] *= R;
35139371c9d4SSatish Balay       vertexC[2] *= R;
35149371c9d4SSatish Balay       vertexC[3] *= R;
3515dd400576SPatrick Sanan       numCells    = rank == 0 ? 600 : 0;
3516dd400576SPatrick Sanan       numVerts    = rank == 0 ? 120 : 0;
3517116ded15SMatthew G. Knepley       firstVertex = numCells;
3518116ded15SMatthew G. Knepley       /* Use the 600-cell, which for a unit sphere has coordinates which are
3519116ded15SMatthew G. Knepley 
3520116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm 1,    \pm 1, \pm 1)                          16
3521116ded15SMatthew G. Knepley                (\pm 1,    0,       0,      0)  all cyclic permutations   8
3522116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm phi, \pm 1/phi, 0)  all even permutations    96
3523116ded15SMatthew G. Knepley 
3524116ded15SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
35256333ae4fSvaleriabarra          length is then given by 1/\phi = 0.61803.
3526116ded15SMatthew G. Knepley 
3527116ded15SMatthew G. Knepley          http://buzzard.pugetsound.edu/sage-practice/ch03s03.html
3528116ded15SMatthew G. Knepley          http://mathworld.wolfram.com/600-Cell.html
3529116ded15SMatthew G. Knepley       */
3530116ded15SMatthew G. Knepley       /* Construct vertices */
35319566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3532116ded15SMatthew G. Knepley       i = 0;
3533dd400576SPatrick Sanan       if (rank == 0) {
3534116ded15SMatthew G. Knepley         for (s[0] = -1; s[0] < 2; s[0] += 2) {
3535116ded15SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
3536116ded15SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
3537116ded15SMatthew G. Knepley               for (s[3] = -1; s[3] < 2; s[3] += 2) {
3538116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d];
3539116ded15SMatthew G. Knepley                 ++i;
3540116ded15SMatthew G. Knepley               }
3541116ded15SMatthew G. Knepley             }
3542116ded15SMatthew G. Knepley           }
3543116ded15SMatthew G. Knepley         }
3544116ded15SMatthew G. Knepley         for (p = 0; p < embedDim; ++p) {
3545116ded15SMatthew G. Knepley           s[1] = s[2] = s[3] = 1;
3546116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
3547116ded15SMatthew G. Knepley             for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim];
3548116ded15SMatthew G. Knepley             ++i;
3549116ded15SMatthew G. Knepley           }
3550116ded15SMatthew G. Knepley         }
3551116ded15SMatthew G. Knepley         for (p = 0; p < 12; ++p) {
3552116ded15SMatthew G. Knepley           s[3] = 1;
3553116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
3554116ded15SMatthew G. Knepley             for (s[1] = -1; s[1] < 2; s[1] += 2) {
3555116ded15SMatthew G. Knepley               for (s[2] = -1; s[2] < 2; s[2] += 2) {
3556116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]];
3557116ded15SMatthew G. Knepley                 ++i;
3558116ded15SMatthew G. Knepley               }
3559116ded15SMatthew G. Knepley             }
3560116ded15SMatthew G. Knepley           }
3561116ded15SMatthew G. Knepley         }
356245da822fSValeria Barra       }
356363a3b9bcSJacob Faibussowitsch       PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts);
3564116ded15SMatthew G. Knepley       /* Construct graph */
35659566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
3566116ded15SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
3567116ded15SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
35689371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
35699371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
35709371c9d4SSatish Balay             ++k;
35719371c9d4SSatish Balay           }
3572116ded15SMatthew G. Knepley         }
357363a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
3574116ded15SMatthew G. Knepley       }
3575116ded15SMatthew G. Knepley       /* Build Topology */
35769566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
357707c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
35789566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3579116ded15SMatthew G. Knepley       /* Cells */
3580dd400576SPatrick Sanan       if (rank == 0) {
358107c565c5SJose E. Roman         for (PetscInt i = 0, c = 0; i < numVerts; ++i) {
3582116ded15SMatthew G. Knepley           for (j = 0; j < i; ++j) {
3583116ded15SMatthew G. Knepley             for (k = 0; k < j; ++k) {
3584116ded15SMatthew G. Knepley               for (l = 0; l < k; ++l) {
35859371c9d4SSatish 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]) {
35869371c9d4SSatish Balay                   cone[0] = firstVertex + i;
35879371c9d4SSatish Balay                   cone[1] = firstVertex + j;
35889371c9d4SSatish Balay                   cone[2] = firstVertex + k;
35899371c9d4SSatish Balay                   cone[3] = firstVertex + l;
3590116ded15SMatthew G. Knepley                   /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */
3591116ded15SMatthew G. Knepley                   {
35929371c9d4SSatish Balay                     const PetscInt epsilon[4][4][4][4] = {
35939371c9d4SSatish 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}}},
3594116ded15SMatthew G. Knepley 
35959371c9d4SSatish 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}}},
3596116ded15SMatthew G. Knepley 
35979371c9d4SSatish 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}}},
3598116ded15SMatthew G. Knepley 
35999371c9d4SSatish 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}} }
36009371c9d4SSatish Balay                     };
3601116ded15SMatthew G. Knepley                     PetscReal normal[4];
3602116ded15SMatthew G. Knepley                     PetscInt  e, f, g;
3603116ded15SMatthew G. Knepley 
3604116ded15SMatthew G. Knepley                     for (d = 0; d < embedDim; ++d) {
3605116ded15SMatthew G. Knepley                       normal[d] = 0.0;
3606116ded15SMatthew G. Knepley                       for (e = 0; e < embedDim; ++e) {
3607116ded15SMatthew G. Knepley                         for (f = 0; f < embedDim; ++f) {
3608116ded15SMatthew G. Knepley                           for (g = 0; g < embedDim; ++g) {
3609116ded15SMatthew 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]);
3610116ded15SMatthew G. Knepley                           }
3611116ded15SMatthew G. Knepley                         }
3612116ded15SMatthew G. Knepley                       }
3613116ded15SMatthew G. Knepley                     }
36149371c9d4SSatish Balay                     if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
36159371c9d4SSatish Balay                       PetscInt tmp = cone[1];
36169371c9d4SSatish Balay                       cone[1]      = cone[2];
36179371c9d4SSatish Balay                       cone[2]      = tmp;
36189371c9d4SSatish Balay                     }
3619116ded15SMatthew G. Knepley                   }
36209566063dSJacob Faibussowitsch                   PetscCall(DMPlexSetCone(dm, c++, cone));
3621116ded15SMatthew G. Knepley                 }
3622116ded15SMatthew G. Knepley               }
3623116ded15SMatthew G. Knepley             }
3624116ded15SMatthew G. Knepley           }
3625116ded15SMatthew G. Knepley         }
362645da822fSValeria Barra       }
36279566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
36289566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
36299566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
3630116ded15SMatthew G. Knepley     }
3631f4d061e9SPierre Jolivet     break;
3632d71ae5a4SJacob Faibussowitsch   default:
3633d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim);
363465a81367SMatthew G. Knepley   }
363565a81367SMatthew G. Knepley   /* Create coordinates */
36369566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
36379566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
36389566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim));
36399566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts));
36402829fed8SMatthew G. Knepley   for (v = firstVertex; v < firstVertex + numVerts; ++v) {
36419566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, embedDim));
36429566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim));
36432829fed8SMatthew G. Knepley   }
36449566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
36459566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
36469566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
36479566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, embedDim));
36489566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
36499566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
36509566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
36519566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
36529371c9d4SSatish Balay   for (v = 0; v < numVerts; ++v)
3653ad540459SPierre Jolivet     for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d];
36549566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
36559566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
36569566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
36579566063dSJacob Faibussowitsch   PetscCall(PetscFree(coordsIn));
365851a74b61SMatthew G. Knepley   {
365951a74b61SMatthew G. Knepley     DM          cdm;
366051a74b61SMatthew G. Knepley     PetscDS     cds;
36619318fe57SMatthew G. Knepley     PetscScalar c = R;
366251a74b61SMatthew G. Knepley 
3663509b31aaSMatthew G. Knepley     PetscCall(DMPlexSetCoordinateMap(dm, snapToSphere));
3664e65c294aSksagiyam     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE));
36659566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
36669566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
36679566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 1, &c));
366851a74b61SMatthew G. Knepley   }
366946139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
36709318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
36719566063dSJacob Faibussowitsch   if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
36723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36739318fe57SMatthew G. Knepley }
36749318fe57SMatthew G. Knepley 
3675b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]);
3676b7f5c055SJed Brown 
3677b7f5c055SJed Brown /*
3678b7f5c055SJed Brown  The Schwarz P implicit surface is
3679b7f5c055SJed Brown 
3680b7f5c055SJed Brown      f(x) = cos(x0) + cos(x1) + cos(x2) = 0
3681b7f5c055SJed Brown */
3682d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
3683d71ae5a4SJacob Faibussowitsch {
3684b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)};
3685b7f5c055SJed Brown   PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)};
3686b7f5c055SJed Brown   f[0]           = c[0] + c[1] + c[2];
3687b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
3688b7f5c055SJed Brown     grad[i] = PETSC_PI * g[i];
3689ad540459SPierre Jolivet     for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.;
3690b7f5c055SJed Brown   }
3691b7f5c055SJed Brown }
3692b7f5c055SJed Brown 
36934663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
3694d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
3695d71ae5a4SJacob Faibussowitsch {
3696ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI);
36973ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
36984663dae6SJed Brown }
36994663dae6SJed Brown 
3700b7f5c055SJed Brown /*
3701b7f5c055SJed Brown  The Gyroid implicit surface is
3702b7f5c055SJed Brown 
3703b7f5c055SJed 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)
3704b7f5c055SJed Brown 
3705b7f5c055SJed Brown */
3706d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
3707d71ae5a4SJacob Faibussowitsch {
3708b7f5c055SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))};
3709b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))};
3710b7f5c055SJed Brown   f[0]           = s[0] * c[1] + s[1] * c[2] + s[2] * c[0];
3711b7f5c055SJed Brown   grad[0]        = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
3712b7f5c055SJed Brown   grad[1]        = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
3713b7f5c055SJed Brown   grad[2]        = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
3714b7f5c055SJed Brown   hess[0][0]     = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]);
3715b7f5c055SJed Brown   hess[0][1]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
3716b7f5c055SJed Brown   hess[0][2]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
3717b7f5c055SJed Brown   hess[1][0]     = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]);
3718b7f5c055SJed Brown   hess[1][1]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
3719b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
3720b7f5c055SJed Brown   hess[2][0]     = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]);
3721b7f5c055SJed Brown   hess[2][1]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
3722b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
3723b7f5c055SJed Brown }
3724b7f5c055SJed Brown 
37254663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
3726d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
3727d71ae5a4SJacob Faibussowitsch {
37284663dae6SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))};
37294663dae6SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))};
37304663dae6SJed Brown   u[0]           = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
37314663dae6SJed Brown   u[1]           = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
37324663dae6SJed Brown   u[2]           = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
37333ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
37344663dae6SJed Brown }
37354663dae6SJed Brown 
3736b7f5c055SJed Brown /*
3737b7f5c055SJed Brown    We wish to solve
3738b7f5c055SJed Brown 
3739b7f5c055SJed Brown          min_y || y - x ||^2  subject to f(y) = 0
3740b7f5c055SJed Brown 
3741b7f5c055SJed Brown    Let g(y) = grad(f).  The minimization problem is equivalent to asking to satisfy
3742b7f5c055SJed 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
3743b7f5c055SJed Brown    tangent space and ask for both components in the tangent space to be zero.
3744b7f5c055SJed Brown 
3745b7f5c055SJed Brown    Take g to be a column vector and compute the "full QR" factorization Q R = g,
3746b7f5c055SJed Brown    where Q = I - 2 n n^T is a symmetric orthogonal matrix.
3747b7f5c055SJed Brown    The first column of Q is parallel to g so the remaining two columns span the null space.
3748b7f5c055SJed Brown    Let Qn = Q[:,1:] be those remaining columns.  Then Qn Qn^T is an orthogonal projector into the tangent space.
3749da81f932SPierre Jolivet    Since Q is symmetric, this is equivalent to multiplying by Q and taking the last two entries.
3750b7f5c055SJed Brown    In total, we have a system of 3 equations in 3 unknowns:
3751b7f5c055SJed Brown 
3752b7f5c055SJed Brown      f(y) = 0                       1 equation
3753b7f5c055SJed Brown      Qn^T (y - x) = 0               2 equations
3754b7f5c055SJed Brown 
3755b7f5c055SJed Brown    Here, we compute the residual and Jacobian of this system.
3756b7f5c055SJed Brown */
3757d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[])
3758d71ae5a4SJacob Faibussowitsch {
3759b7f5c055SJed Brown   PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])};
3760b7f5c055SJed Brown   PetscReal d[3]     = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])};
37612f0490c0SSatish Balay   PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign;
37629371c9d4SSatish Balay   PetscReal n_y[3][3] = {
37639371c9d4SSatish Balay     {0, 0, 0},
37649371c9d4SSatish Balay     {0, 0, 0},
37659371c9d4SSatish Balay     {0, 0, 0}
37669371c9d4SSatish Balay   };
3767b7f5c055SJed Brown 
3768b7f5c055SJed Brown   feval(yreal, &f, grad, n_y);
3769b7f5c055SJed Brown 
3770b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n[i] = grad[i];
3771b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
3772ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i];
3773b7f5c055SJed Brown 
3774b7f5c055SJed Brown   // Define the Householder reflector
3775b7f5c055SJed Brown   sign = n[0] >= 0 ? 1. : -1.;
3776b7f5c055SJed Brown   n[0] += norm * sign;
3777b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign;
3778b7f5c055SJed Brown 
3779b7f5c055SJed Brown   norm      = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
3780b7f5c055SJed Brown   norm_y[0] = 1. / norm * (n[0] * n_y[0][0]);
3781b7f5c055SJed Brown   norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]);
3782b7f5c055SJed Brown   norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]);
3783b7f5c055SJed Brown 
3784b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
3785b7f5c055SJed Brown     n[i] /= norm;
3786b7f5c055SJed Brown     for (PetscInt j = 0; j < 3; j++) {
3787b7f5c055SJed Brown       // note that n[i] is n_old[i]/norm when executing the code below
3788b7f5c055SJed Brown       n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j];
3789b7f5c055SJed Brown     }
3790b7f5c055SJed Brown   }
3791b7f5c055SJed Brown 
3792b7f5c055SJed Brown   nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2];
3793b7f5c055SJed 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];
3794b7f5c055SJed Brown 
3795b7f5c055SJed Brown   res[0] = f;
3796b7f5c055SJed Brown   res[1] = d[1] - 2 * n[1] * nd;
3797b7f5c055SJed Brown   res[2] = d[2] - 2 * n[2] * nd;
3798b7f5c055SJed Brown   // J[j][i] is J_{ij} (column major)
3799b7f5c055SJed Brown   for (PetscInt j = 0; j < 3; j++) {
3800b7f5c055SJed Brown     J[0 + j * 3] = grad[j];
3801b7f5c055SJed Brown     J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]);
3802b7f5c055SJed Brown     J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]);
3803b7f5c055SJed Brown   }
3804b7f5c055SJed Brown }
3805b7f5c055SJed Brown 
3806b7f5c055SJed Brown /*
3807b7f5c055SJed Brown    Project x to the nearest point on the implicit surface using Newton's method.
3808b7f5c055SJed Brown */
3809d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[])
3810d71ae5a4SJacob Faibussowitsch {
3811b7f5c055SJed Brown   PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess
3812b7f5c055SJed Brown 
3813b7f5c055SJed Brown   PetscFunctionBegin;
3814b7f5c055SJed Brown   for (PetscInt iter = 0; iter < 10; iter++) {
3815b7f5c055SJed Brown     PetscScalar res[3], J[9];
3816b7f5c055SJed Brown     PetscReal   resnorm;
3817b7f5c055SJed Brown     TPSNearestPointResJac(feval, x, y, res, J);
3818b7f5c055SJed Brown     resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2])));
3819b7f5c055SJed Brown     if (0) { // Turn on this monitor if you need to confirm quadratic convergence
382063a3b9bcSJacob 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])));
3821b7f5c055SJed Brown     }
3822b7f5c055SJed Brown     if (resnorm < PETSC_SMALL) break;
3823b7f5c055SJed Brown 
3824b7f5c055SJed Brown     // Take the Newton step
38259566063dSJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL));
3826b7f5c055SJed Brown     PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res);
3827b7f5c055SJed Brown   }
3828b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) x[i] = y[i];
38293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3830b7f5c055SJed Brown }
3831b7f5c055SJed Brown 
3832b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL};
3833b7f5c055SJed Brown 
3834d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness)
3835d71ae5a4SJacob Faibussowitsch {
3836b7f5c055SJed Brown   PetscMPIInt rank;
3837b7f5c055SJed Brown   PetscInt    topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0;
3838b7f5c055SJed Brown   PetscInt (*edges)[2] = NULL, *edgeSets = NULL;
3839b7f5c055SJed Brown   PetscInt           *cells_flat = NULL;
3840b7f5c055SJed Brown   PetscReal          *vtxCoords  = NULL;
3841b7f5c055SJed Brown   TPSEvaluateFunc     evalFunc   = NULL;
38428434afd1SBarry Smith   PetscSimplePointFn *normalFunc = NULL;
3843b7f5c055SJed Brown   DMLabel             label;
3844b7f5c055SJed Brown 
3845b7f5c055SJed Brown   PetscFunctionBegin;
384646139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
38479566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
384863a3b9bcSJacob 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);
3849b7f5c055SJed Brown   switch (tpstype) {
3850b7f5c055SJed Brown   case DMPLEX_TPS_SCHWARZ_P:
3851b7f5c055SJed 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");
3852c5853193SPierre Jolivet     if (rank == 0) {
3853b7f5c055SJed Brown       PetscInt (*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn]
3854b7f5c055SJed Brown       PetscInt  Njunctions = 0, Ncuts = 0, Npipes[3], vcount;
3855b7f5c055SJed Brown       PetscReal L = 1;
3856b7f5c055SJed Brown 
3857b7f5c055SJed Brown       Npipes[0]   = (extent[0] + 1) * extent[1] * extent[2];
3858b7f5c055SJed Brown       Npipes[1]   = extent[0] * (extent[1] + 1) * extent[2];
3859b7f5c055SJed Brown       Npipes[2]   = extent[0] * extent[1] * (extent[2] + 1);
3860b7f5c055SJed Brown       Njunctions  = extent[0] * extent[1] * extent[2];
3861b7f5c055SJed Brown       Ncuts       = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]);
3862b7f5c055SJed Brown       numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions;
38639566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords));
38649566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Njunctions, &cells));
38659566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edges));
38669566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets));
3867b7f5c055SJed Brown       // x-normal pipes
3868b7f5c055SJed Brown       vcount = 0;
3869b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0] + 1; i++) {
3870b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3871b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3872b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3873b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * i - 1) * L;
3874b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3875b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3876b7f5c055SJed Brown             }
3877b7f5c055SJed Brown           }
3878b7f5c055SJed Brown         }
3879b7f5c055SJed Brown       }
3880b7f5c055SJed Brown       // y-normal pipes
3881b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3882b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1] + 1; j++) {
3883b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3884b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3885b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3886b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * j - 1) * L;
3887b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3888b7f5c055SJed Brown             }
3889b7f5c055SJed Brown           }
3890b7f5c055SJed Brown         }
3891b7f5c055SJed Brown       }
3892b7f5c055SJed Brown       // z-normal pipes
3893b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3894b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3895b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2] + 1; k++) {
3896b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3897b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3898b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3899b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * k - 1) * L;
3900b7f5c055SJed Brown             }
3901b7f5c055SJed Brown           }
3902b7f5c055SJed Brown         }
3903b7f5c055SJed Brown       }
3904b7f5c055SJed Brown       // junctions
3905b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3906b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3907b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3908b7f5c055SJed Brown             const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8;
3909b7f5c055SJed Brown             PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count");
3910b7f5c055SJed Brown             for (PetscInt ii = 0; ii < 2; ii++) {
3911b7f5c055SJed Brown               for (PetscInt jj = 0; jj < 2; jj++) {
3912b7f5c055SJed Brown                 for (PetscInt kk = 0; kk < 2; kk++) {
3913b7f5c055SJed Brown                   double Ls           = (1 - sqrt(2) / 4) * L;
3914b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls;
3915b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls;
3916b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls;
3917b7f5c055SJed Brown                 }
3918b7f5c055SJed Brown               }
3919b7f5c055SJed Brown             }
3920b7f5c055SJed Brown             const PetscInt jfaces[3][2][4] = {
3921b7f5c055SJed Brown               {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned
3922b7f5c055SJed Brown               {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned
3923b7f5c055SJed Brown               {{6, 2, 0, 4}, {7, 3, 1, 5}}  // z-aligned
3924b7f5c055SJed Brown             };
3925b7f5c055SJed Brown             const PetscInt pipe_lo[3] = {// vertex numbers of pipes
39269371c9d4SSatish 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};
3927b7f5c055SJed Brown             const PetscInt pipe_hi[3] = {// vertex numbers of pipes
39289371c9d4SSatish 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};
3929b7f5c055SJed Brown             for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z
3930b7f5c055SJed Brown               const PetscInt ijk[3] = {i, j, k};
3931b7f5c055SJed Brown               for (PetscInt l = 0; l < 4; l++) { // rotations
3932b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l;
3933b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l];
3934b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4];
3935b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4;
3936b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l];
3937b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l;
3938b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4;
3939b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4];
3940b7f5c055SJed Brown                 if (ijk[dir] == 0) {
3941b7f5c055SJed Brown                   edges[numEdges][0] = pipe_lo[dir] + l;
3942b7f5c055SJed Brown                   edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4;
3943b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 1;
3944b7f5c055SJed Brown                   numEdges++;
3945b7f5c055SJed Brown                 }
3946b7f5c055SJed Brown                 if (ijk[dir] + 1 == extent[dir]) {
3947b7f5c055SJed Brown                   edges[numEdges][0] = pipe_hi[dir] + l;
3948b7f5c055SJed Brown                   edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4;
3949b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 2;
3950b7f5c055SJed Brown                   numEdges++;
3951b7f5c055SJed Brown                 }
3952b7f5c055SJed Brown               }
3953b7f5c055SJed Brown             }
3954b7f5c055SJed Brown           }
3955b7f5c055SJed Brown         }
3956b7f5c055SJed Brown       }
395763a3b9bcSJacob Faibussowitsch       PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts);
3958b7f5c055SJed Brown       numFaces   = 24 * Njunctions;
3959b7f5c055SJed Brown       cells_flat = cells[0][0][0];
3960b7f5c055SJed Brown     }
3961b7f5c055SJed Brown     evalFunc   = TPSEvaluate_SchwarzP;
39624663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_SchwarzP;
3963b7f5c055SJed Brown     break;
3964b7f5c055SJed Brown   case DMPLEX_TPS_GYROID:
3965c5853193SPierre Jolivet     if (rank == 0) {
3966b7f5c055SJed Brown       // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set
3967b7f5c055SJed Brown       //
3968b7f5c055SJed 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)
3969b7f5c055SJed Brown       //
3970b7f5c055SJed Brown       // on the cell [0,2]^3.
3971b7f5c055SJed Brown       //
3972b7f5c055SJed Brown       // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2].
3973b7f5c055SJed Brown       // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins
3974b7f5c055SJed Brown       // like a boomerang:
3975b7f5c055SJed Brown       //
3976b7f5c055SJed Brown       //     z = 0          z = 1/4        z = 1/2        z = 3/4     //
3977b7f5c055SJed Brown       //     -----          -------        -------        -------     //
3978b7f5c055SJed Brown       //                                                              //
3979b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
3980b7f5c055SJed Brown       //      \                                   /            \      //
3981b7f5c055SJed Brown       //       \            `-_   _-'            /              }     //
3982b7f5c055SJed Brown       //        *-_            `-'            _-'              /      //
3983b7f5c055SJed Brown       //     +     `-+      +       +      +-'     +      +   /   +   //
3984b7f5c055SJed Brown       //                                                              //
3985b7f5c055SJed Brown       //                                                              //
3986b7f5c055SJed Brown       //     z = 1          z = 5/4        z = 3/2        z = 7/4     //
3987b7f5c055SJed Brown       //     -----          -------        -------        -------     //
3988b7f5c055SJed Brown       //                                                              //
3989b7f5c055SJed Brown       //     +-_     +      +       +      +     _-+      +   /   +   //
3990b7f5c055SJed Brown       //        `-_            _-_            _-`            /        //
3991b7f5c055SJed Brown       //           \        _-'   `-_        /              {         //
3992b7f5c055SJed Brown       //            \                       /                \        //
3993b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
3994b7f5c055SJed Brown       //
3995b7f5c055SJed Brown       //
3996b7f5c055SJed Brown       // This course mesh approximates each of these slices by two line segments,
3997b7f5c055SJed Brown       // and then connects the segments in consecutive layers with quadrilateral faces.
3998b7f5c055SJed Brown       // All of the end points of the segments are multiples of 1/4 except for the
3999b7f5c055SJed Brown       // point * in the picture for z = 0 above and the similar points in other layers.
4000b7f5c055SJed Brown       // That point is at (gamma, gamma, 0), where gamma is calculated below.
4001b7f5c055SJed Brown       //
4002b7f5c055SJed Brown       // The column  [1,2]x[1,2]x[0,2] looks the same as this column;
4003b7f5c055SJed Brown       // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images.
4004b7f5c055SJed Brown       //
4005b7f5c055SJed Brown       // As for how this method turned into the names given to the vertices:
4006b7f5c055SJed Brown       // that was not systematic, it was just the way it worked out in my handwritten notes.
4007b7f5c055SJed Brown 
4008b7f5c055SJed Brown       PetscInt facesPerBlock = 64;
4009b7f5c055SJed Brown       PetscInt vertsPerBlock = 56;
4010b7f5c055SJed Brown       PetscInt extentPlus[3];
4011b7f5c055SJed Brown       PetscInt numBlocks, numBlocksPlus;
40129371c9d4SSatish 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;
40139371c9d4SSatish Balay       const PetscInt pattern[64][4] = {
40149371c9d4SSatish Balay         /* face to vertex within the coarse discretization of a single gyroid block */
4015b7f5c055SJed Brown         /* layer 0 */
40169371c9d4SSatish Balay         {A,           C,           K,           G          },
40179371c9d4SSatish Balay         {C,           B,           II,          K          },
40189371c9d4SSatish Balay         {D,           A,           H,           L          },
40199371c9d4SSatish Balay         {B + 56 * 1,  D,           L,           J          },
40209371c9d4SSatish Balay         {E,           B + 56 * 1,  J,           N          },
40219371c9d4SSatish Balay         {A + 56 * 2,  E,           N,           H + 56 * 2 },
40229371c9d4SSatish Balay         {F,           A + 56 * 2,  G + 56 * 2,  M          },
40239371c9d4SSatish Balay         {B,           F,           M,           II         },
4024b7f5c055SJed Brown         /* layer 1 */
40259371c9d4SSatish Balay         {G,           K,           Q,           O          },
40269371c9d4SSatish Balay         {K,           II,          P,           Q          },
40279371c9d4SSatish Balay         {L,           H,           O + 56 * 1,  R          },
40289371c9d4SSatish Balay         {J,           L,           R,           P          },
40299371c9d4SSatish Balay         {N,           J,           P,           S          },
40309371c9d4SSatish Balay         {H + 56 * 2,  N,           S,           O + 56 * 3 },
40319371c9d4SSatish Balay         {M,           G + 56 * 2,  O + 56 * 2,  T          },
40329371c9d4SSatish Balay         {II,          M,           T,           P          },
4033b7f5c055SJed Brown         /* layer 2 */
40349371c9d4SSatish Balay         {O,           Q,           Y,           U          },
40359371c9d4SSatish Balay         {Q,           P,           W,           Y          },
40369371c9d4SSatish Balay         {R,           O + 56 * 1,  U + 56 * 1,  Ap         },
40379371c9d4SSatish Balay         {P,           R,           Ap,          W          },
40389371c9d4SSatish Balay         {S,           P,           X,           Bp         },
40399371c9d4SSatish Balay         {O + 56 * 3,  S,           Bp,          V + 56 * 1 },
40409371c9d4SSatish Balay         {T,           O + 56 * 2,  V,           Z          },
40419371c9d4SSatish Balay         {P,           T,           Z,           X          },
4042b7f5c055SJed Brown         /* layer 3 */
40439371c9d4SSatish Balay         {U,           Y,           Ep,          Dp         },
40449371c9d4SSatish Balay         {Y,           W,           Cp,          Ep         },
40459371c9d4SSatish Balay         {Ap,          U + 56 * 1,  Dp + 56 * 1, Gp         },
40469371c9d4SSatish Balay         {W,           Ap,          Gp,          Cp         },
40479371c9d4SSatish Balay         {Bp,          X,           Cp + 56 * 2, Fp         },
40489371c9d4SSatish Balay         {V + 56 * 1,  Bp,          Fp,          Dp + 56 * 1},
40499371c9d4SSatish Balay         {Z,           V,           Dp,          Hp         },
40509371c9d4SSatish Balay         {X,           Z,           Hp,          Cp + 56 * 2},
4051b7f5c055SJed Brown         /* layer 4 */
40529371c9d4SSatish Balay         {Dp,          Ep,          Mp,          Kp         },
40539371c9d4SSatish Balay         {Ep,          Cp,          Ip,          Mp         },
40549371c9d4SSatish Balay         {Gp,          Dp + 56 * 1, Lp,          Np         },
40559371c9d4SSatish Balay         {Cp,          Gp,          Np,          Jp         },
40569371c9d4SSatish Balay         {Fp,          Cp + 56 * 2, Jp + 56 * 2, Pp         },
40579371c9d4SSatish Balay         {Dp + 56 * 1, Fp,          Pp,          Lp         },
40589371c9d4SSatish Balay         {Hp,          Dp,          Kp,          Op         },
40599371c9d4SSatish Balay         {Cp + 56 * 2, Hp,          Op,          Ip + 56 * 2},
4060b7f5c055SJed Brown         /* layer 5 */
40619371c9d4SSatish Balay         {Kp,          Mp,          Sp,          Rp         },
40629371c9d4SSatish Balay         {Mp,          Ip,          Qp,          Sp         },
40639371c9d4SSatish Balay         {Np,          Lp,          Rp,          Tp         },
40649371c9d4SSatish Balay         {Jp,          Np,          Tp,          Qp + 56 * 1},
40659371c9d4SSatish Balay         {Pp,          Jp + 56 * 2, Qp + 56 * 3, Up         },
40669371c9d4SSatish Balay         {Lp,          Pp,          Up,          Rp         },
40679371c9d4SSatish Balay         {Op,          Kp,          Rp,          Vp         },
40689371c9d4SSatish Balay         {Ip + 56 * 2, Op,          Vp,          Qp + 56 * 2},
4069b7f5c055SJed Brown         /* layer 6 */
40709371c9d4SSatish Balay         {Rp,          Sp,          Aq,          Yp         },
40719371c9d4SSatish Balay         {Sp,          Qp,          Wp,          Aq         },
40729371c9d4SSatish Balay         {Tp,          Rp,          Yp,          Cq         },
40739371c9d4SSatish Balay         {Qp + 56 * 1, Tp,          Cq,          Wp + 56 * 1},
40749371c9d4SSatish Balay         {Up,          Qp + 56 * 3, Xp + 56 * 1, Dq         },
40759371c9d4SSatish Balay         {Rp,          Up,          Dq,          Zp         },
40769371c9d4SSatish Balay         {Vp,          Rp,          Zp,          Bq         },
40779371c9d4SSatish Balay         {Qp + 56 * 2, Vp,          Bq,          Xp         },
4078b7f5c055SJed Brown         /* layer 7 (the top is the periodic image of the bottom of layer 0) */
40799371c9d4SSatish Balay         {Yp,          Aq,          C + 56 * 4,  A + 56 * 4 },
40809371c9d4SSatish Balay         {Aq,          Wp,          B + 56 * 4,  C + 56 * 4 },
40819371c9d4SSatish Balay         {Cq,          Yp,          A + 56 * 4,  D + 56 * 4 },
40829371c9d4SSatish Balay         {Wp + 56 * 1, Cq,          D + 56 * 4,  B + 56 * 5 },
40839371c9d4SSatish Balay         {Dq,          Xp + 56 * 1, B + 56 * 5,  E + 56 * 4 },
40849371c9d4SSatish Balay         {Zp,          Dq,          E + 56 * 4,  A + 56 * 6 },
40859371c9d4SSatish Balay         {Bq,          Zp,          A + 56 * 6,  F + 56 * 4 },
40869371c9d4SSatish Balay         {Xp,          Bq,          F + 56 * 4,  B + 56 * 4 }
4087b7f5c055SJed Brown       };
4088b7f5c055SJed Brown       const PetscReal gamma                = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI;
40899371c9d4SSatish Balay       const PetscReal patternCoords[56][3] = {
4090bee3fc89SBarry Smith         {1.,        0.,        0.  }, /* A  */
4091bee3fc89SBarry Smith         {0.,        1.,        0.  }, /* B  */
4092bee3fc89SBarry Smith         {gamma,     gamma,     0.  }, /* C  */
4093bee3fc89SBarry Smith         {1 + gamma, 1 - gamma, 0.  }, /* D  */
4094bee3fc89SBarry Smith         {2 - gamma, 2 - gamma, 0.  }, /* E  */
4095bee3fc89SBarry Smith         {1 - gamma, 1 + gamma, 0.  }, /* F  */
4096b7f5c055SJed Brown 
4097bee3fc89SBarry Smith         {.5,        0,         .25 }, /* G  */
4098bee3fc89SBarry Smith         {1.5,       0.,        .25 }, /* H  */
4099bee3fc89SBarry Smith         {.5,        1.,        .25 }, /* II */
4100bee3fc89SBarry Smith         {1.5,       1.,        .25 }, /* J  */
4101bee3fc89SBarry Smith         {.25,       .5,        .25 }, /* K  */
4102bee3fc89SBarry Smith         {1.25,      .5,        .25 }, /* L  */
4103bee3fc89SBarry Smith         {.75,       1.5,       .25 }, /* M  */
4104bee3fc89SBarry Smith         {1.75,      1.5,       .25 }, /* N  */
4105b7f5c055SJed Brown 
4106bee3fc89SBarry Smith         {0.,        0.,        .5  }, /* O  */
4107bee3fc89SBarry Smith         {1.,        1.,        .5  }, /* P  */
4108bee3fc89SBarry Smith         {gamma,     1 - gamma, .5  }, /* Q  */
4109bee3fc89SBarry Smith         {1 + gamma, gamma,     .5  }, /* R  */
4110bee3fc89SBarry Smith         {2 - gamma, 1 + gamma, .5  }, /* S  */
4111bee3fc89SBarry Smith         {1 - gamma, 2 - gamma, .5  }, /* T  */
4112b7f5c055SJed Brown 
4113bee3fc89SBarry Smith         {0.,        .5,        .75 }, /* U  */
4114bee3fc89SBarry Smith         {0.,        1.5,       .75 }, /* V  */
4115bee3fc89SBarry Smith         {1.,        .5,        .75 }, /* W  */
4116bee3fc89SBarry Smith         {1.,        1.5,       .75 }, /* X  */
4117bee3fc89SBarry Smith         {.5,        .75,       .75 }, /* Y  */
4118bee3fc89SBarry Smith         {.5,        1.75,      .75 }, /* Z  */
4119bee3fc89SBarry Smith         {1.5,       .25,       .75 }, /* Ap */
4120bee3fc89SBarry Smith         {1.5,       1.25,      .75 }, /* Bp */
4121b7f5c055SJed Brown 
4122bee3fc89SBarry Smith         {1.,        0.,        1.  }, /* Cp */
4123bee3fc89SBarry Smith         {0.,        1.,        1.  }, /* Dp */
4124bee3fc89SBarry Smith         {1 - gamma, 1 - gamma, 1.  }, /* Ep */
4125bee3fc89SBarry Smith         {1 + gamma, 1 + gamma, 1.  }, /* Fp */
4126bee3fc89SBarry Smith         {2 - gamma, gamma,     1.  }, /* Gp */
4127bee3fc89SBarry Smith         {gamma,     2 - gamma, 1.  }, /* Hp */
4128b7f5c055SJed Brown 
4129bee3fc89SBarry Smith         {.5,        0.,        1.25}, /* Ip */
4130bee3fc89SBarry Smith         {1.5,       0.,        1.25}, /* Jp */
4131bee3fc89SBarry Smith         {.5,        1.,        1.25}, /* Kp */
4132bee3fc89SBarry Smith         {1.5,       1.,        1.25}, /* Lp */
4133bee3fc89SBarry Smith         {.75,       .5,        1.25}, /* Mp */
4134bee3fc89SBarry Smith         {1.75,      .5,        1.25}, /* Np */
4135bee3fc89SBarry Smith         {.25,       1.5,       1.25}, /* Op */
4136bee3fc89SBarry Smith         {1.25,      1.5,       1.25}, /* Pp */
4137b7f5c055SJed Brown 
4138bee3fc89SBarry Smith         {0.,        0.,        1.5 }, /* Qp */
4139bee3fc89SBarry Smith         {1.,        1.,        1.5 }, /* Rp */
4140bee3fc89SBarry Smith         {1 - gamma, gamma,     1.5 }, /* Sp */
4141bee3fc89SBarry Smith         {2 - gamma, 1 - gamma, 1.5 }, /* Tp */
4142bee3fc89SBarry Smith         {1 + gamma, 2 - gamma, 1.5 }, /* Up */
4143bee3fc89SBarry Smith         {gamma,     1 + gamma, 1.5 }, /* Vp */
4144b7f5c055SJed Brown 
4145bee3fc89SBarry Smith         {0.,        .5,        1.75}, /* Wp */
4146bee3fc89SBarry Smith         {0.,        1.5,       1.75}, /* Xp */
4147bee3fc89SBarry Smith         {1.,        .5,        1.75}, /* Yp */
4148bee3fc89SBarry Smith         {1.,        1.5,       1.75}, /* Zp */
4149bee3fc89SBarry Smith         {.5,        .25,       1.75}, /* Aq */
4150bee3fc89SBarry Smith         {.5,        1.25,      1.75}, /* Bq */
4151bee3fc89SBarry Smith         {1.5,       .75,       1.75}, /* Cq */
4152bee3fc89SBarry Smith         {1.5,       1.75,      1.75}, /* Dq */
4153b7f5c055SJed Brown       };
4154b7f5c055SJed Brown       PetscInt (*cells)[64][4] = NULL;
4155b7f5c055SJed Brown       PetscBool *seen;
4156b7f5c055SJed Brown       PetscInt  *vertToTrueVert;
4157b7f5c055SJed Brown       PetscInt   count;
4158b7f5c055SJed Brown 
4159b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1;
4160b7f5c055SJed Brown       numBlocks = 1;
4161b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i];
4162b7f5c055SJed Brown       numBlocksPlus = 1;
4163b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i];
4164b7f5c055SJed Brown       numFaces = numBlocks * facesPerBlock;
41659566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocks, &cells));
41669566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen));
4167b7f5c055SJed Brown       for (PetscInt k = 0; k < extent[2]; k++) {
4168b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
4169b7f5c055SJed Brown           for (PetscInt i = 0; i < extent[0]; i++) {
4170b7f5c055SJed Brown             for (PetscInt f = 0; f < facesPerBlock; f++) {
4171b7f5c055SJed Brown               for (PetscInt v = 0; v < 4; v++) {
4172b7f5c055SJed Brown                 PetscInt vertRaw     = pattern[f][v];
4173b7f5c055SJed Brown                 PetscInt blockidx    = vertRaw / 56;
4174b7f5c055SJed Brown                 PetscInt patternvert = vertRaw % 56;
4175b7f5c055SJed Brown                 PetscInt xplus       = (blockidx & 1);
4176b7f5c055SJed Brown                 PetscInt yplus       = (blockidx & 2) >> 1;
4177b7f5c055SJed Brown                 PetscInt zplus       = (blockidx & 4) >> 2;
4178b7f5c055SJed Brown                 PetscInt zcoord      = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus);
4179b7f5c055SJed Brown                 PetscInt ycoord      = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus);
4180b7f5c055SJed Brown                 PetscInt xcoord      = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus);
4181b7f5c055SJed Brown                 PetscInt vert        = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert;
4182b7f5c055SJed Brown 
4183b7f5c055SJed Brown                 cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert;
4184b7f5c055SJed Brown                 seen[vert]                                       = PETSC_TRUE;
4185b7f5c055SJed Brown               }
4186b7f5c055SJed Brown             }
4187b7f5c055SJed Brown           }
4188b7f5c055SJed Brown         }
4189b7f5c055SJed Brown       }
41909371c9d4SSatish Balay       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++)
41919371c9d4SSatish Balay         if (seen[i]) numVertices++;
4192b7f5c055SJed Brown       count = 0;
41939566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert));
41949566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords));
4195b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1;
4196b7f5c055SJed Brown       for (PetscInt k = 0; k < extentPlus[2]; k++) {
4197b7f5c055SJed Brown         for (PetscInt j = 0; j < extentPlus[1]; j++) {
4198b7f5c055SJed Brown           for (PetscInt i = 0; i < extentPlus[0]; i++) {
4199b7f5c055SJed Brown             for (PetscInt v = 0; v < vertsPerBlock; v++) {
4200b7f5c055SJed Brown               PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v;
4201b7f5c055SJed Brown 
4202b7f5c055SJed Brown               if (seen[vIdx]) {
4203b7f5c055SJed Brown                 PetscInt thisVert;
4204b7f5c055SJed Brown 
4205b7f5c055SJed Brown                 vertToTrueVert[vIdx] = thisVert = count++;
4206b7f5c055SJed Brown 
4207b7f5c055SJed Brown                 for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d];
4208b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 0] += i * 2;
4209b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 1] += j * 2;
4210b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 2] += k * 2;
4211b7f5c055SJed Brown               }
4212b7f5c055SJed Brown             }
4213b7f5c055SJed Brown           }
4214b7f5c055SJed Brown         }
4215b7f5c055SJed Brown       }
4216b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocks; i++) {
4217b7f5c055SJed Brown         for (PetscInt f = 0; f < facesPerBlock; f++) {
4218ad540459SPierre Jolivet           for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]];
4219b7f5c055SJed Brown         }
4220b7f5c055SJed Brown       }
42219566063dSJacob Faibussowitsch       PetscCall(PetscFree(vertToTrueVert));
42229566063dSJacob Faibussowitsch       PetscCall(PetscFree(seen));
4223b7f5c055SJed Brown       cells_flat = cells[0][0];
4224b7f5c055SJed Brown       numEdges   = 0;
4225b7f5c055SJed Brown       for (PetscInt i = 0; i < numFaces; i++) {
4226b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
4227b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
4228b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
4229b7f5c055SJed Brown 
4230b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
4231b7f5c055SJed Brown             if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) {
4232b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++;
4233b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++;
4234b7f5c055SJed Brown             }
4235b7f5c055SJed Brown           }
4236b7f5c055SJed Brown         }
4237b7f5c055SJed Brown       }
42389566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edges));
42399566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edgeSets));
4240b7f5c055SJed Brown       for (PetscInt edge = 0, i = 0; i < numFaces; i++) {
4241b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
4242b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
4243b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
4244b7f5c055SJed Brown 
4245b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
4246b7f5c055SJed Brown             if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) {
4247b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) {
4248b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
4249b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
4250b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d;
4251b7f5c055SJed Brown               }
4252b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) {
4253b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
4254b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
4255b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d + 1;
4256b7f5c055SJed Brown               }
4257b7f5c055SJed Brown             }
4258b7f5c055SJed Brown           }
4259b7f5c055SJed Brown         }
4260b7f5c055SJed Brown       }
4261b7f5c055SJed Brown     }
4262b7f5c055SJed Brown     evalFunc   = TPSEvaluate_Gyroid;
42634663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_Gyroid;
4264b7f5c055SJed Brown     break;
4265b7f5c055SJed Brown   }
4266b7f5c055SJed Brown 
42679566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, topoDim));
4268c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat));
42699566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL));
42709566063dSJacob Faibussowitsch   PetscCall(PetscFree(cells_flat));
4271b7f5c055SJed Brown   {
4272b7f5c055SJed Brown     DM idm;
42739566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
427469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &idm));
4275b7f5c055SJed Brown   }
4276c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords));
42779566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL));
42789566063dSJacob Faibussowitsch   PetscCall(PetscFree(vtxCoords));
4279b7f5c055SJed Brown 
42809566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
42819566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
4282b7f5c055SJed Brown   for (PetscInt e = 0; e < numEdges; e++) {
4283b7f5c055SJed Brown     PetscInt        njoin;
4284b7f5c055SJed Brown     const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]};
42859566063dSJacob Faibussowitsch     PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join));
428663a3b9bcSJacob 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]);
42879566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(label, join[0], edgeSets[e]));
42889566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join));
4289b7f5c055SJed Brown   }
42909566063dSJacob Faibussowitsch   PetscCall(PetscFree(edges));
42919566063dSJacob Faibussowitsch   PetscCall(PetscFree(edgeSets));
42921436d7faSJed Brown   if (tps_distribute) {
42931436d7faSJed Brown     DM               pdm = NULL;
42941436d7faSJed Brown     PetscPartitioner part;
42951436d7faSJed Brown 
42969566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
42979566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
42989566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm));
429948a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
43001436d7faSJed Brown     // Do not auto-distribute again
43019566063dSJacob Faibussowitsch     PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
43021436d7faSJed Brown   }
4303b7f5c055SJed Brown 
43049566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
4305b7f5c055SJed Brown   for (PetscInt refine = 0; refine < refinements; refine++) {
4306b7f5c055SJed Brown     PetscInt     m;
4307f1d4225fSZach Atkins     DM           dmf, cdm, cdmf;
4308b7f5c055SJed Brown     Vec          X;
4309b7f5c055SJed Brown     PetscScalar *x;
4310f1d4225fSZach Atkins 
43119566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf));
4312f1d4225fSZach Atkins     PetscCall(DMGetCoordinateDM(dm, &cdm));
4313f1d4225fSZach Atkins     PetscCall(DMGetCoordinateDM(dmf, &cdmf));
4314f1d4225fSZach Atkins     PetscCall(DMCopyDisc(cdm, cdmf));
431569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmf));
4316b7f5c055SJed Brown 
43179566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &X));
43189566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(X, &m));
43199566063dSJacob Faibussowitsch     PetscCall(VecGetArray(X, &x));
432048a46eb9SPierre Jolivet     for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i]));
43219566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(X, &x));
4322b7f5c055SJed Brown   }
4323b7f5c055SJed Brown 
4324b7f5c055SJed Brown   // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices.
43259566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
43269566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, label));
4327b7f5c055SJed Brown 
432846139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
432946139095SJed Brown 
4330b7f5c055SJed Brown   if (thickness > 0) {
43314663dae6SJed Brown     DM              edm, cdm, ecdm;
43324663dae6SJed Brown     DMPlexTransform tr;
43334663dae6SJed Brown     const char     *prefix;
43344663dae6SJed Brown     PetscOptions    options;
43354663dae6SJed Brown     // Code from DMPlexExtrude
43364663dae6SJed Brown     PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr));
43374663dae6SJed Brown     PetscCall(DMPlexTransformSetDM(tr, dm));
4338ce78bad3SBarry Smith     PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDETYPE));
43394663dae6SJed Brown     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
43404663dae6SJed Brown     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix));
43414663dae6SJed Brown     PetscCall(PetscObjectGetOptions((PetscObject)dm, &options));
43424663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, options));
43434663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers));
43444663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness));
43454663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE));
43464663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE));
43474663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc));
43484663dae6SJed Brown     PetscCall(DMPlexTransformSetFromOptions(tr));
43494663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL));
43504663dae6SJed Brown     PetscCall(DMPlexTransformSetUp(tr));
43514663dae6SJed Brown     PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view"));
43524663dae6SJed Brown     PetscCall(DMPlexTransformApply(tr, dm, &edm));
43534663dae6SJed Brown     PetscCall(DMCopyDisc(dm, edm));
43544663dae6SJed Brown     PetscCall(DMGetCoordinateDM(dm, &cdm));
43554663dae6SJed Brown     PetscCall(DMGetCoordinateDM(edm, &ecdm));
43564663dae6SJed Brown     PetscCall(DMCopyDisc(cdm, ecdm));
43574663dae6SJed Brown     PetscCall(DMPlexTransformCreateDiscLabels(tr, edm));
43584663dae6SJed Brown     PetscCall(DMPlexTransformDestroy(&tr));
4359a77a5016SMatthew G. Knepley     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, edm));
436069d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
4361b7f5c055SJed Brown   }
43623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4363b7f5c055SJed Brown }
4364b7f5c055SJed Brown 
4365b7f5c055SJed Brown /*@
4366b7f5c055SJed Brown   DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface
4367b7f5c055SJed Brown 
4368b7f5c055SJed Brown   Collective
4369b7f5c055SJed Brown 
4370b7f5c055SJed Brown   Input Parameters:
4371a1cb98faSBarry Smith + comm           - The communicator for the `DM` object
4372b7f5c055SJed Brown . tpstype        - Type of triply-periodic surface
4373b7f5c055SJed Brown . extent         - Array of length 3 containing number of periods in each direction
437420f4b53cSBarry Smith . periodic       - array of length 3 with periodicity, or `NULL` for non-periodic
43751436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable)
4376817da375SSatish Balay . refinements    - Number of factor-of-2 refinements of 2D manifold mesh
43771436d7faSJed Brown . layers         - Number of cell layers extruded in normal direction
4378817da375SSatish Balay - thickness      - Thickness in normal direction
4379b7f5c055SJed Brown 
4380b7f5c055SJed Brown   Output Parameter:
4381a1cb98faSBarry Smith . dm - The `DM` object
4382a1cb98faSBarry Smith 
4383a1cb98faSBarry Smith   Level: beginner
4384b7f5c055SJed Brown 
4385b7f5c055SJed Brown   Notes:
438615229ffcSPierre Jolivet   This meshes the surface of the Schwarz P or Gyroid surfaces.  Schwarz P is the simplest member of the triply-periodic minimal surfaces.
43871d27aa22SBarry Smith   <https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22)> and can be cut with "clean" boundaries.
43881d27aa22SBarry 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.
4389b7f5c055SJed Brown   Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested.
4390b7f5c055SJed Brown   On each refinement, all vertices are projected to their nearest point on the surface.
4391b7f5c055SJed Brown   This projection could readily be extended to related surfaces.
4392b7f5c055SJed Brown 
43931d27aa22SBarry Smith   See {cite}`maskery2018insights`
43941d27aa22SBarry Smith 
43951d27aa22SBarry Smith   The face (edge) sets for the Schwarz P surface are numbered $1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z)$.
43961d27aa22SBarry Smith   When the mesh is refined, "Face Sets" contain the new vertices (created during refinement).
43971d27aa22SBarry Smith   Use `DMPlexLabelComplete()` to propagate to coarse-level vertices.
4398b7f5c055SJed Brown 
439960225df5SJacob Faibussowitsch   Developer Notes:
4400b7f5c055SJed Brown   The Gyroid mesh does not currently mark boundary sets.
4401b7f5c055SJed Brown 
44021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()`
4403b7f5c055SJed Brown @*/
4404d71ae5a4SJacob 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)
4405d71ae5a4SJacob Faibussowitsch {
4406b7f5c055SJed Brown   PetscFunctionBegin;
44079566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
44089566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
44099566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness));
44103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4411b7f5c055SJed Brown }
4412b7f5c055SJed Brown 
44139318fe57SMatthew G. Knepley /*@
44149318fe57SMatthew G. Knepley   DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d.
44159318fe57SMatthew G. Knepley 
44169318fe57SMatthew G. Knepley   Collective
44179318fe57SMatthew G. Knepley 
44189318fe57SMatthew G. Knepley   Input Parameters:
4419a1cb98faSBarry Smith + comm    - The communicator for the `DM` object
44209318fe57SMatthew G. Knepley . dim     - The dimension
44219318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells
44229318fe57SMatthew G. Knepley - R       - The radius
44239318fe57SMatthew G. Knepley 
44249318fe57SMatthew G. Knepley   Output Parameter:
4425a1cb98faSBarry Smith . dm - The `DM` object
44269318fe57SMatthew G. Knepley 
44279318fe57SMatthew G. Knepley   Level: beginner
44289318fe57SMatthew G. Knepley 
44291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
44309318fe57SMatthew G. Knepley @*/
4431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm)
4432d71ae5a4SJacob Faibussowitsch {
44339318fe57SMatthew G. Knepley   PetscFunctionBegin;
44344f572ea9SToby Isaac   PetscAssertPointer(dm, 5);
44359566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
44369566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
44379566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R));
44383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44399318fe57SMatthew G. Knepley }
44409318fe57SMatthew G. Knepley 
4441d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R)
4442d71ae5a4SJacob Faibussowitsch {
44439318fe57SMatthew G. Knepley   DM          sdm, vol;
44449318fe57SMatthew G. Knepley   DMLabel     bdlabel;
4445dd2b43ebSStefano Zampini   const char *prefix;
44469318fe57SMatthew G. Knepley 
44479318fe57SMatthew G. Knepley   PetscFunctionBegin;
44489566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm));
44499566063dSJacob Faibussowitsch   PetscCall(DMSetType(sdm, DMPLEX));
4450dd2b43ebSStefano Zampini   PetscCall(DMGetOptionsPrefix(dm, &prefix));
4451dd2b43ebSStefano Zampini   PetscCall(DMSetOptionsPrefix(sdm, prefix));
4452dd2b43ebSStefano Zampini   PetscCall(DMAppendOptionsPrefix(sdm, "bd_"));
4453dd2b43ebSStefano Zampini   PetscCall(DMPlexDistributeSetDefault(sdm, PETSC_FALSE));
44549566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R));
44559566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(sdm));
44569566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view"));
44579566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol));
44589566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&sdm));
445969d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
44609566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
44619566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
44629566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
44639566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, bdlabel));
44643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
446551a74b61SMatthew G. Knepley }
446651a74b61SMatthew G. Knepley 
446751a74b61SMatthew G. Knepley /*@
446851a74b61SMatthew G. Knepley   DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d.
446951a74b61SMatthew G. Knepley 
447051a74b61SMatthew G. Knepley   Collective
447151a74b61SMatthew G. Knepley 
447251a74b61SMatthew G. Knepley   Input Parameters:
4473a1cb98faSBarry Smith + comm - The communicator for the `DM` object
447451a74b61SMatthew G. Knepley . dim  - The dimension
447551a74b61SMatthew G. Knepley - R    - The radius
447651a74b61SMatthew G. Knepley 
447751a74b61SMatthew G. Knepley   Output Parameter:
4478a1cb98faSBarry Smith . dm - The `DM` object
447951a74b61SMatthew G. Knepley 
4480a1cb98faSBarry Smith   Options Database Key:
448160225df5SJacob Faibussowitsch . bd_dm_refine - This will refine the surface mesh preserving the sphere geometry
448251a74b61SMatthew G. Knepley 
448351a74b61SMatthew G. Knepley   Level: beginner
448451a74b61SMatthew G. Knepley 
44851cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
448651a74b61SMatthew G. Knepley @*/
4487d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm)
4488d71ae5a4SJacob Faibussowitsch {
448951a74b61SMatthew G. Knepley   PetscFunctionBegin;
44909566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
44919566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
44929566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R));
44933ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44942829fed8SMatthew G. Knepley }
44952829fed8SMatthew G. Knepley 
4496d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct)
4497d71ae5a4SJacob Faibussowitsch {
44980a6ba040SMatthew G. Knepley   PetscFunctionBegin;
44999318fe57SMatthew G. Knepley   switch (ct) {
45009371c9d4SSatish Balay   case DM_POLYTOPE_POINT: {
45019318fe57SMatthew G. Knepley     PetscInt    numPoints[1]        = {1};
45029318fe57SMatthew G. Knepley     PetscInt    coneSize[1]         = {0};
45039318fe57SMatthew G. Knepley     PetscInt    cones[1]            = {0};
45049318fe57SMatthew G. Knepley     PetscInt    coneOrientations[1] = {0};
45059318fe57SMatthew G. Knepley     PetscScalar vertexCoords[1]     = {0.0};
45069318fe57SMatthew G. Knepley 
45079566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 0));
45089566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45099371c9d4SSatish Balay   } break;
45109371c9d4SSatish Balay   case DM_POLYTOPE_SEGMENT: {
45119318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
45129318fe57SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
45139318fe57SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
45149318fe57SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
45159318fe57SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
45169318fe57SMatthew G. Knepley 
45179566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
45189566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45199371c9d4SSatish Balay   } break;
45209371c9d4SSatish Balay   case DM_POLYTOPE_POINT_PRISM_TENSOR: {
4521b5a892a1SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
4522b5a892a1SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
4523b5a892a1SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
4524b5a892a1SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
4525b5a892a1SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
4526b5a892a1SMatthew G. Knepley 
45279566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
45289566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45299371c9d4SSatish Balay   } break;
45309371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
45319318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {3, 1};
45329318fe57SMatthew G. Knepley     PetscInt    coneSize[4]         = {3, 0, 0, 0};
45339318fe57SMatthew G. Knepley     PetscInt    cones[3]            = {1, 2, 3};
45349318fe57SMatthew G. Knepley     PetscInt    coneOrientations[3] = {0, 0, 0};
45359318fe57SMatthew G. Knepley     PetscScalar vertexCoords[6]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0};
45369318fe57SMatthew G. Knepley 
45379566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
45389566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45399371c9d4SSatish Balay   } break;
45409371c9d4SSatish Balay   case DM_POLYTOPE_QUADRILATERAL: {
45419318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
45429318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
45439318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
45449318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
45459318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0};
45469318fe57SMatthew G. Knepley 
45479566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
45489566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45499371c9d4SSatish Balay   } break;
45509371c9d4SSatish Balay   case DM_POLYTOPE_SEG_PRISM_TENSOR: {
45519318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
45529318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
45539318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
45549318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
45559318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0};
45569318fe57SMatthew G. Knepley 
45579566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
45589566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45599371c9d4SSatish Balay   } break;
45609371c9d4SSatish Balay   case DM_POLYTOPE_TETRAHEDRON: {
45619318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
45629318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
4563f0edb160SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
45649318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
4565f0edb160SMatthew 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};
45669318fe57SMatthew G. Knepley 
45679566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
45689566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45699371c9d4SSatish Balay   } break;
45709371c9d4SSatish Balay   case DM_POLYTOPE_HEXAHEDRON: {
45719318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
45729318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
4573f0edb160SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
45749318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
45759371c9d4SSatish 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};
45769318fe57SMatthew G. Knepley 
45779566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
45789566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45799371c9d4SSatish Balay   } break;
45809371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM: {
45819318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
45829318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
4583f0edb160SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
45849318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
45859371c9d4SSatish 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};
45869318fe57SMatthew G. Knepley 
45879566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
45889566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45899371c9d4SSatish Balay   } break;
45909371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM_TENSOR: {
45919318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
45929318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
45939318fe57SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
45949318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
45959371c9d4SSatish 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};
45969318fe57SMatthew G. Knepley 
45979566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
45989566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45999371c9d4SSatish Balay   } break;
46009371c9d4SSatish Balay   case DM_POLYTOPE_QUAD_PRISM_TENSOR: {
46019318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
46029318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
46039318fe57SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
46049318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
46059371c9d4SSatish 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};
46069318fe57SMatthew G. Knepley 
46079566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
46089566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
46099371c9d4SSatish Balay   } break;
46109371c9d4SSatish Balay   case DM_POLYTOPE_PYRAMID: {
46119318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {5, 1};
46129318fe57SMatthew G. Knepley     PetscInt    coneSize[6]         = {5, 0, 0, 0, 0, 0};
4613f0edb160SMatthew G. Knepley     PetscInt    cones[5]            = {1, 2, 3, 4, 5};
46149318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
46159371c9d4SSatish 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};
46169318fe57SMatthew G. Knepley 
46179566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
46189566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
46199371c9d4SSatish Balay   } break;
4620d71ae5a4SJacob Faibussowitsch   default:
4621d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]);
46229318fe57SMatthew G. Knepley   }
46239318fe57SMatthew G. Knepley   {
46249318fe57SMatthew G. Knepley     PetscInt Nv, v;
46259318fe57SMatthew G. Knepley 
46269318fe57SMatthew G. Knepley     /* Must create the celltype label here so that we do not automatically try to compute the types */
46279566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(rdm, "celltype"));
46289566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(rdm, 0, ct));
46299566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(rdm, NULL, &Nv));
46309566063dSJacob Faibussowitsch     for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT));
46319318fe57SMatthew G. Knepley   }
46329566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(rdm));
46339566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct]));
46343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46350a6ba040SMatthew G. Knepley }
46360a6ba040SMatthew G. Knepley 
46379318fe57SMatthew G. Knepley /*@
4638a1cb98faSBarry Smith   DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell
46399318fe57SMatthew G. Knepley 
46409318fe57SMatthew G. Knepley   Collective
46419318fe57SMatthew G. Knepley 
46429318fe57SMatthew G. Knepley   Input Parameters:
46439318fe57SMatthew G. Knepley + comm - The communicator
46449318fe57SMatthew G. Knepley - ct   - The cell type of the reference cell
46459318fe57SMatthew G. Knepley 
46469318fe57SMatthew G. Knepley   Output Parameter:
46479318fe57SMatthew G. Knepley . refdm - The reference cell
46489318fe57SMatthew G. Knepley 
46499318fe57SMatthew G. Knepley   Level: intermediate
46509318fe57SMatthew G. Knepley 
465142747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`
46529318fe57SMatthew G. Knepley @*/
4653d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm)
4654d71ae5a4SJacob Faibussowitsch {
46550a6ba040SMatthew G. Knepley   PetscFunctionBegin;
46569566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, refdm));
46579566063dSJacob Faibussowitsch   PetscCall(DMSetType(*refdm, DMPLEX));
46589566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct));
46593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46609318fe57SMatthew G. Knepley }
466179a015ccSMatthew G. Knepley 
4662d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[])
4663d71ae5a4SJacob Faibussowitsch {
46649318fe57SMatthew G. Knepley   DM        plex;
46659318fe57SMatthew G. Knepley   DMLabel   label;
46669318fe57SMatthew G. Knepley   PetscBool hasLabel;
46670a6ba040SMatthew G. Knepley 
4668c22d3578SMatthew G. Knepley   PetscFunctionBegin;
46699566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &hasLabel));
46703ba16761SJacob Faibussowitsch   if (hasLabel) PetscFunctionReturn(PETSC_SUCCESS);
46719566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, name));
46729566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
46739566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
46749566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label));
46751c8afea9SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(plex, label));
46769566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
46773ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46789318fe57SMatthew G. Knepley }
4679acdc6f61SToby Isaac 
4680669647acSMatthew G. Knepley /*
4681669647acSMatthew 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.
4682669647acSMatthew G. Knepley 
4683669647acSMatthew G. Knepley     (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0]))
4684669647acSMatthew G. Knepley */
4685d71ae5a4SJacob 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[])
4686d71ae5a4SJacob Faibussowitsch {
4687669647acSMatthew G. Knepley   const PetscReal low = PetscRealPart(constants[0]);
4688669647acSMatthew G. Knepley   const PetscReal upp = PetscRealPart(constants[1]);
4689669647acSMatthew G. Knepley   const PetscReal r   = PetscRealPart(u[1]);
4690669647acSMatthew G. Knepley   const PetscReal th  = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low);
4691669647acSMatthew G. Knepley 
4692669647acSMatthew G. Knepley   f0[0] = r * PetscCosReal(th);
4693669647acSMatthew G. Knepley   f0[1] = r * PetscSinReal(th);
4694669647acSMatthew G. Knepley }
4695669647acSMatthew G. Knepley 
46965390be7dSMatthew G. Knepley // Insert vertices and their joins, marked by depth
46975390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Vertices(DM dm, DMLabel label, DMLabel vlabel, PetscInt val, PetscInt n, const PetscInt vertices[])
46985390be7dSMatthew G. Knepley {
46995390be7dSMatthew G. Knepley   PetscFunctionBegin;
47005390be7dSMatthew G. Knepley   PetscCall(DMPlexMarkSubmesh_Interpolated(dm, vlabel, val, PETSC_FALSE, PETSC_FALSE, label, NULL));
47015390be7dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
47025390be7dSMatthew G. Knepley }
47035390be7dSMatthew G. Knepley 
47045390be7dSMatthew G. Knepley // Insert faces and their closures, marked by depth
47055390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Faces(DM dm, DMLabel label, PetscInt n, const PetscInt faces[])
47065390be7dSMatthew G. Knepley {
47075390be7dSMatthew G. Knepley   PetscFunctionBegin;
47085390be7dSMatthew G. Knepley   for (PetscInt p = 0; p < n; ++p) {
47095390be7dSMatthew G. Knepley     const PetscInt point   = faces[p];
47105390be7dSMatthew G. Knepley     PetscInt      *closure = NULL;
47115390be7dSMatthew G. Knepley     PetscInt       clSize, pdepth;
47125390be7dSMatthew G. Knepley 
47135390be7dSMatthew G. Knepley     PetscCall(DMPlexGetPointDepth(dm, point, &pdepth));
47145390be7dSMatthew G. Knepley     PetscCall(DMLabelSetValue(label, point, pdepth));
47155390be7dSMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure));
47165390be7dSMatthew G. Knepley     for (PetscInt cl = 0; cl < clSize * 2; cl += 2) {
47175390be7dSMatthew G. Knepley       PetscCall(DMPlexGetPointDepth(dm, closure[cl], &pdepth));
47185390be7dSMatthew G. Knepley       PetscCall(DMLabelSetValue(label, closure[cl], pdepth));
47195390be7dSMatthew G. Knepley     }
47205390be7dSMatthew G. Knepley     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure));
47215390be7dSMatthew G. Knepley   }
47225390be7dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
47235390be7dSMatthew G. Knepley }
47245390be7dSMatthew G. Knepley 
47254e22dd4cSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *flg);
47264e22dd4cSMatthew G. Knepley 
47275dca41c3SJed Brown const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "zbox", "unknown", "DMPlexShape", "DM_SHAPE_", NULL};
47289318fe57SMatthew G. Knepley 
4729ce78bad3SBarry Smith static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems PetscOptionsObject, PetscBool *useCoordSpace, DM dm)
4730d71ae5a4SJacob Faibussowitsch {
47319318fe57SMatthew G. Knepley   DMPlexShape    shape   = DM_SHAPE_BOX;
47329318fe57SMatthew G. Knepley   DMPolytopeType cell    = DM_POLYTOPE_TRIANGLE;
47339318fe57SMatthew G. Knepley   PetscInt       dim     = 2;
4734b9da1bb3SMatthew G. Knepley   PetscBool      simplex = PETSC_TRUE, interpolate = PETSC_TRUE, orient = PETSC_FALSE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE;
4735d0812dedSMatthew G. Knepley   PetscBool      flg, flg2, fflg, strflg, bdfflg, nameflg;
47369318fe57SMatthew G. Knepley   MPI_Comm       comm;
4737ed5e4e85SVaclav Hapla   char           filename[PETSC_MAX_PATH_LEN]   = "<unspecified>";
4738ed5e4e85SVaclav Hapla   char           bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>";
4739ed5e4e85SVaclav Hapla   char           plexname[PETSC_MAX_PATH_LEN]   = "";
47404e22dd4cSMatthew G. Knepley   const char    *option;
47419318fe57SMatthew G. Knepley 
47429318fe57SMatthew G. Knepley   PetscFunctionBegin;
4743708be2fdSJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromOptions, dm, 0, 0, 0));
47449566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
47459318fe57SMatthew G. Knepley   /* TODO Turn this into a registration interface */
47469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg));
4747d0812dedSMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_plex_file_contents", "Contents of a file format in a string", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &strflg));
47489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg));
47499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg));
47509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL));
47519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL));
47529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg));
47539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0));
47549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg));
47559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg));
4756b9da1bb3SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_orient", "Orient the constructed mesh", "DMPlexOrient", orient, &orient, &flg));
47579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg));
47589566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2));
47599566063dSJacob Faibussowitsch   if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure));
47603f3e541fSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_adj", "Debug output level all adjacency computations", "", 0, &((DM_Plex *)dm->data)->printAdj, NULL, 0));
47619318fe57SMatthew G. Knepley 
476261a622f3SMatthew G. Knepley   switch (cell) {
476361a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT:
476461a622f3SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
476561a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
476661a622f3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
476761a622f3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
476861a622f3SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
4769d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_HEXAHEDRON:
4770d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_TRUE;
4771d71ae5a4SJacob Faibussowitsch     break;
4772d71ae5a4SJacob Faibussowitsch   default:
4773d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_FALSE;
4774d71ae5a4SJacob Faibussowitsch     break;
477561a622f3SMatthew G. Knepley   }
477661a622f3SMatthew G. Knepley 
47779318fe57SMatthew G. Knepley   if (fflg) {
47789318fe57SMatthew G. Knepley     DM          dmnew;
47791e4a82c4SMatthew G. Knepley     const char *name;
47809318fe57SMatthew G. Knepley 
47811e4a82c4SMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
47821e4a82c4SMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, nameflg ? plexname : name, interpolate, &dmnew));
47835de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
478469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
47859318fe57SMatthew G. Knepley   } else if (refDomain) {
47869566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell));
47879318fe57SMatthew G. Knepley   } else if (bdfflg) {
47889318fe57SMatthew G. Knepley     DM          bdm, dmnew;
47891e4a82c4SMatthew G. Knepley     const char *name;
47909318fe57SMatthew G. Knepley 
47911e4a82c4SMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
47921e4a82c4SMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, nameflg ? plexname : name, interpolate, &bdm));
47939566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_"));
47949566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(bdm));
47959566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew));
47969566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&bdm));
47975de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
479869d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
4799d0812dedSMatthew G. Knepley   } else if (strflg) {
4800d0812dedSMatthew G. Knepley     DM          dmnew;
4801d0812dedSMatthew G. Knepley     PetscViewer viewer;
4802d0812dedSMatthew G. Knepley     const char *contents;
4803d0812dedSMatthew G. Knepley     char       *strname;
4804d0812dedSMatthew G. Knepley     char        tmpdir[PETSC_MAX_PATH_LEN];
4805d0812dedSMatthew G. Knepley     char        tmpfilename[PETSC_MAX_PATH_LEN];
4806d0812dedSMatthew G. Knepley     char        name[PETSC_MAX_PATH_LEN];
4807d0812dedSMatthew G. Knepley     MPI_Comm    comm;
4808d0812dedSMatthew G. Knepley     PetscMPIInt rank;
4809d0812dedSMatthew G. Knepley 
4810d0812dedSMatthew G. Knepley     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4811d0812dedSMatthew G. Knepley     PetscCallMPI(MPI_Comm_rank(comm, &rank));
4812d0812dedSMatthew G. Knepley     PetscCall(PetscStrchr(filename, ':', &strname));
4813d0812dedSMatthew G. Knepley     PetscCheck(strname, comm, PETSC_ERR_ARG_WRONG, "File contents must have the form \"ext:string_name\", not %s", filename);
4814d0812dedSMatthew G. Knepley     strname[0] = '\0';
4815d0812dedSMatthew G. Knepley     ++strname;
4816d0812dedSMatthew G. Knepley     PetscCall(PetscDLSym(NULL, strname, (void **)&contents));
4817d0812dedSMatthew G. Knepley     PetscCheck(contents, comm, PETSC_ERR_ARG_WRONG, "Could not locate mesh string %s", strname);
4818d0812dedSMatthew G. Knepley     PetscCall(PetscGetTmp(comm, tmpdir, PETSC_MAX_PATH_LEN));
4819ed32af8cSMatthew G. Knepley     PetscCall(PetscStrlcat(tmpdir, "/meshXXXXXX", PETSC_MAX_PATH_LEN));
4820ed32af8cSMatthew G. Knepley     PetscCall(PetscMkdtemp(tmpdir));
4821ed32af8cSMatthew G. Knepley     PetscCall(PetscSNPrintf(tmpfilename, PETSC_MAX_PATH_LEN, "%s/mesh.%s", tmpdir, filename));
4822d0812dedSMatthew G. Knepley     PetscCall(PetscViewerASCIIOpen(comm, tmpfilename, &viewer));
4823d0812dedSMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", contents));
4824d0812dedSMatthew G. Knepley     PetscCall(PetscViewerDestroy(&viewer));
4825d0812dedSMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), tmpfilename, plexname, interpolate, &dmnew));
4826ed32af8cSMatthew G. Knepley     PetscCall(PetscRMTree(tmpdir));
4827d0812dedSMatthew G. Knepley     PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%s Mesh", strname));
4828d0812dedSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, name));
4829d0812dedSMatthew G. Knepley     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
4830d0812dedSMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
48319318fe57SMatthew G. Knepley   } else {
48329566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape]));
48339318fe57SMatthew G. Knepley     switch (shape) {
4834669647acSMatthew G. Knepley     case DM_SHAPE_BOX:
48355dca41c3SJed Brown     case DM_SHAPE_ZBOX:
4836669647acSMatthew G. Knepley     case DM_SHAPE_ANNULUS: {
48379318fe57SMatthew G. Knepley       PetscInt       faces[3]  = {0, 0, 0};
48389318fe57SMatthew G. Knepley       PetscReal      lower[3]  = {0, 0, 0};
48399318fe57SMatthew G. Knepley       PetscReal      upper[3]  = {1, 1, 1};
48409318fe57SMatthew G. Knepley       DMBoundaryType bdt[3]    = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
4841669647acSMatthew G. Knepley       PetscBool      isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE;
48429318fe57SMatthew G. Knepley       PetscInt       i, n;
48439318fe57SMatthew G. Knepley 
48449318fe57SMatthew G. Knepley       n = dim;
48459318fe57SMatthew G. Knepley       for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim);
48469566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
48479318fe57SMatthew G. Knepley       n = 3;
48489566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
484963a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
48509318fe57SMatthew G. Knepley       n = 3;
48519566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
485263a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
48539318fe57SMatthew G. Knepley       n = 3;
48549566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
485563a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
4856669647acSMatthew G. Knepley 
4857669647acSMatthew G. Knepley       PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented");
4858669647acSMatthew G. Knepley       if (isAnnular)
4859669647acSMatthew G. Knepley         for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC;
4860669647acSMatthew G. Knepley 
48619318fe57SMatthew G. Knepley       switch (cell) {
486261a622f3SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
48639566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt));
4864d410b0cfSMatthew G. Knepley         if (!interpolate) {
4865d410b0cfSMatthew G. Knepley           DM udm;
4866d410b0cfSMatthew G. Knepley 
48679566063dSJacob Faibussowitsch           PetscCall(DMPlexUninterpolate(dm, &udm));
486869d8a87bSksagiyam           PetscCall(DMPlexReplace_Internal(dm, &udm));
4869d410b0cfSMatthew G. Knepley         }
48709318fe57SMatthew G. Knepley         break;
4871d71ae5a4SJacob Faibussowitsch       default:
48725dca41c3SJed Brown         PetscCall(DMPlexCreateBoxMesh_Internal(dm, shape, dim, simplex, faces, lower, upper, bdt, interpolate));
4873d71ae5a4SJacob Faibussowitsch         break;
48749318fe57SMatthew G. Knepley       }
4875669647acSMatthew G. Knepley       if (isAnnular) {
4876669647acSMatthew G. Knepley         DM          cdm;
4877669647acSMatthew G. Knepley         PetscDS     cds;
4878669647acSMatthew G. Knepley         PetscScalar bounds[2] = {lower[0], upper[0]};
4879669647acSMatthew G. Knepley 
4880669647acSMatthew G. Knepley         // Fix coordinates for annular region
4881669647acSMatthew G. Knepley         PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL));
4882669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinatesLocal(dm, NULL));
4883669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinates(dm, NULL));
4884e65c294aSksagiyam         PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE));
4885669647acSMatthew G. Knepley         PetscCall(DMGetCoordinateDM(dm, &cdm));
4886669647acSMatthew G. Knepley         PetscCall(DMGetDS(cdm, &cds));
4887669647acSMatthew G. Knepley         PetscCall(PetscDSSetConstants(cds, 2, bounds));
4888669647acSMatthew G. Knepley         PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus));
4889669647acSMatthew G. Knepley       }
48909371c9d4SSatish Balay     } break;
48919371c9d4SSatish Balay     case DM_SHAPE_BOX_SURFACE: {
48929318fe57SMatthew G. Knepley       PetscInt  faces[3] = {0, 0, 0};
48939318fe57SMatthew G. Knepley       PetscReal lower[3] = {0, 0, 0};
48949318fe57SMatthew G. Knepley       PetscReal upper[3] = {1, 1, 1};
48959318fe57SMatthew G. Knepley       PetscInt  i, n;
48969318fe57SMatthew G. Knepley 
48979318fe57SMatthew G. Knepley       n = dim + 1;
48989318fe57SMatthew G. Knepley       for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1));
48999566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
49009318fe57SMatthew G. Knepley       n = 3;
49019566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
490263a3b9bcSJacob 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);
49039318fe57SMatthew G. Knepley       n = 3;
49049566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
490563a3b9bcSJacob 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);
49069566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate));
49079371c9d4SSatish Balay     } break;
49089371c9d4SSatish Balay     case DM_SHAPE_SPHERE: {
49099318fe57SMatthew G. Knepley       PetscReal R = 1.0;
49109318fe57SMatthew G. Knepley 
49119566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg));
49129566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R));
49139371c9d4SSatish Balay     } break;
49149371c9d4SSatish Balay     case DM_SHAPE_BALL: {
49159318fe57SMatthew G. Knepley       PetscReal R = 1.0;
49169318fe57SMatthew G. Knepley 
49179566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg));
49189566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R));
49199371c9d4SSatish Balay     } break;
49209371c9d4SSatish Balay     case DM_SHAPE_CYLINDER: {
49219318fe57SMatthew G. Knepley       DMBoundaryType bdt = DM_BOUNDARY_NONE;
49229318fe57SMatthew G. Knepley       PetscInt       Nw  = 6;
492349704ca5SMatthew G. Knepley       PetscInt       Nr  = 0;
49249318fe57SMatthew G. Knepley 
49259566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL));
49269566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL));
492749704ca5SMatthew G. Knepley       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_refine", "Number of refinements before projection", "", Nr, &Nr, NULL));
49289318fe57SMatthew G. Knepley       switch (cell) {
4929d71ae5a4SJacob Faibussowitsch       case DM_POLYTOPE_TRI_PRISM_TENSOR:
4930d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate));
4931d71ae5a4SJacob Faibussowitsch         break;
4932d71ae5a4SJacob Faibussowitsch       default:
493349704ca5SMatthew G. Knepley         PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt, Nr));
4934d71ae5a4SJacob Faibussowitsch         break;
49359318fe57SMatthew G. Knepley       }
49369371c9d4SSatish Balay     } break;
4937b7f5c055SJed Brown     case DM_SHAPE_SCHWARZ_P: // fallthrough
49389371c9d4SSatish Balay     case DM_SHAPE_GYROID: {
4939b7f5c055SJed Brown       PetscInt       extent[3] = {1, 1, 1}, refine = 0, layers = 0, three;
4940b7f5c055SJed Brown       PetscReal      thickness   = 0.;
4941b7f5c055SJed Brown       DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
4942b7f5c055SJed Brown       DMPlexTPSType  tps_type    = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID;
49431436d7faSJed Brown       PetscBool      tps_distribute;
49449566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL));
49459566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL));
49469566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL));
49479566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL));
49489566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL));
49499566063dSJacob Faibussowitsch       PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute));
49509566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL));
49519566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness));
49529371c9d4SSatish Balay     } break;
49539371c9d4SSatish Balay     case DM_SHAPE_DOUBLET: {
495405bd46c0SStefano Zampini       DM        dmnew;
495505bd46c0SStefano Zampini       PetscReal rl = 0.0;
495605bd46c0SStefano Zampini 
495705bd46c0SStefano Zampini       PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL));
495805bd46c0SStefano Zampini       PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew));
49595de52c6dSVaclav Hapla       PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
496069d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &dmnew));
49619371c9d4SSatish Balay     } break;
4962cfb853baSMatthew G. Knepley     case DM_SHAPE_HYPERCUBIC: {
49638d2ec52aSSatish Balay       PetscInt       *edges, overlap = 1;
4964cfb853baSMatthew G. Knepley       PetscReal      *lower, *upper;
4965cfb853baSMatthew G. Knepley       DMBoundaryType *bdt;
4966cfb853baSMatthew G. Knepley       PetscInt        n, d;
4967cfb853baSMatthew G. Knepley 
4968cfb853baSMatthew G. Knepley       *useCoordSpace = PETSC_FALSE;
4969cfb853baSMatthew G. Knepley       PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt));
4970cfb853baSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
4971cfb853baSMatthew G. Knepley         edges[d] = 1;
4972cfb853baSMatthew G. Knepley         lower[d] = 0.;
4973cfb853baSMatthew G. Knepley         upper[d] = 1.;
4974cfb853baSMatthew G. Knepley         bdt[d]   = DM_BOUNDARY_PERIODIC;
4975cfb853baSMatthew G. Knepley       }
4976cfb853baSMatthew G. Knepley       n = dim;
4977cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg));
4978cfb853baSMatthew G. Knepley       n = dim;
4979cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
4980cfb853baSMatthew 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);
4981cfb853baSMatthew G. Knepley       n = dim;
4982cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
4983cfb853baSMatthew 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);
4984cfb853baSMatthew G. Knepley       n = dim;
4985cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
4986cfb853baSMatthew 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);
49878d2ec52aSSatish Balay       PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", overlap, &overlap, NULL, 0));
49888d2ec52aSSatish Balay       PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, overlap, bdt));
4989cfb853baSMatthew G. Knepley       PetscCall(PetscFree4(edges, lower, upper, bdt));
4990cfb853baSMatthew G. Knepley     } break;
4991d71ae5a4SJacob Faibussowitsch     default:
4992d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]);
49939318fe57SMatthew G. Knepley     }
49949318fe57SMatthew G. Knepley   }
49959566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
499648a46eb9SPierre Jolivet   if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname));
4997b9da1bb3SMatthew G. Knepley   if (orient) PetscCall(DMPlexOrient(dm));
49984e22dd4cSMatthew G. Knepley   // Allow label creation
49994e22dd4cSMatthew G. Knepley   PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_label_", &option, NULL, &flg));
50004e22dd4cSMatthew G. Knepley   if (flg) {
50014e22dd4cSMatthew G. Knepley     DMLabel     label;
50024e22dd4cSMatthew G. Knepley     PetscInt    points[1024], n = 1024;
50034e22dd4cSMatthew G. Knepley     char        fulloption[PETSC_MAX_PATH_LEN];
50044e22dd4cSMatthew G. Knepley     const char *name = &option[14];
50054e22dd4cSMatthew G. Knepley 
50064e22dd4cSMatthew G. Knepley     PetscCall(DMCreateLabel(dm, name));
50074e22dd4cSMatthew G. Knepley     PetscCall(DMGetLabel(dm, name, &label));
50084e22dd4cSMatthew G. Knepley     fulloption[0] = '-';
50094e22dd4cSMatthew G. Knepley     fulloption[1] = 0;
50104e22dd4cSMatthew G. Knepley     PetscCall(PetscStrlcat(fulloption, option, PETSC_MAX_PATH_LEN));
50114e22dd4cSMatthew G. Knepley     PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, NULL));
50124e22dd4cSMatthew G. Knepley     for (PetscInt p = 0; p < n; ++p) PetscCall(DMLabelSetValue(label, points[p], 1));
50134e22dd4cSMatthew G. Knepley   }
5014dd0eeac9SMatthew G. Knepley   // Allow cohesive label creation
5015dd0eeac9SMatthew G. Knepley   //   Faces are input, completed, and all points are marked with their depth
5016dd0eeac9SMatthew G. Knepley   PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_cohesive_label_", &option, NULL, &flg));
5017dd0eeac9SMatthew G. Knepley   if (flg) {
5018dd0eeac9SMatthew G. Knepley     DMLabel   label;
5019dd0eeac9SMatthew G. Knepley     PetscInt  points[1024], n, pStart, pEnd, Nl = 1;
50205390be7dSMatthew G. Knepley     PetscBool noCreate = PETSC_FALSE;
5021dd0eeac9SMatthew G. Knepley     char      fulloption[PETSC_MAX_PATH_LEN];
5022dd0eeac9SMatthew G. Knepley     char      name[PETSC_MAX_PATH_LEN];
5023dd0eeac9SMatthew G. Knepley     size_t    len;
5024dd0eeac9SMatthew G. Knepley 
5025dd0eeac9SMatthew G. Knepley     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
5026dd0eeac9SMatthew G. Knepley     PetscCall(PetscStrncpy(name, &option[23], PETSC_MAX_PATH_LEN));
5027dd0eeac9SMatthew G. Knepley     PetscCall(PetscStrlen(name, &len));
5028dd0eeac9SMatthew G. Knepley     if (name[len - 1] == '0') Nl = 10;
5029dd0eeac9SMatthew G. Knepley     for (PetscInt l = 0; l < Nl; ++l) {
50306497c311SBarry Smith       if (l > 0) name[len - 1] = (char)('0' + l);
5031dd0eeac9SMatthew G. Knepley       fulloption[0] = 0;
5032dd0eeac9SMatthew G. Knepley       PetscCall(PetscStrlcat(fulloption, "-dm_plex_cohesive_label_", 32));
5033dd0eeac9SMatthew G. Knepley       PetscCall(PetscStrlcat(fulloption, name, PETSC_MAX_PATH_LEN - 32));
5034dd0eeac9SMatthew G. Knepley       n = 1024;
5035dd0eeac9SMatthew G. Knepley       PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, &flg));
5036dd0eeac9SMatthew G. Knepley       if (!flg) break;
50375390be7dSMatthew G. Knepley       PetscCall(DMHasLabel(dm, name, &noCreate));
50385390be7dSMatthew G. Knepley       if (noCreate) {
50395390be7dSMatthew G. Knepley         DMLabel         inlabel;
50405390be7dSMatthew G. Knepley         IS              pointIS;
50415390be7dSMatthew G. Knepley         const PetscInt *lpoints;
50425390be7dSMatthew G. Knepley         PetscInt        pdep, ln, inval = points[0];
50435390be7dSMatthew G. Knepley         char            newname[PETSC_MAX_PATH_LEN];
50445390be7dSMatthew G. Knepley 
50455390be7dSMatthew G. Knepley         PetscCheck(n == 1, comm, PETSC_ERR_ARG_WRONG, "Must specify a label value with this option");
50465390be7dSMatthew G. Knepley         PetscCall(DMGetLabel(dm, name, &inlabel));
50475390be7dSMatthew G. Knepley         PetscCall(DMLabelGetStratumIS(inlabel, inval, &pointIS));
50485390be7dSMatthew G. Knepley         PetscCall(ISGetLocalSize(pointIS, &ln));
50495390be7dSMatthew G. Knepley         PetscCall(ISGetIndices(pointIS, &lpoints));
50505390be7dSMatthew G. Knepley         PetscCall(DMPlexGetPointDepth(dm, lpoints[0], &pdep));
50515390be7dSMatthew G. Knepley         PetscCall(PetscSNPrintf(newname, PETSC_MAX_PATH_LEN, "%s%" PetscInt_FMT, name, points[0]));
50525390be7dSMatthew G. Knepley         PetscCall(DMCreateLabel(dm, newname));
50535390be7dSMatthew G. Knepley         PetscCall(DMGetLabel(dm, newname, &label));
50545390be7dSMatthew G. Knepley         if (!pdep) PetscCall(ProcessCohesiveLabel_Vertices(dm, label, inlabel, inval, ln, lpoints));
50555390be7dSMatthew G. Knepley         else PetscCall(ProcessCohesiveLabel_Faces(dm, label, ln, lpoints));
50565390be7dSMatthew G. Knepley         PetscCall(ISRestoreIndices(pointIS, &lpoints));
50575390be7dSMatthew G. Knepley         PetscCall(ISDestroy(&pointIS));
50585390be7dSMatthew G. Knepley       } else {
5059dd0eeac9SMatthew G. Knepley         PetscCall(DMCreateLabel(dm, name));
5060dd0eeac9SMatthew G. Knepley         PetscCall(DMGetLabel(dm, name, &label));
5061dd0eeac9SMatthew G. Knepley         if (pStart >= pEnd) n = 0;
50625390be7dSMatthew G. Knepley         PetscCall(ProcessCohesiveLabel_Faces(dm, label, n, points));
5063dd0eeac9SMatthew G. Knepley       }
5064dd0eeac9SMatthew G. Knepley       PetscCall(DMPlexOrientLabel(dm, label));
50650542aa8cSMatthew G. Knepley       PetscCall(DMPlexLabelCohesiveComplete(dm, label, NULL, 1, PETSC_FALSE, PETSC_FALSE, NULL));
5066dd0eeac9SMatthew G. Knepley     }
5067dd0eeac9SMatthew G. Knepley   }
50685390be7dSMatthew G. Knepley   PetscCall(DMViewFromOptions(dm, NULL, "-created_dm_view"));
5069708be2fdSJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromOptions, dm, 0, 0, 0));
50703ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50710a6ba040SMatthew G. Knepley }
50720a6ba040SMatthew G. Knepley 
5073ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems PetscOptionsObject)
5074d71ae5a4SJacob Faibussowitsch {
50750a6ba040SMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
50767f9d8d6cSVaclav Hapla   PetscBool flg, flg2;
50779318fe57SMatthew G. Knepley   char      bdLabel[PETSC_MAX_PATH_LEN];
5078adc21957SMatthew G. Knepley   char      method[PETSC_MAX_PATH_LEN];
50790a6ba040SMatthew G. Knepley 
50800a6ba040SMatthew G. Knepley   PetscFunctionBegin;
50810a6ba040SMatthew G. Knepley   /* Handle viewing */
50829566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL));
50835962854dSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level for all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0));
50845962854dSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fvm", "Debug output level for all fvm computations", "DMPlexSNESComputeResidualFVM", 0, &mesh->printFVM, NULL, 0));
50859566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL));
50869566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0));
5087f5867de0SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0));
5088a77a5016SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_project", "Debug output level all projection computations", "DMPlexProject", 0, &mesh->printProject, NULL, 0));
50899566063dSJacob Faibussowitsch   PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg));
50909566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscLogDefaultBegin());
50915e2c5519SMatthew G. Knepley   // Interpolation
50925e2c5519SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_interpolate_prefer_tensor", "When different orderings exist, prefer the tensor order", "DMPlexSetInterpolationPreferTensor", mesh->interpolatePreferTensor, &mesh->interpolatePreferTensor, NULL));
50939318fe57SMatthew G. Knepley   /* Labeling */
50949566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg));
50959566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel));
5096953fc75cSMatthew G. Knepley   /* Point Location */
50979566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL));
50980848f4b5SMatthew G. Knepley   /* Partitioning and distribution */
50999566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL));
5100d02c7345SMatthew G. Knepley   /* Reordering */
5101adc21957SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_reorder_section", "Compute point permutation for local section", "DMReorderSectionSetDefault", PETSC_FALSE, &flg2, &flg));
5102adc21957SMatthew G. Knepley   if (flg) PetscCall(DMReorderSectionSetDefault(dm, flg2 ? DM_REORDER_DEFAULT_TRUE : DM_REORDER_DEFAULT_FALSE));
5103adc21957SMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_reorder_section_type", "Reordering method for local section", "DMReorderSectionSetType", method, method, PETSC_MAX_PATH_LEN, &flg));
5104adc21957SMatthew G. Knepley   if (flg) PetscCall(DMReorderSectionSetType(dm, method));
51052e62ab5aSMatthew G. Knepley   /* Generation and remeshing */
51069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL));
510761f058f9SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_save_transform", "Save the transform producing this mesh", "DMAdapt", PETSC_FALSE, &mesh->saveTransform, NULL));
5108b29cfa1cSToby Isaac   /* Projection behavior */
5109d5b43468SJose E. Roman   PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0));
51109566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL));
5111f12cf164SMatthew G. Knepley   /* Checking structure */
5112f12cf164SMatthew G. Knepley   {
51137f9d8d6cSVaclav Hapla     PetscBool all = PETSC_FALSE;
5114f12cf164SMatthew G. Knepley 
51157f9d8d6cSVaclav Hapla     PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL));
51167f9d8d6cSVaclav Hapla     if (all) {
51177f9d8d6cSVaclav Hapla       PetscCall(DMPlexCheck(dm));
51187f9d8d6cSVaclav Hapla     } else {
51199566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2));
51207f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm));
51219566063dSJacob 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));
51227f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0));
51239566063dSJacob 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));
51247f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0));
51259566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2));
51267f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm));
51279566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2));
5128d7d32a9aSMatthew G. Knepley       if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
51299566063dSJacob 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));
51307f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm));
51317f9d8d6cSVaclav Hapla     }
51329566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2));
51339566063dSJacob Faibussowitsch     if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE));
5134f12cf164SMatthew G. Knepley   }
51359318fe57SMatthew G. Knepley   {
51369318fe57SMatthew G. Knepley     PetscReal scale = 1.0;
51374f3833eaSMatthew G. Knepley 
51389566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg));
51399318fe57SMatthew G. Knepley     if (flg) {
51409318fe57SMatthew G. Knepley       Vec coordinates, coordinatesLocal;
51419318fe57SMatthew G. Knepley 
51429566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinates(dm, &coordinates));
51439566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
51449566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinates, scale));
51459566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinatesLocal, scale));
51469318fe57SMatthew G. Knepley     }
51479318fe57SMatthew G. Knepley   }
51489566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner));
51493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
515068d4fef7SMatthew G. Knepley }
515168d4fef7SMatthew G. Knepley 
5152ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems PetscOptionsObject, PetscInt *overlap)
5153d71ae5a4SJacob Faibussowitsch {
5154c506a872SMatthew G. Knepley   PetscInt  numOvLabels = 16, numOvExLabels = 16;
5155c506a872SMatthew G. Knepley   char     *ovLabelNames[16], *ovExLabelNames[16];
5156c506a872SMatthew G. Knepley   PetscInt  numOvValues = 16, numOvExValues = 16, l;
5157c506a872SMatthew G. Knepley   PetscBool flg;
5158c506a872SMatthew G. Knepley 
5159c506a872SMatthew G. Knepley   PetscFunctionBegin;
5160c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0));
5161c506a872SMatthew G. Knepley   PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg));
5162c506a872SMatthew G. Knepley   if (!flg) numOvLabels = 0;
5163c506a872SMatthew G. Knepley   if (numOvLabels) {
5164c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvLabels = numOvLabels;
5165c506a872SMatthew G. Knepley     for (l = 0; l < numOvLabels; ++l) {
5166c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l]));
5167c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]);
5168c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovLabelNames[l]));
5169c506a872SMatthew G. Knepley     }
5170c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg));
5171c506a872SMatthew G. Knepley     if (!flg) numOvValues = 0;
5172c506a872SMatthew 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);
5173c506a872SMatthew G. Knepley 
5174c506a872SMatthew G. Knepley     PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg));
5175c506a872SMatthew G. Knepley     if (!flg) numOvExLabels = 0;
5176c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels;
5177c506a872SMatthew G. Knepley     for (l = 0; l < numOvExLabels; ++l) {
5178c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l]));
5179c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]);
5180c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovExLabelNames[l]));
5181c506a872SMatthew G. Knepley     }
5182c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg));
5183c506a872SMatthew G. Knepley     if (!flg) numOvExValues = 0;
5184c506a872SMatthew 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);
5185c506a872SMatthew G. Knepley   }
51863ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5187c506a872SMatthew G. Knepley }
5188c506a872SMatthew G. Knepley 
5189ce78bad3SBarry Smith static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems PetscOptionsObject)
5190d71ae5a4SJacob Faibussowitsch {
5191bdf63967SMatthew G. Knepley   PetscFunctionList    ordlist;
5192bdf63967SMatthew G. Knepley   char                 oname[256];
51934e22dd4cSMatthew G. Knepley   char                 sublabelname[PETSC_MAX_PATH_LEN] = "";
5194adc21957SMatthew G. Knepley   DMReorderDefaultFlag reorder;
5195d410b0cfSMatthew G. Knepley   PetscReal            volume    = -1.0;
51969318fe57SMatthew G. Knepley   PetscInt             prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim;
5197530e699aSMatthew 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;
519868d4fef7SMatthew G. Knepley 
519968d4fef7SMatthew G. Knepley   PetscFunctionBegin;
5200d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options");
5201dd4c3f67SMatthew G. Knepley   if (dm->cloneOpts) goto non_refine;
52029318fe57SMatthew G. Knepley   /* Handle automatic creation */
52039566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
5204530e699aSMatthew G. Knepley   if (dim < 0) PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));
52056bc1bd01Sksagiyam   PetscCall(DMGetDimension(dm, &dim));
5206d89e6e46SMatthew G. Knepley   /* Handle interpolation before distribution */
52079566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg));
5208d89e6e46SMatthew G. Knepley   if (flg) {
5209d89e6e46SMatthew G. Knepley     DMPlexInterpolatedFlag interpolated;
5210d89e6e46SMatthew G. Knepley 
52119566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpolated));
5212d89e6e46SMatthew G. Knepley     if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) {
5213d89e6e46SMatthew G. Knepley       DM udm;
5214d89e6e46SMatthew G. Knepley 
52159566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(dm, &udm));
521669d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &udm));
5217d89e6e46SMatthew G. Knepley     } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) {
5218d89e6e46SMatthew G. Knepley       DM idm;
5219d89e6e46SMatthew G. Knepley 
52209566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(dm, &idm));
522169d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &idm));
5222d89e6e46SMatthew G. Knepley     }
5223d89e6e46SMatthew G. Knepley   }
52244e22dd4cSMatthew G. Knepley   // Handle submesh selection before distribution
52254e22dd4cSMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_plex_submesh", "Label to use for submesh selection", "", sublabelname, sublabelname, PETSC_MAX_PATH_LEN, &flg));
52264e22dd4cSMatthew G. Knepley   if (flg) {
52274e22dd4cSMatthew G. Knepley     DM              subdm;
52284e22dd4cSMatthew G. Knepley     DMLabel         label;
52294e22dd4cSMatthew G. Knepley     IS              valueIS, pointIS;
52304e22dd4cSMatthew G. Knepley     const PetscInt *values, *points;
52314e22dd4cSMatthew G. Knepley     PetscBool       markedFaces = PETSC_FALSE;
52324e22dd4cSMatthew G. Knepley     PetscInt        Nv, value, Np;
52334e22dd4cSMatthew G. Knepley 
52344e22dd4cSMatthew G. Knepley     PetscCall(DMGetLabel(dm, sublabelname, &label));
52354e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetNumValues(label, &Nv));
52364e22dd4cSMatthew 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);
52374e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetValueIS(label, &valueIS));
52384e22dd4cSMatthew G. Knepley     PetscCall(ISGetIndices(valueIS, &values));
52394e22dd4cSMatthew G. Knepley     value = values[0];
52404e22dd4cSMatthew G. Knepley     PetscCall(ISRestoreIndices(valueIS, &values));
52414e22dd4cSMatthew G. Knepley     PetscCall(ISDestroy(&valueIS));
52424e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetStratumSize(label, value, &Np));
52434e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetStratumIS(label, value, &pointIS));
52444e22dd4cSMatthew G. Knepley     PetscCall(ISGetIndices(pointIS, &points));
52454e22dd4cSMatthew G. Knepley     for (PetscInt p = 0; p < Np; ++p) {
52464e22dd4cSMatthew G. Knepley       PetscInt pdepth;
52474e22dd4cSMatthew G. Knepley 
52484e22dd4cSMatthew G. Knepley       PetscCall(DMPlexGetPointDepth(dm, points[p], &pdepth));
52494e22dd4cSMatthew G. Knepley       if (pdepth) {
52504e22dd4cSMatthew G. Knepley         markedFaces = PETSC_TRUE;
52514e22dd4cSMatthew G. Knepley         break;
52524e22dd4cSMatthew G. Knepley       }
52534e22dd4cSMatthew G. Knepley     }
52544e22dd4cSMatthew G. Knepley     PetscCall(ISRestoreIndices(pointIS, &points));
52554e22dd4cSMatthew G. Knepley     PetscCall(ISDestroy(&pointIS));
52564e22dd4cSMatthew G. Knepley     PetscCall(DMPlexCreateSubmesh(dm, label, value, markedFaces, &subdm));
52574e22dd4cSMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &subdm));
52584e22dd4cSMatthew G. Knepley     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
52594e22dd4cSMatthew G. Knepley   }
52609b44eab4SMatthew G. Knepley   /* Handle DMPlex refinement before distribution */
52619566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig));
52629566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0));
52639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
52649566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg));
52659566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform));
52669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg));
52679318fe57SMatthew G. Knepley   if (flg) {
52689566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE));
52699566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(dm, volume));
52709318fe57SMatthew G. Knepley     prerefine = PetscMax(prerefine, 1);
52719318fe57SMatthew G. Knepley   }
5272b23db253SStefano Zampini   if (prerefine) PetscCall(DMLocalizeCoordinates(dm));
52739b44eab4SMatthew G. Knepley   for (r = 0; r < prerefine; ++r) {
52749b44eab4SMatthew G. Knepley     DM            rdm;
52752192575eSBarry Smith     PetscPointFn *coordFunc;
52769b44eab4SMatthew G. Knepley 
5277509b31aaSMatthew G. Knepley     PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc));
5278dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
52799566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
528069d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &rdm));
5281dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
528261a622f3SMatthew G. Knepley     if (coordFunc && remap) {
52839566063dSJacob Faibussowitsch       PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
5284509b31aaSMatthew G. Knepley       PetscCall(DMPlexSetCoordinateMap(dm, coordFunc));
52859b44eab4SMatthew G. Knepley     }
52869b44eab4SMatthew G. Knepley   }
52879566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig));
52889318fe57SMatthew G. Knepley   /* Handle DMPlex extrusion before distribution */
52899566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0));
52909318fe57SMatthew G. Knepley   if (extLayers) {
52919318fe57SMatthew G. Knepley     DM edm;
52929318fe57SMatthew G. Knepley 
52939566063dSJacob Faibussowitsch     PetscCall(DMExtrude(dm, extLayers, &edm));
529469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
5295509b31aaSMatthew G. Knepley     PetscCall(DMPlexSetCoordinateMap(dm, NULL));
5296dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
5297d410b0cfSMatthew G. Knepley     extLayers = 0;
52985e17fc22SAidan Hamilton     PetscCall(DMGetDimension(dm, &dim));
52999318fe57SMatthew G. Knepley   }
5300bdf63967SMatthew G. Knepley   /* Handle DMPlex reordering before distribution */
53016bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dm, &reorder));
53029566063dSJacob Faibussowitsch   PetscCall(MatGetOrderingList(&ordlist));
53036bc1bd01Sksagiyam   PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname)));
53049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg));
5305adc21957SMatthew G. Knepley   if (reorder == DM_REORDER_DEFAULT_TRUE || flg) {
5306bdf63967SMatthew G. Knepley     DM pdm;
5307bdf63967SMatthew G. Knepley     IS perm;
5308bdf63967SMatthew G. Knepley 
53099566063dSJacob Faibussowitsch     PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm));
53109566063dSJacob Faibussowitsch     PetscCall(DMPlexPermute(dm, perm, &pdm));
53119566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&perm));
531269d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &pdm));
5313dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
5314bdf63967SMatthew G. Knepley   }
53159b44eab4SMatthew G. Knepley   /* Handle DMPlex distribution */
53169566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dm, &distribute));
5317c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL));
5318a286e215SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute_save_sf", "Flag to save the migration SF", "DMPlexSetMigrationSF", saveSF, &saveSF, NULL));
5319dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap));
53209b44eab4SMatthew G. Knepley   if (distribute) {
53219b44eab4SMatthew G. Knepley     DM               pdm = NULL;
53229b44eab4SMatthew G. Knepley     PetscPartitioner part;
5323a286e215SMatthew G. Knepley     PetscSF          sfMigration;
53249566ead2SJames Wright     PetscBool        use_partition_balance;
53259b44eab4SMatthew G. Knepley 
53269566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
53279566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
53289566ead2SJames Wright     PetscCall(DMPlexGetPartitionBalance(dm, &use_partition_balance));
53299566ead2SJames 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));
53309566ead2SJames Wright     if (flg) PetscCall(DMPlexSetPartitionBalance(dm, use_partition_balance));
5331a286e215SMatthew G. Knepley     PetscCall(DMPlexDistribute(dm, overlap, &sfMigration, &pdm));
53325d2873a6SJames Wright     if (pdm) {
53335d2873a6SJames Wright       // Delete the local section to force the existing one to be rebuilt with the distributed DM
53345d2873a6SJames Wright       PetscCall(DMSetLocalSection(dm, pdm->localSection));
53355d2873a6SJames Wright       PetscCall(DMPlexReplace_Internal(dm, &pdm));
53365d2873a6SJames Wright     }
5337a286e215SMatthew G. Knepley     if (saveSF) PetscCall(DMPlexSetMigrationSF(dm, sfMigration));
5338a286e215SMatthew G. Knepley     PetscCall(PetscSFDestroy(&sfMigration));
53399b44eab4SMatthew G. Knepley   }
53404054ae39SJames Wright 
53414054ae39SJames Wright   {
53424054ae39SJames Wright     PetscBool useBoxLabel = PETSC_FALSE;
53434054ae39SJames Wright     PetscCall(PetscOptionsBool("-dm_plex_box_label", "Create 'Face Sets' assuming boundary faces align with cartesian directions", "DMCreate", useBoxLabel, &useBoxLabel, NULL));
5344d7d2d1d2SJames Wright     if (useBoxLabel) {
5345d7d2d1d2SJames Wright       PetscInt       n      = 3;
5346d7d2d1d2SJames Wright       DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
5347d7d2d1d2SJames Wright 
5348d7d2d1d2SJames Wright       PetscCall(PetscOptionsEnumArray("-dm_plex_box_label_bd", "Boundary type for each dimension when using -dm_plex_box_label", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
5349d7d2d1d2SJames 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);
5350d7d2d1d2SJames Wright       PetscCall(DMPlexSetBoxLabel_Internal(dm, bdt));
5351d7d2d1d2SJames Wright     }
53524054ae39SJames Wright   }
5353d2b2dc1eSMatthew G. Knepley   /* Must check CEED options before creating function space for coordinates */
5354d2b2dc1eSMatthew G. Knepley   {
5355d2b2dc1eSMatthew G. Knepley     PetscBool useCeed = PETSC_FALSE, flg;
5356d2b2dc1eSMatthew G. Knepley 
5357d2b2dc1eSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_plex_use_ceed", "Use LibCEED as the FEM backend", "DMPlexSetUseCeed", useCeed, &useCeed, &flg));
5358d2b2dc1eSMatthew G. Knepley     if (flg) PetscCall(DMPlexSetUseCeed(dm, useCeed));
5359d2b2dc1eSMatthew G. Knepley   }
53609318fe57SMatthew G. Knepley   /* Create coordinate space */
5361530e699aSMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, NULL));
5362530e699aSMatthew G. Knepley   if (coordSpace) {
5363e44f6aebSMatthew G. Knepley     PetscInt  degree = 1, deg;
53645515ebd3SMatthew G. Knepley     PetscInt  height = 0;
53655515ebd3SMatthew G. Knepley     DM        cdm;
5366530e699aSMatthew G. Knepley     PetscBool localize = PETSC_TRUE, sparseLocalize = PETSC_TRUE;
53679318fe57SMatthew G. Knepley 
53689566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, &degree, NULL));
5369e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDegree_Internal(dm, &deg));
5370e65c294aSksagiyam     if (coordSpace && deg <= 1) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_FALSE, PETSC_TRUE));
53715515ebd3SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
5372530e699aSMatthew G. Knepley     if (!coordSpace) {
537361a622f3SMatthew G. Knepley       PetscDS      cds;
537461a622f3SMatthew G. Knepley       PetscObject  obj;
537561a622f3SMatthew G. Knepley       PetscClassId id;
537661a622f3SMatthew G. Knepley 
53779566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdm, &cds));
53789566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
53799566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
538061a622f3SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
538161a622f3SMatthew G. Knepley         PetscContainer dummy;
538261a622f3SMatthew G. Knepley 
53839566063dSJacob Faibussowitsch         PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy));
53849566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates"));
53859566063dSJacob Faibussowitsch         PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy));
53869566063dSJacob Faibussowitsch         PetscCall(PetscContainerDestroy(&dummy));
53879566063dSJacob Faibussowitsch         PetscCall(DMClearDS(cdm));
538861a622f3SMatthew G. Knepley       }
5389509b31aaSMatthew G. Knepley       PetscCall(DMPlexSetCoordinateMap(dm, NULL));
539061a622f3SMatthew G. Knepley     }
5391c3db174cSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_localize", "Localize mesh coordinates", "", localize, &localize, NULL));
5392c3db174cSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "DMSetSparseLocalize", sparseLocalize, &sparseLocalize, &flg));
5393c3db174cSMatthew G. Knepley     if (flg) PetscCall(DMSetSparseLocalize(dm, sparseLocalize));
53945515ebd3SMatthew G. Knepley     PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg));
53955515ebd3SMatthew G. Knepley     if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height));
5396c3db174cSMatthew G. Knepley     if (localize) PetscCall(DMLocalizeCoordinates(dm));
53979318fe57SMatthew G. Knepley   }
539868d4fef7SMatthew G. Knepley   /* Handle DMPlex refinement */
539961a622f3SMatthew G. Knepley   remap = PETSC_TRUE;
54009566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0));
54019566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
54029566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0));
54039566063dSJacob Faibussowitsch   if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
540468d4fef7SMatthew G. Knepley   if (refine && isHierarchy) {
5405acdc6f61SToby Isaac     DM *dms, coarseDM;
540668d4fef7SMatthew G. Knepley 
54079566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &coarseDM));
54089566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarseDM));
54099566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(refine, &dms));
54109566063dSJacob Faibussowitsch     PetscCall(DMRefineHierarchy(dm, refine, dms));
541168d4fef7SMatthew G. Knepley     /* Total hack since we do not pass in a pointer */
54129566063dSJacob Faibussowitsch     PetscCall(DMPlexSwap_Static(dm, dms[refine - 1]));
541368d4fef7SMatthew G. Knepley     if (refine == 1) {
54149566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[0]));
54159566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
541668d4fef7SMatthew G. Knepley     } else {
54179566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[refine - 2]));
54189566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
54199566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1]));
54209566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE));
542168d4fef7SMatthew G. Knepley     }
54229566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM));
54239566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coarseDM));
542468d4fef7SMatthew G. Knepley     /* Free DMs */
542568d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
5426dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
54279566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
542868d4fef7SMatthew G. Knepley     }
54299566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
543068d4fef7SMatthew G. Knepley   } else {
543168d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
54329318fe57SMatthew G. Knepley       DM            rdm;
54332192575eSBarry Smith       PetscPointFn *coordFunc;
543468d4fef7SMatthew G. Knepley 
5435dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
54369566063dSJacob Faibussowitsch       PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
543768d4fef7SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
543869d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
5439dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
54403674be70SMatthew G. Knepley       PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc));
544161a622f3SMatthew G. Knepley       if (coordFunc && remap) {
54429566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
5443509b31aaSMatthew G. Knepley         PetscCall(DMPlexSetCoordinateMap(dm, coordFunc));
544451a74b61SMatthew G. Knepley       }
544568d4fef7SMatthew G. Knepley     }
544668d4fef7SMatthew G. Knepley   }
54473cf6fe12SMatthew G. Knepley   /* Handle DMPlex coarsening */
54489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0));
54499566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0));
5450b653a561SMatthew G. Knepley   if (coarsen && isHierarchy) {
5451b653a561SMatthew G. Knepley     DM *dms;
5452b653a561SMatthew G. Knepley 
54539566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coarsen, &dms));
54549566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHierarchy(dm, coarsen, dms));
5455b653a561SMatthew G. Knepley     /* Free DMs */
5456b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
5457dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
54589566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
5459b653a561SMatthew G. Knepley     }
54609566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
5461b653a561SMatthew G. Knepley   } else {
5462b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
54639318fe57SMatthew G. Knepley       DM            cdm;
54642192575eSBarry Smith       PetscPointFn *coordFunc;
54653cf6fe12SMatthew G. Knepley 
5466509b31aaSMatthew G. Knepley       PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc));
5467dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
54689566063dSJacob Faibussowitsch       PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm));
54693cf6fe12SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
547069d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &cdm));
5471dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
54729318fe57SMatthew G. Knepley       if (coordFunc) {
54739566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
5474509b31aaSMatthew G. Knepley         PetscCall(DMPlexSetCoordinateMap(dm, coordFunc));
54759318fe57SMatthew G. Knepley       }
54763cf6fe12SMatthew G. Knepley     }
5477b653a561SMatthew G. Knepley   }
5478be664eb1SMatthew G. Knepley   // Handle coordinate remapping
5479be664eb1SMatthew G. Knepley   remap = PETSC_FALSE;
5480be664eb1SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_coord_remap", "Flag to control coordinate remapping", "", remap, &remap, NULL));
5481be664eb1SMatthew G. Knepley   if (remap) {
5482be664eb1SMatthew G. Knepley     DMPlexCoordMap map     = DM_COORD_MAP_NONE;
54832192575eSBarry Smith     PetscPointFn  *mapFunc = NULL;
5484be664eb1SMatthew G. Knepley     PetscScalar    params[16];
5485f45b553cSPierre Jolivet     PetscInt       Np = PETSC_STATIC_ARRAY_LENGTH(params), cdim;
5486be664eb1SMatthew G. Knepley     MPI_Comm       comm;
5487be664eb1SMatthew G. Knepley 
5488be664eb1SMatthew G. Knepley     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5489be664eb1SMatthew G. Knepley     PetscCall(DMGetCoordinateDim(dm, &cdim));
5490be664eb1SMatthew G. Knepley     PetscCall(PetscOptionsScalarArray("-dm_coord_map_params", "Parameters for the coordinate remapping", "", params, &Np, &flg));
5491be664eb1SMatthew G. Knepley     if (!flg) Np = 0;
5492be664eb1SMatthew G. Knepley     // TODO Allow user to pass a map function by name
5493be664eb1SMatthew G. Knepley     PetscCall(PetscOptionsEnum("-dm_coord_map", "Coordinate mapping for built-in mesh", "", DMPlexCoordMaps, (PetscEnum)map, (PetscEnum *)&map, &flg));
5494be664eb1SMatthew G. Knepley     if (flg) {
5495be664eb1SMatthew G. Knepley       switch (map) {
5496be664eb1SMatthew G. Knepley       case DM_COORD_MAP_NONE:
5497be664eb1SMatthew G. Knepley         mapFunc = coordMap_identity;
5498be664eb1SMatthew G. Knepley         break;
5499be664eb1SMatthew G. Knepley       case DM_COORD_MAP_SHEAR:
5500be664eb1SMatthew G. Knepley         mapFunc = coordMap_shear;
5501be664eb1SMatthew G. Knepley         if (!Np) {
5502be664eb1SMatthew G. Knepley           Np        = cdim + 1;
5503be664eb1SMatthew G. Knepley           params[0] = 0;
5504be664eb1SMatthew G. Knepley           for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0;
5505be664eb1SMatthew G. Knepley         }
5506be664eb1SMatthew 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);
5507be664eb1SMatthew G. Knepley         break;
5508be664eb1SMatthew G. Knepley       case DM_COORD_MAP_FLARE:
5509be664eb1SMatthew G. Knepley         mapFunc = coordMap_flare;
5510be664eb1SMatthew G. Knepley         if (!Np) {
5511be664eb1SMatthew G. Knepley           Np        = cdim + 1;
5512be664eb1SMatthew G. Knepley           params[0] = 0;
5513be664eb1SMatthew G. Knepley           for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0;
5514be664eb1SMatthew G. Knepley         }
5515be664eb1SMatthew 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);
5516be664eb1SMatthew G. Knepley         break;
5517be664eb1SMatthew G. Knepley       case DM_COORD_MAP_ANNULUS:
5518be664eb1SMatthew G. Knepley         mapFunc = coordMap_annulus;
5519be664eb1SMatthew G. Knepley         if (!Np) {
5520be664eb1SMatthew G. Knepley           Np        = 2;
5521be664eb1SMatthew G. Knepley           params[0] = 1.;
5522be664eb1SMatthew G. Knepley           params[1] = 2.;
5523be664eb1SMatthew G. Knepley         }
5524be664eb1SMatthew G. Knepley         PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The annulus coordinate map must have 2 parameters, not %" PetscInt_FMT, Np);
5525be664eb1SMatthew G. Knepley         break;
5526be664eb1SMatthew G. Knepley       case DM_COORD_MAP_SHELL:
5527be664eb1SMatthew G. Knepley         mapFunc = coordMap_shell;
5528be664eb1SMatthew G. Knepley         if (!Np) {
5529be664eb1SMatthew G. Knepley           Np        = 2;
5530be664eb1SMatthew G. Knepley           params[0] = 1.;
5531be664eb1SMatthew G. Knepley           params[1] = 2.;
5532be664eb1SMatthew G. Knepley         }
5533be664eb1SMatthew G. Knepley         PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The spherical shell coordinate map must have 2 parameters, not %" PetscInt_FMT, Np);
5534be664eb1SMatthew G. Knepley         break;
5535530e699aSMatthew G. Knepley       case DM_COORD_MAP_SINUSOID:
5536530e699aSMatthew G. Knepley         mapFunc = coordMap_sinusoid;
5537530e699aSMatthew G. Knepley         if (!Np) {
5538530e699aSMatthew G. Knepley           Np        = 3;
5539530e699aSMatthew G. Knepley           params[0] = 1.;
5540530e699aSMatthew G. Knepley           params[1] = 1.;
5541530e699aSMatthew G. Knepley           params[2] = 1.;
5542530e699aSMatthew G. Knepley         }
5543530e699aSMatthew G. Knepley         PetscCheck(Np == 3, comm, PETSC_ERR_ARG_WRONG, "The sinusoidal coordinate map must have 3 parameters, not %" PetscInt_FMT, Np);
5544530e699aSMatthew G. Knepley         break;
5545be664eb1SMatthew G. Knepley       default:
5546be664eb1SMatthew G. Knepley         mapFunc = coordMap_identity;
5547be664eb1SMatthew G. Knepley       }
5548be664eb1SMatthew G. Knepley     }
5549be664eb1SMatthew G. Knepley     if (Np) {
5550be664eb1SMatthew G. Knepley       DM      cdm;
5551be664eb1SMatthew G. Knepley       PetscDS cds;
5552be664eb1SMatthew G. Knepley 
5553be664eb1SMatthew G. Knepley       PetscCall(DMGetCoordinateDM(dm, &cdm));
5554be664eb1SMatthew G. Knepley       PetscCall(DMGetDS(cdm, &cds));
5555be664eb1SMatthew G. Knepley       PetscCall(PetscDSSetConstants(cds, Np, params));
5556be664eb1SMatthew G. Knepley     }
5557be664eb1SMatthew G. Knepley     PetscCall(DMPlexRemapGeometry(dm, 0.0, mapFunc));
5558be664eb1SMatthew G. Knepley   }
5559909dfd52SMatthew G. Knepley   /* Handle ghost cells */
55609566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL));
5561909dfd52SMatthew G. Knepley   if (ghostCells) {
5562909dfd52SMatthew G. Knepley     DM   gdm;
5563909dfd52SMatthew G. Knepley     char lname[PETSC_MAX_PATH_LEN];
5564909dfd52SMatthew G. Knepley 
5565909dfd52SMatthew G. Knepley     lname[0] = '\0';
55669566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg));
55679566063dSJacob Faibussowitsch     PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm));
556869d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &gdm));
5569909dfd52SMatthew G. Knepley   }
55706913077dSMatthew G. Knepley   /* Handle 1D order */
5571adc21957SMatthew G. Knepley   if (reorder != DM_REORDER_DEFAULT_FALSE && dim == 1) {
55726913077dSMatthew G. Knepley     DM           cdm, rdm;
55736913077dSMatthew G. Knepley     PetscDS      cds;
55746913077dSMatthew G. Knepley     PetscObject  obj;
55756913077dSMatthew G. Knepley     PetscClassId id = PETSC_OBJECT_CLASSID;
55766913077dSMatthew G. Knepley     IS           perm;
55776bc1bd01Sksagiyam     PetscInt     Nf;
55786913077dSMatthew G. Knepley     PetscBool    distributed;
55796913077dSMatthew G. Knepley 
55809566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(dm, &distributed));
55819566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
55829566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
55839566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(cds, &Nf));
55846913077dSMatthew G. Knepley     if (Nf) {
55859566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
55869566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
55876913077dSMatthew G. Knepley     }
55886bc1bd01Sksagiyam     if (!distributed && id != PETSCFE_CLASSID) {
55899566063dSJacob Faibussowitsch       PetscCall(DMPlexGetOrdering1D(dm, &perm));
55909566063dSJacob Faibussowitsch       PetscCall(DMPlexPermute(dm, perm, &rdm));
559169d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
55929566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&perm));
55936913077dSMatthew G. Knepley     }
55946913077dSMatthew G. Knepley   }
55953cf6fe12SMatthew G. Knepley /* Handle */
5596dd4c3f67SMatthew G. Knepley non_refine:
5597dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
559822d6dc08SStefano Zampini   char    *phases[16];
559922d6dc08SStefano Zampini   PetscInt Nphases = 16;
560022d6dc08SStefano Zampini   PetscCall(PetscOptionsStringArray("-dm_plex_option_phases", "Option phase prefixes", "DMSetFromOptions", phases, &Nphases, &flg));
5601d0609cedSBarry Smith   PetscOptionsHeadEnd();
560222d6dc08SStefano Zampini 
560322d6dc08SStefano Zampini   // Phases
560422d6dc08SStefano Zampini   if (flg) {
5605530e699aSMatthew G. Knepley     DM          cdm;
5606530e699aSMatthew G. Knepley     char       *oldPrefix, *oldCoordPrefix;
5607530e699aSMatthew G. Knepley     const char *tmp;
560822d6dc08SStefano Zampini 
5609530e699aSMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
5610530e699aSMatthew G. Knepley     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &tmp));
5611530e699aSMatthew G. Knepley     PetscCall(PetscStrallocpy(tmp, &oldPrefix));
5612530e699aSMatthew G. Knepley     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)cdm, &tmp));
5613530e699aSMatthew G. Knepley     PetscCall(PetscStrallocpy(tmp, &oldCoordPrefix));
561422d6dc08SStefano Zampini     for (PetscInt ph = 0; ph < Nphases; ++ph) {
561522d6dc08SStefano Zampini       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, phases[ph]));
5616530e699aSMatthew G. Knepley       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)cdm, phases[ph]));
561722d6dc08SStefano Zampini       PetscCall(PetscInfo(dm, "Options phase %s for DM %s\n", phases[ph], dm->hdr.name));
561822d6dc08SStefano Zampini       PetscCall(DMSetFromOptions(dm));
561922d6dc08SStefano Zampini       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix));
5620530e699aSMatthew G. Knepley       PetscCall(DMGetCoordinateDM(dm, &cdm));
5621530e699aSMatthew G. Knepley       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)cdm, oldCoordPrefix));
562222d6dc08SStefano Zampini       PetscCall(PetscFree(phases[ph]));
562322d6dc08SStefano Zampini     }
5624530e699aSMatthew G. Knepley     PetscCall(PetscFree(oldPrefix));
5625530e699aSMatthew G. Knepley     PetscCall(PetscFree(oldCoordPrefix));
562622d6dc08SStefano Zampini   }
56273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
56280a6ba040SMatthew G. Knepley }
56290a6ba040SMatthew G. Knepley 
5630d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec)
5631d71ae5a4SJacob Faibussowitsch {
5632552f7358SJed Brown   PetscFunctionBegin;
56339566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector_Section_Private(dm, vec));
56349566063dSJacob Faibussowitsch   /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
56359566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex));
56369566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native));
56379566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex));
56389566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native));
56393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5640552f7358SJed Brown }
5641552f7358SJed Brown 
5642d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec)
5643d71ae5a4SJacob Faibussowitsch {
5644552f7358SJed Brown   PetscFunctionBegin;
56459566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector_Section_Private(dm, vec));
56469566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local));
56479566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local));
56483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5649552f7358SJed Brown }
5650552f7358SJed Brown 
5651d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
5652d71ae5a4SJacob Faibussowitsch {
5653793f3fe5SMatthew G. Knepley   PetscInt depth, d;
5654793f3fe5SMatthew G. Knepley 
5655793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
56569566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
5657793f3fe5SMatthew G. Knepley   if (depth == 1) {
56589566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &d));
56599566063dSJacob Faibussowitsch     if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
56609566063dSJacob Faibussowitsch     else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd));
56619371c9d4SSatish Balay     else {
56629371c9d4SSatish Balay       *pStart = 0;
56639371c9d4SSatish Balay       *pEnd   = 0;
56649371c9d4SSatish Balay     }
5665793f3fe5SMatthew G. Knepley   } else {
56669566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
5667793f3fe5SMatthew G. Knepley   }
56683ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5669793f3fe5SMatthew G. Knepley }
5670793f3fe5SMatthew G. Knepley 
5671d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
5672d71ae5a4SJacob Faibussowitsch {
5673502a2867SDave May   PetscSF            sf;
56746497c311SBarry Smith   PetscMPIInt        niranks, njranks;
56756497c311SBarry Smith   PetscInt           n;
56760a19bb7dSprj-   const PetscMPIInt *iranks, *jranks;
56770a19bb7dSprj-   DM_Plex           *data = (DM_Plex *)dm->data;
5678502a2867SDave May 
56792f356facSMatthew G. Knepley   PetscFunctionBegin;
56809566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
56810a19bb7dSprj-   if (!data->neighbors) {
56829566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sf));
56839566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL));
56849566063dSJacob Faibussowitsch     PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL));
56859566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors));
56869566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks));
56879566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks));
56880a19bb7dSprj-     n = njranks + niranks;
56899566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1));
56900a19bb7dSprj-     /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */
56919566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(n, data->neighbors));
56920a19bb7dSprj-   }
56930a19bb7dSprj-   if (nranks) *nranks = data->neighbors[0];
56940a19bb7dSprj-   if (ranks) {
56950a19bb7dSprj-     if (data->neighbors[0]) *ranks = data->neighbors + 1;
56960a19bb7dSprj-     else *ranks = NULL;
56970a19bb7dSprj-   }
56983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5699502a2867SDave May }
5700502a2867SDave May 
57011eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec);
57021eb70e55SToby Isaac 
5703d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm)
5704d71ae5a4SJacob Faibussowitsch {
5705552f7358SJed Brown   PetscFunctionBegin;
5706552f7358SJed Brown   dm->ops->view                      = DMView_Plex;
57072c40f234SMatthew G. Knepley   dm->ops->load                      = DMLoad_Plex;
5708552f7358SJed Brown   dm->ops->setfromoptions            = DMSetFromOptions_Plex;
570938221697SMatthew G. Knepley   dm->ops->clone                     = DMClone_Plex;
5710552f7358SJed Brown   dm->ops->setup                     = DMSetUp_Plex;
57111bb6d2a8SBarry Smith   dm->ops->createlocalsection        = DMCreateLocalSection_Plex;
5712adc21957SMatthew G. Knepley   dm->ops->createsectionpermutation  = DMCreateSectionPermutation_Plex;
571366ad2231SToby Isaac   dm->ops->createdefaultconstraints  = DMCreateDefaultConstraints_Plex;
5714552f7358SJed Brown   dm->ops->createglobalvector        = DMCreateGlobalVector_Plex;
5715552f7358SJed Brown   dm->ops->createlocalvector         = DMCreateLocalVector_Plex;
5716184d77edSJed Brown   dm->ops->getlocaltoglobalmapping   = NULL;
57170298fd71SBarry Smith   dm->ops->createfieldis             = NULL;
5718552f7358SJed Brown   dm->ops->createcoordinatedm        = DMCreateCoordinateDM_Plex;
571999acd26cSksagiyam   dm->ops->createcellcoordinatedm    = DMCreateCellCoordinateDM_Plex;
5720f19dbd58SToby Isaac   dm->ops->createcoordinatefield     = DMCreateCoordinateField_Plex;
57210a6ba040SMatthew G. Knepley   dm->ops->getcoloring               = NULL;
5722552f7358SJed Brown   dm->ops->creatematrix              = DMCreateMatrix_Plex;
5723bceba477SMatthew G. Knepley   dm->ops->createinterpolation       = DMCreateInterpolation_Plex;
5724bd041c0cSMatthew G. Knepley   dm->ops->createmassmatrix          = DMCreateMassMatrix_Plex;
5725b4937a87SMatthew G. Knepley   dm->ops->createmassmatrixlumped    = DMCreateMassMatrixLumped_Plex;
57265a84ad33SLisandro Dalcin   dm->ops->createinjection           = DMCreateInjection_Plex;
5727552f7358SJed Brown   dm->ops->refine                    = DMRefine_Plex;
57280a6ba040SMatthew G. Knepley   dm->ops->coarsen                   = DMCoarsen_Plex;
57290a6ba040SMatthew G. Knepley   dm->ops->refinehierarchy           = DMRefineHierarchy_Plex;
5730b653a561SMatthew G. Knepley   dm->ops->coarsenhierarchy          = DMCoarsenHierarchy_Plex;
5731d410b0cfSMatthew G. Knepley   dm->ops->extrude                   = DMExtrude_Plex;
57320298fd71SBarry Smith   dm->ops->globaltolocalbegin        = NULL;
57330298fd71SBarry Smith   dm->ops->globaltolocalend          = NULL;
57340298fd71SBarry Smith   dm->ops->localtoglobalbegin        = NULL;
57350298fd71SBarry Smith   dm->ops->localtoglobalend          = NULL;
5736552f7358SJed Brown   dm->ops->destroy                   = DMDestroy_Plex;
5737552f7358SJed Brown   dm->ops->createsubdm               = DMCreateSubDM_Plex;
57382adcc780SMatthew G. Knepley   dm->ops->createsuperdm             = DMCreateSuperDM_Plex;
5739793f3fe5SMatthew G. Knepley   dm->ops->getdimpoints              = DMGetDimPoints_Plex;
5740552f7358SJed Brown   dm->ops->locatepoints              = DMLocatePoints_Plex;
57410709b2feSToby Isaac   dm->ops->projectfunctionlocal      = DMProjectFunctionLocal_Plex;
57420709b2feSToby Isaac   dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex;
5743bfc4295aSToby Isaac   dm->ops->projectfieldlocal         = DMProjectFieldLocal_Plex;
57448c6c5593SMatthew G. Knepley   dm->ops->projectfieldlabellocal    = DMProjectFieldLabelLocal_Plex;
5745ece3a9fcSMatthew G. Knepley   dm->ops->projectbdfieldlabellocal  = DMProjectBdFieldLabelLocal_Plex;
57460709b2feSToby Isaac   dm->ops->computel2diff             = DMComputeL2Diff_Plex;
5747b698f381SToby Isaac   dm->ops->computel2gradientdiff     = DMComputeL2GradientDiff_Plex;
57482a16baeaSToby Isaac   dm->ops->computel2fielddiff        = DMComputeL2FieldDiff_Plex;
574928d58a37SPierre Jolivet   dm->ops->getneighbors              = DMGetNeighbors_Plex;
57506c6a6b79SMatthew G. Knepley   dm->ops->getlocalboundingbox       = DMGetLocalBoundingBox_Coordinates;
5751907a3e9cSStefano Zampini   dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_Plex;
5752907a3e9cSStefano Zampini   dm->ops->createddscatters          = DMCreateDomainDecompositionScatters_Plex;
57539566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex));
57546c51210dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex));
575501468941SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBounds_C", DMPlexInsertBounds_Plex));
57569566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex));
57579566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex));
57589566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex));
57599566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex));
57606bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex));
57616bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex));
5762adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", DMReorderSectionGetDefault_Plex));
5763adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", DMReorderSectionSetDefault_Plex));
5764adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", DMReorderSectionGetType_Plex));
5765adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", DMReorderSectionSetType_Plex));
57669566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex));
5767c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
5768c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex));
5769d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", DMPlexGetUseCeed_Plex));
5770d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", DMPlexSetUseCeed_Plex));
57713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5772552f7358SJed Brown }
5773552f7358SJed Brown 
5774d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm)
5775d71ae5a4SJacob Faibussowitsch {
577663a16f15SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex *)dm->data;
57771fca310dSJames Wright   const PetscSF *face_sfs;
57781fca310dSJames Wright   PetscInt       num_face_sfs;
577963a16f15SMatthew G. Knepley 
578063a16f15SMatthew G. Knepley   PetscFunctionBegin;
578163a16f15SMatthew G. Knepley   mesh->refct++;
578263a16f15SMatthew G. Knepley   (*newdm)->data = mesh;
57831fca310dSJames Wright   PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &face_sfs));
57841fca310dSJames Wright   PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, num_face_sfs, (PetscSF *)face_sfs));
57859566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX));
57869566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(*newdm));
57873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
578863a16f15SMatthew G. Knepley }
578963a16f15SMatthew G. Knepley 
57908818961aSMatthew G Knepley /*MC
57910b4b7b1cSBarry Smith   DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh (or grid), or CW Complex {cite}`cwcomplex`,
57920b4b7b1cSBarry Smith            which can be expressed using a Hasse Diagram {cite}`hassediagram`.
579320f4b53cSBarry Smith            In the local representation, `Vec`s contain all unknowns in the interior and shared boundary. This is
57940b4b7b1cSBarry Smith            specified by a `PetscSection` object. Ownership in the global representation is determined by
5795a1cb98faSBarry Smith            ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object.
57968818961aSMatthew G Knepley 
5797e5893cccSMatthew G. Knepley   Options Database Keys:
5798250712c9SMatthew G. Knepley + -dm_refine_pre                     - Refine mesh before distribution
5799250712c9SMatthew G. Knepley + -dm_refine_uniform_pre             - Choose uniform or generator-based refinement
5800250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre        - Cell volume limit after pre-refinement using generator
5801250712c9SMatthew G. Knepley . -dm_distribute                     - Distribute mesh across processes
5802250712c9SMatthew G. Knepley . -dm_distribute_overlap             - Number of cells to overlap for distribution
5803250712c9SMatthew G. Knepley . -dm_refine                         - Refine mesh after distribution
5804c3db174cSMatthew G. Knepley . -dm_localize <bool>                - Whether to localize coordinates for periodic meshes
5805c3db174cSMatthew G. Knepley . -dm_sparse_localize <bool>         - Whether to only localize cells on the periodic boundary
5806250712c9SMatthew G. Knepley . -dm_plex_hash_location             - Use grid hashing for point location
5807ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p>    - The number of divisions in each direction of the grid hash
5808f12cf164SMatthew G. Knepley . -dm_plex_partition_balance         - Attempt to evenly divide points on partition boundary between processes
5809f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd                 - Allow changes to the boundary on remeshing
5810d5b43468SJose E. Roman . -dm_plex_max_projection_height     - Maximum mesh point height used to project locally
5811f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement        - Use special nested projection algorithm for regular refinement
5812d02c7345SMatthew G. Knepley . -dm_plex_reorder_section           - Use specialized blocking if available
5813aaa8cc7dSPierre Jolivet . -dm_plex_check_all                 - Perform all checks below
5814f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry            - Check that the adjacency information in the mesh is symmetric
5815f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices
5816f12cf164SMatthew 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
5817f12cf164SMatthew G. Knepley . -dm_plex_check_geometry            - Check that cells have positive volume
5818f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex     - View the mesh in LaTeX/TikZ
5819e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num>          - Scale the TikZ
58205962854dSMatthew G. Knepley . -dm_plex_print_fem <num>           - View FEM assembly information, such as element vectors and matrices
58215962854dSMatthew G. Knepley - -dm_plex_print_fvm <num>           - View FVM assembly information, such as flux updates
5822e5893cccSMatthew G. Knepley 
58238818961aSMatthew G Knepley   Level: intermediate
58248818961aSMatthew G Knepley 
58251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection`
58268818961aSMatthew G Knepley M*/
58278818961aSMatthew G Knepley 
5828d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
5829d71ae5a4SJacob Faibussowitsch {
5830552f7358SJed Brown   DM_Plex *mesh;
5831412e9a14SMatthew G. Knepley   PetscInt unit;
5832552f7358SJed Brown 
5833552f7358SJed Brown   PetscFunctionBegin;
5834f39ec787SMatthew G. Knepley   PetscCall(PetscCitationsRegister(PlexCitation, &Plexcite));
5835552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
58364dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&mesh));
5837adc21957SMatthew G. Knepley   dm->reorderSection = DM_REORDER_DEFAULT_NOTSET;
5838552f7358SJed Brown   dm->data           = mesh;
5839552f7358SJed Brown 
5840552f7358SJed Brown   mesh->refct = 1;
58419566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection));
58429566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection));
5843552f7358SJed Brown   mesh->refinementUniform       = PETSC_TRUE;
5844552f7358SJed Brown   mesh->refinementLimit         = -1.0;
5845e600fa54SMatthew G. Knepley   mesh->distDefault             = PETSC_TRUE;
5846adc21957SMatthew G. Knepley   mesh->reorderDefault          = DM_REORDER_DEFAULT_NOTSET;
58471d1f2f2aSksagiyam   mesh->distributionName        = NULL;
58487d0f5628SVaclav Hapla   mesh->interpolated            = DMPLEX_INTERPOLATED_INVALID;
58497d0f5628SVaclav Hapla   mesh->interpolatedCollective  = DMPLEX_INTERPOLATED_INVALID;
58505e2c5519SMatthew G. Knepley   mesh->interpolatePreferTensor = PETSC_TRUE;
5851552f7358SJed Brown 
58529566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner));
58532e62ab5aSMatthew G. Knepley   mesh->remeshBd = PETSC_FALSE;
5854d9deefdfSMatthew G. Knepley 
58558865f1eaSKarl Rupp   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
5856552f7358SJed Brown 
5857df0420ecSMatthew G. Knepley   mesh->depthState    = -1;
5858ba2698f1SMatthew G. Knepley   mesh->celltypeState = -1;
58596113b454SMatthew G. Knepley   mesh->printTol      = 1.0e-10;
5860c29ce622SStefano Zampini   mesh->nonempty_comm = MPI_COMM_SELF;
5861552f7358SJed Brown 
58629566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
58633ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5864552f7358SJed Brown }
5865552f7358SJed Brown 
5866552f7358SJed Brown /*@
5867a1cb98faSBarry Smith   DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
5868552f7358SJed Brown 
5869d083f849SBarry Smith   Collective
5870552f7358SJed Brown 
5871552f7358SJed Brown   Input Parameter:
5872a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object
5873552f7358SJed Brown 
5874552f7358SJed Brown   Output Parameter:
5875a1cb98faSBarry Smith . mesh - The `DMPLEX` object
5876552f7358SJed Brown 
5877552f7358SJed Brown   Level: beginner
5878552f7358SJed Brown 
587942747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMCreate()`, `DMSetType()`
5880552f7358SJed Brown @*/
5881d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
5882d71ae5a4SJacob Faibussowitsch {
5883552f7358SJed Brown   PetscFunctionBegin;
58844f572ea9SToby Isaac   PetscAssertPointer(mesh, 2);
58859566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, mesh));
58869566063dSJacob Faibussowitsch   PetscCall(DMSetType(*mesh, DMPLEX));
58873ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5888552f7358SJed Brown }
5889552f7358SJed Brown 
5890b09969d6SVaclav Hapla /*@C
5891b0fe842aSMatthew 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
5892a1cb98faSBarry Smith 
589320f4b53cSBarry Smith   Collective; No Fortran Support
5894b09969d6SVaclav Hapla 
5895b09969d6SVaclav Hapla   Input Parameters:
5896a1cb98faSBarry Smith + dm          - The `DM`
5897b09969d6SVaclav Hapla . numCells    - The number of cells owned by this process
5898a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
5899a1cb98faSBarry Smith . NVertices   - The global number of vertices, or `PETSC_DETERMINE`
5900b09969d6SVaclav Hapla . numCorners  - The number of vertices for each cell
59015e488331SVaclav Hapla - cells       - An array of numCells*numCorners numbers, the global vertex numbers for each cell
5902b09969d6SVaclav Hapla 
5903be8c289dSNicolas Barral   Output Parameters:
5904a1cb98faSBarry Smith + vertexSF         - (Optional) `PetscSF` describing complete vertex ownership
5905be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
5906b09969d6SVaclav Hapla 
5907b09969d6SVaclav Hapla   Level: advanced
5908b09969d6SVaclav Hapla 
5909a1cb98faSBarry Smith   Notes:
5910a1cb98faSBarry Smith   Two triangles sharing a face
5911a1cb98faSBarry Smith .vb
5912a1cb98faSBarry Smith 
5913a1cb98faSBarry Smith         2
5914a1cb98faSBarry Smith       / | \
5915a1cb98faSBarry Smith      /  |  \
5916a1cb98faSBarry Smith     /   |   \
5917a1cb98faSBarry Smith    0  0 | 1  3
5918a1cb98faSBarry Smith     \   |   /
5919a1cb98faSBarry Smith      \  |  /
5920a1cb98faSBarry Smith       \ | /
5921a1cb98faSBarry Smith         1
5922a1cb98faSBarry Smith .ve
5923a1cb98faSBarry Smith   would have input
5924a1cb98faSBarry Smith .vb
5925a1cb98faSBarry Smith   numCells = 2, numVertices = 4
5926a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
5927a1cb98faSBarry Smith .ve
5928a1cb98faSBarry Smith   which would result in the `DMPLEX`
5929a1cb98faSBarry Smith .vb
5930a1cb98faSBarry Smith 
5931a1cb98faSBarry Smith         4
5932a1cb98faSBarry Smith       / | \
5933a1cb98faSBarry Smith      /  |  \
5934a1cb98faSBarry Smith     /   |   \
5935a1cb98faSBarry Smith    2  0 | 1  5
5936a1cb98faSBarry Smith     \   |   /
5937a1cb98faSBarry Smith      \  |  /
5938a1cb98faSBarry Smith       \ | /
5939a1cb98faSBarry Smith         3
5940a1cb98faSBarry Smith .ve
5941a1cb98faSBarry Smith 
5942a1cb98faSBarry Smith   Vertices are implicitly numbered consecutively 0,...,NVertices.
5943a1cb98faSBarry Smith   Each rank owns a chunk of numVertices consecutive vertices.
5944a1cb98faSBarry Smith   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
5945a1cb98faSBarry Smith   If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
5946a1cb98faSBarry Smith   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
5947a1cb98faSBarry Smith 
5948a1cb98faSBarry Smith   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
5949a1cb98faSBarry Smith 
59501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
5951a1cb98faSBarry Smith           `PetscSF`
5952b09969d6SVaclav Hapla @*/
5953ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[])
5954d71ae5a4SJacob Faibussowitsch {
59552464107aSksagiyam   PetscSF     sfPoint;
59562464107aSksagiyam   PetscLayout layout;
595782fb893eSVaclav Hapla   PetscInt    numVerticesAdj, *verticesAdj, *cones, c, p;
5958a47d0d45SMatthew G. Knepley 
5959a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
596025b6865aSVaclav Hapla   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
59619566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
596225b6865aSVaclav Hapla   /* Get/check global number of vertices */
596325b6865aSVaclav Hapla   {
596425b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
596525b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
596625b6865aSVaclav Hapla 
596725b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
59681690c2aeSBarry Smith     NVerticesInCells = PETSC_INT_MIN;
59699371c9d4SSatish Balay     for (i = 0; i < len; i++)
59709371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
597125b6865aSVaclav Hapla     ++NVerticesInCells;
5972462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
597325b6865aSVaclav Hapla 
597425b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
59759371c9d4SSatish Balay     else
59769371c9d4SSatish 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);
597725b6865aSVaclav Hapla   }
59789079aca8SVaclav Hapla   /* Count locally unique vertices */
59799079aca8SVaclav Hapla   {
59809079aca8SVaclav Hapla     PetscHSetI vhash;
59819079aca8SVaclav Hapla     PetscInt   off = 0;
59829079aca8SVaclav Hapla 
59839566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&vhash));
5984a47d0d45SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
598548a46eb9SPierre Jolivet       for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p]));
5986a47d0d45SMatthew G. Knepley     }
59879566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
59889566063dSJacob Faibussowitsch     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
5989ad540459SPierre Jolivet     else verticesAdj = *verticesAdjSaved;
59909566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
59919566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&vhash));
599263a3b9bcSJacob Faibussowitsch     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
5993a47d0d45SMatthew G. Knepley   }
59949566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
5995a47d0d45SMatthew G. Knepley   /* Create cones */
59969566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
59979566063dSJacob Faibussowitsch   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
59989566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
59999566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
6000a47d0d45SMatthew G. Knepley   for (c = 0; c < numCells; ++c) {
6001a47d0d45SMatthew G. Knepley     for (p = 0; p < numCorners; ++p) {
6002a47d0d45SMatthew G. Knepley       const PetscInt gv = cells[c * numCorners + p];
6003a47d0d45SMatthew G. Knepley       PetscInt       lv;
6004a47d0d45SMatthew G. Knepley 
60059079aca8SVaclav Hapla       /* Positions within verticesAdj form 0-based local vertex numbering;
60069079aca8SVaclav Hapla          we need to shift it by numCells to get correct DAG points (cells go first) */
60079566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
600863a3b9bcSJacob Faibussowitsch       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
6009961cfab0SVaclav Hapla       cones[c * numCorners + p] = lv + numCells;
6010a47d0d45SMatthew G. Knepley     }
6011a47d0d45SMatthew G. Knepley   }
60122464107aSksagiyam   /* Build point sf */
60139566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
60149566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(layout, NVertices));
60159566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
60169566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
60179566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
60189566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
60199566063dSJacob Faibussowitsch   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
60209566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
60212464107aSksagiyam   if (dm->sf) {
60222464107aSksagiyam     const char *prefix;
60232464107aSksagiyam 
60249566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
60259566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
60262464107aSksagiyam   }
60279566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sfPoint));
60289566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfPoint));
6029f4f49eeaSPierre Jolivet   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF"));
6030a47d0d45SMatthew G. Knepley   /* Fill in the rest of the topology structure */
60319566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
60329566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
60339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
60343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6035a47d0d45SMatthew G. Knepley }
6036a47d0d45SMatthew G. Knepley 
6037b0fe842aSMatthew G. Knepley /*@C
6038b0fe842aSMatthew G. Knepley   DMPlexBuildFromCellSectionParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) allowing multiple celltypes
6039b0fe842aSMatthew G. Knepley 
6040b0fe842aSMatthew G. Knepley   Collective; No Fortran Support
6041b0fe842aSMatthew G. Knepley 
6042b0fe842aSMatthew G. Knepley   Input Parameters:
6043b0fe842aSMatthew G. Knepley + dm          - The `DM`
6044b0fe842aSMatthew G. Knepley . numCells    - The number of cells owned by this process
6045b0fe842aSMatthew G. Knepley . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
6046b0fe842aSMatthew G. Knepley . NVertices   - The global number of vertices, or `PETSC_DETERMINE`
6047b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells)
6048b0fe842aSMatthew G. Knepley - cells       - An array of the global vertex numbers for each cell
6049b0fe842aSMatthew G. Knepley 
6050b0fe842aSMatthew G. Knepley   Output Parameters:
6051b0fe842aSMatthew G. Knepley + vertexSF         - (Optional) `PetscSF` describing complete vertex ownership
6052b0fe842aSMatthew G. Knepley - verticesAdjSaved - (Optional) vertex adjacency array
6053b0fe842aSMatthew G. Knepley 
6054b0fe842aSMatthew G. Knepley   Level: advanced
6055b0fe842aSMatthew G. Knepley 
6056b0fe842aSMatthew G. Knepley   Notes:
6057b0fe842aSMatthew G. Knepley   A triangle and quadrilateral sharing a face
6058b0fe842aSMatthew G. Knepley .vb
6059b0fe842aSMatthew G. Knepley         2----------3
6060b0fe842aSMatthew G. Knepley       / |          |
6061b0fe842aSMatthew G. Knepley      /  |          |
6062b0fe842aSMatthew G. Knepley     /   |          |
6063b0fe842aSMatthew G. Knepley    0  0 |     1    |
6064b0fe842aSMatthew G. Knepley     \   |          |
6065b0fe842aSMatthew G. Knepley      \  |          |
6066b0fe842aSMatthew G. Knepley       \ |          |
6067b0fe842aSMatthew G. Knepley         1----------4
6068b0fe842aSMatthew G. Knepley .ve
6069b0fe842aSMatthew G. Knepley   would have input
6070b0fe842aSMatthew G. Knepley .vb
6071b0fe842aSMatthew G. Knepley   numCells = 2, numVertices = 5
6072b0fe842aSMatthew G. Knepley   cells = [0 1 2  1 4 3 2]
6073b0fe842aSMatthew G. Knepley .ve
6074b0fe842aSMatthew G. Knepley   which would result in the `DMPLEX`
6075b0fe842aSMatthew G. Knepley .vb
6076b0fe842aSMatthew G. Knepley         4----------5
6077b0fe842aSMatthew G. Knepley       / |          |
6078b0fe842aSMatthew G. Knepley      /  |          |
6079b0fe842aSMatthew G. Knepley     /   |          |
6080b0fe842aSMatthew G. Knepley    2  0 |     1    |
6081b0fe842aSMatthew G. Knepley     \   |          |
6082b0fe842aSMatthew G. Knepley      \  |          |
6083b0fe842aSMatthew G. Knepley       \ |          |
6084b0fe842aSMatthew G. Knepley         3----------6
6085b0fe842aSMatthew G. Knepley .ve
6086b0fe842aSMatthew G. Knepley 
6087b0fe842aSMatthew G. Knepley   Vertices are implicitly numbered consecutively 0,...,NVertices.
6088b0fe842aSMatthew G. Knepley   Each rank owns a chunk of numVertices consecutive vertices.
6089b0fe842aSMatthew G. Knepley   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
6090b0fe842aSMatthew 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.
6091b0fe842aSMatthew G. Knepley   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
6092b0fe842aSMatthew G. Knepley 
6093b0fe842aSMatthew G. Knepley   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
6094b0fe842aSMatthew G. Knepley 
6095b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexCreateFromCellSectionParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
6096b0fe842aSMatthew G. Knepley           `PetscSF`
6097b0fe842aSMatthew G. Knepley @*/
6098ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellSectionParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[])
6099b0fe842aSMatthew G. Knepley {
6100b0fe842aSMatthew G. Knepley   PetscSF     sfPoint;
6101b0fe842aSMatthew G. Knepley   PetscLayout layout;
6102b0fe842aSMatthew G. Knepley   PetscInt    numVerticesAdj, *verticesAdj, *cones, cStart, cEnd, len;
6103b0fe842aSMatthew G. Knepley 
6104b0fe842aSMatthew G. Knepley   PetscFunctionBegin;
6105b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
6106b0fe842aSMatthew G. Knepley   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
6107b0fe842aSMatthew G. Knepley   PetscCall(PetscSectionGetChart(cellSection, &cStart, &cEnd));
6108b0fe842aSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(cellSection, &len));
6109b0fe842aSMatthew 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);
6110b0fe842aSMatthew G. Knepley   /* Get/check global number of vertices */
6111b0fe842aSMatthew G. Knepley   {
6112b0fe842aSMatthew G. Knepley     PetscInt NVerticesInCells;
6113b0fe842aSMatthew G. Knepley 
6114b0fe842aSMatthew G. Knepley     /* NVerticesInCells = max(cells) + 1 */
6115b0fe842aSMatthew G. Knepley     NVerticesInCells = PETSC_MIN_INT;
6116b0fe842aSMatthew G. Knepley     for (PetscInt i = 0; i < len; i++)
6117b0fe842aSMatthew G. Knepley       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
6118b0fe842aSMatthew G. Knepley     ++NVerticesInCells;
6119b0fe842aSMatthew G. Knepley     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
6120b0fe842aSMatthew G. Knepley 
6121b0fe842aSMatthew G. Knepley     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
6122b0fe842aSMatthew G. Knepley     else
6123b0fe842aSMatthew 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);
6124b0fe842aSMatthew G. Knepley   }
6125b0fe842aSMatthew G. Knepley   /* Count locally unique vertices */
6126b0fe842aSMatthew G. Knepley   {
6127b0fe842aSMatthew G. Knepley     PetscHSetI vhash;
6128b0fe842aSMatthew G. Knepley     PetscInt   off = 0;
6129b0fe842aSMatthew G. Knepley 
6130b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetICreate(&vhash));
6131b0fe842aSMatthew G. Knepley     for (PetscInt i = 0; i < len; i++) PetscCall(PetscHSetIAdd(vhash, cells[i]));
6132b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
6133b0fe842aSMatthew G. Knepley     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
6134b0fe842aSMatthew G. Knepley     else verticesAdj = *verticesAdjSaved;
6135b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
6136b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIDestroy(&vhash));
6137b0fe842aSMatthew 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);
6138b0fe842aSMatthew G. Knepley   }
6139b0fe842aSMatthew G. Knepley   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
6140b0fe842aSMatthew G. Knepley   /* Create cones */
6141b0fe842aSMatthew G. Knepley   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
6142b0fe842aSMatthew G. Knepley   for (PetscInt c = 0; c < numCells; ++c) {
6143b0fe842aSMatthew G. Knepley     PetscInt dof;
6144b0fe842aSMatthew G. Knepley 
6145b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetDof(cellSection, c, &dof));
6146b0fe842aSMatthew G. Knepley     PetscCall(DMPlexSetConeSize(dm, c, dof));
6147b0fe842aSMatthew G. Knepley   }
6148b0fe842aSMatthew G. Knepley   PetscCall(DMSetUp(dm));
6149b0fe842aSMatthew G. Knepley   PetscCall(DMPlexGetCones(dm, &cones));
6150b0fe842aSMatthew G. Knepley   for (PetscInt c = 0; c < numCells; ++c) {
6151b0fe842aSMatthew G. Knepley     PetscInt dof, off;
6152b0fe842aSMatthew G. Knepley 
6153b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetDof(cellSection, c, &dof));
6154b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetOffset(cellSection, c, &off));
6155b0fe842aSMatthew G. Knepley     for (PetscInt p = off; p < off + dof; ++p) {
6156b0fe842aSMatthew G. Knepley       const PetscInt gv = cells[p];
6157b0fe842aSMatthew G. Knepley       PetscInt       lv;
6158b0fe842aSMatthew G. Knepley 
6159b0fe842aSMatthew G. Knepley       /* Positions within verticesAdj form 0-based local vertex numbering;
6160b0fe842aSMatthew G. Knepley          we need to shift it by numCells to get correct DAG points (cells go first) */
6161b0fe842aSMatthew G. Knepley       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
6162b0fe842aSMatthew G. Knepley       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
6163b0fe842aSMatthew G. Knepley       cones[p] = lv + numCells;
6164b0fe842aSMatthew G. Knepley     }
6165b0fe842aSMatthew G. Knepley   }
6166b0fe842aSMatthew G. Knepley   /* Build point sf */
6167b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
6168b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetSize(layout, NVertices));
6169b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
6170b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetBlockSize(layout, 1));
6171b0fe842aSMatthew G. Knepley   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
6172b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutDestroy(&layout));
6173b0fe842aSMatthew G. Knepley   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
6174b0fe842aSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
6175b0fe842aSMatthew G. Knepley   if (dm->sf) {
6176b0fe842aSMatthew G. Knepley     const char *prefix;
6177b0fe842aSMatthew G. Knepley 
6178b0fe842aSMatthew G. Knepley     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
6179b0fe842aSMatthew G. Knepley     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
6180b0fe842aSMatthew G. Knepley   }
6181b0fe842aSMatthew G. Knepley   PetscCall(DMSetPointSF(dm, sfPoint));
6182b0fe842aSMatthew G. Knepley   PetscCall(PetscSFDestroy(&sfPoint));
6183b0fe842aSMatthew G. Knepley   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF"));
6184b0fe842aSMatthew G. Knepley   /* Fill in the rest of the topology structure */
6185b0fe842aSMatthew G. Knepley   PetscCall(DMPlexSymmetrize(dm));
6186b0fe842aSMatthew G. Knepley   PetscCall(DMPlexStratify(dm));
6187b0fe842aSMatthew G. Knepley   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
6188b0fe842aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
6189b0fe842aSMatthew G. Knepley }
6190b0fe842aSMatthew G. Knepley 
6191cc4c1da9SBarry Smith /*@
6192a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
6193a1cb98faSBarry Smith 
619420f4b53cSBarry Smith   Collective; No Fortran Support
6195b09969d6SVaclav Hapla 
6196b09969d6SVaclav Hapla   Input Parameters:
6197a1cb98faSBarry Smith + dm           - The `DM`
6198b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
6199a1cb98faSBarry Smith . sfVert       - `PetscSF` describing complete vertex ownership
6200b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6201b09969d6SVaclav Hapla 
6202b09969d6SVaclav Hapla   Level: advanced
6203b09969d6SVaclav Hapla 
62041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()`
6205b09969d6SVaclav Hapla @*/
6206d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[])
6207d71ae5a4SJacob Faibussowitsch {
6208a47d0d45SMatthew G. Knepley   PetscSection coordSection;
6209a47d0d45SMatthew G. Knepley   Vec          coordinates;
6210a47d0d45SMatthew G. Knepley   PetscScalar *coords;
62111edcf0b2SVaclav Hapla   PetscInt     numVertices, numVerticesAdj, coordSize, v, vStart, vEnd;
6212835f2295SStefano Zampini   PetscMPIInt  spaceDimi;
6213a47d0d45SMatthew G. Knepley 
6214a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
62159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
62169566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
62171dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
62189566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
62199566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL));
62201dca8a05SBarry 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);
62219566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
62229566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
62239566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
62249566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
62251edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
62269566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
62279566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
6228a47d0d45SMatthew G. Knepley   }
62299566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
62309566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
62319566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
62329566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
62339566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
62349566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
62359566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
62369566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
6237a47d0d45SMatthew G. Knepley   {
6238a47d0d45SMatthew G. Knepley     MPI_Datatype coordtype;
6239a47d0d45SMatthew G. Knepley 
6240a47d0d45SMatthew G. Knepley     /* Need a temp buffer for coords if we have complex/single */
6241835f2295SStefano Zampini     PetscCall(PetscMPIIntCast(spaceDim, &spaceDimi));
6242835f2295SStefano Zampini     PetscCallMPI(MPI_Type_contiguous(spaceDimi, MPIU_SCALAR, &coordtype));
62439566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&coordtype));
624421016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX)
624521016a8bSBarry Smith     {
624621016a8bSBarry Smith       PetscScalar *svertexCoords;
624721016a8bSBarry Smith       PetscInt     i;
62489566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords));
62493612f820SVaclav Hapla       for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i];
62509566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
62519566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
62529566063dSJacob Faibussowitsch       PetscCall(PetscFree(svertexCoords));
625321016a8bSBarry Smith     }
625421016a8bSBarry Smith #else
62559566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
62569566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
625721016a8bSBarry Smith #endif
62589566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&coordtype));
6259a47d0d45SMatthew G. Knepley   }
62609566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
62619566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
62629566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
62639566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
62643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6265a47d0d45SMatthew G. Knepley }
6266a47d0d45SMatthew G. Knepley 
6267c3edce3dSSatish Balay /*@
6268b0fe842aSMatthew 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
6269a1cb98faSBarry Smith 
6270a1cb98faSBarry Smith   Collective
6271a47d0d45SMatthew G. Knepley 
6272a47d0d45SMatthew G. Knepley   Input Parameters:
6273a47d0d45SMatthew G. Knepley + comm         - The communicator
6274a47d0d45SMatthew G. Knepley . dim          - The topological dimension of the mesh
6275a47d0d45SMatthew G. Knepley . numCells     - The number of cells owned by this process
6276a1cb98faSBarry Smith . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`
6277a1cb98faSBarry Smith . NVertices    - The global number of vertices, or `PETSC_DECIDE`
6278a47d0d45SMatthew G. Knepley . numCorners   - The number of vertices for each cell
6279a47d0d45SMatthew G. Knepley . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
6280a47d0d45SMatthew G. Knepley . cells        - An array of numCells*numCorners numbers, the global vertex numbers for each cell
6281a47d0d45SMatthew G. Knepley . spaceDim     - The spatial dimension used for coordinates
6282a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6283a47d0d45SMatthew G. Knepley 
6284d8d19677SJose E. Roman   Output Parameters:
6285a1cb98faSBarry Smith + dm          - The `DM`
6286a1cb98faSBarry Smith . vertexSF    - (Optional) `PetscSF` describing complete vertex ownership
628760225df5SJacob Faibussowitsch - verticesAdj - (Optional) vertex adjacency array
6288a47d0d45SMatthew G. Knepley 
6289b09969d6SVaclav Hapla   Level: intermediate
6290a47d0d45SMatthew G. Knepley 
6291a1cb98faSBarry Smith   Notes:
6292a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
6293a1cb98faSBarry Smith   `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
6294a1cb98faSBarry Smith 
6295a1cb98faSBarry Smith   See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters.
6296a1cb98faSBarry Smith 
6297a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
6298a1cb98faSBarry Smith 
62991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
6300a47d0d45SMatthew G. Knepley @*/
6301ce78bad3SBarry 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)
6302d71ae5a4SJacob Faibussowitsch {
6303a47d0d45SMatthew G. Knepley   PetscSF sfVert;
6304a47d0d45SMatthew G. Knepley 
6305a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
63069566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
63079566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
6308a47d0d45SMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
6309064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
63109566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
63119566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj));
6312a47d0d45SMatthew G. Knepley   if (interpolate) {
63135fd9971aSMatthew G. Knepley     DM idm;
6314a47d0d45SMatthew G. Knepley 
63159566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
63169566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
6317a47d0d45SMatthew G. Knepley     *dm = idm;
6318a47d0d45SMatthew G. Knepley   }
63199566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
632018d54ad4SMichael Lange   if (vertexSF) *vertexSF = sfVert;
63219566063dSJacob Faibussowitsch   else PetscCall(PetscSFDestroy(&sfVert));
63223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6323a47d0d45SMatthew G. Knepley }
6324a47d0d45SMatthew G. Knepley 
6325cc4c1da9SBarry Smith /*@
6326b0fe842aSMatthew G. Knepley   DMPlexCreateFromCellSectionParallel - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) and supports multiple celltypes
6327b0fe842aSMatthew G. Knepley 
6328b0fe842aSMatthew G. Knepley   Collective
6329b0fe842aSMatthew G. Knepley 
6330b0fe842aSMatthew G. Knepley   Input Parameters:
6331b0fe842aSMatthew G. Knepley + comm         - The communicator
6332b0fe842aSMatthew G. Knepley . dim          - The topological dimension of the mesh
6333b0fe842aSMatthew G. Knepley . numCells     - The number of cells owned by this process
6334b0fe842aSMatthew G. Knepley . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`
6335b0fe842aSMatthew G. Knepley . NVertices    - The global number of vertices, or `PETSC_DECIDE`
6336b0fe842aSMatthew G. Knepley . cellSection  - The `PetscSection` giving the number of vertices for each cell (layout of cells)
6337b0fe842aSMatthew G. Knepley . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
6338b0fe842aSMatthew G. Knepley . cells        - An array of the global vertex numbers for each cell
6339b0fe842aSMatthew G. Knepley . spaceDim     - The spatial dimension used for coordinates
6340b0fe842aSMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6341b0fe842aSMatthew G. Knepley 
6342b0fe842aSMatthew G. Knepley   Output Parameters:
6343b0fe842aSMatthew G. Knepley + dm          - The `DM`
6344b0fe842aSMatthew G. Knepley . vertexSF    - (Optional) `PetscSF` describing complete vertex ownership
6345b0fe842aSMatthew G. Knepley - verticesAdj - (Optional) vertex adjacency array
6346b0fe842aSMatthew G. Knepley 
6347b0fe842aSMatthew G. Knepley   Level: intermediate
6348b0fe842aSMatthew G. Knepley 
6349b0fe842aSMatthew G. Knepley   Notes:
6350b0fe842aSMatthew G. Knepley   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
6351b0fe842aSMatthew G. Knepley   `DMPlexBuildFromCellSectionParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
6352b0fe842aSMatthew G. Knepley 
6353b0fe842aSMatthew G. Knepley   See `DMPlexBuildFromCellSectionParallel()` for an example and details about the topology-related parameters.
6354b0fe842aSMatthew G. Knepley 
6355b0fe842aSMatthew G. Knepley   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
6356b0fe842aSMatthew G. Knepley 
6357b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
6358b0fe842aSMatthew G. Knepley @*/
6359ce78bad3SBarry 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)
6360b0fe842aSMatthew G. Knepley {
6361b0fe842aSMatthew G. Knepley   PetscSF sfVert;
6362b0fe842aSMatthew G. Knepley 
6363b0fe842aSMatthew G. Knepley   PetscFunctionBegin;
6364b0fe842aSMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
6365b0fe842aSMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
6366b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
6367b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
6368b0fe842aSMatthew G. Knepley   PetscCall(DMSetDimension(*dm, dim));
6369b0fe842aSMatthew G. Knepley   PetscCall(DMPlexBuildFromCellSectionParallel(*dm, numCells, numVertices, NVertices, cellSection, cells, &sfVert, verticesAdj));
6370b0fe842aSMatthew G. Knepley   if (interpolate) {
6371b0fe842aSMatthew G. Knepley     DM idm;
6372b0fe842aSMatthew G. Knepley 
6373b0fe842aSMatthew G. Knepley     PetscCall(DMPlexInterpolate(*dm, &idm));
6374b0fe842aSMatthew G. Knepley     PetscCall(DMDestroy(dm));
6375b0fe842aSMatthew G. Knepley     *dm = idm;
6376b0fe842aSMatthew G. Knepley   }
6377b0fe842aSMatthew G. Knepley   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
6378b0fe842aSMatthew G. Knepley   if (vertexSF) *vertexSF = sfVert;
6379b0fe842aSMatthew G. Knepley   else PetscCall(PetscSFDestroy(&sfVert));
6380b0fe842aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
6381b0fe842aSMatthew G. Knepley }
6382b0fe842aSMatthew G. Knepley 
6383b0fe842aSMatthew G. Knepley /*@
6384a1cb98faSBarry Smith   DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output)
6385a1cb98faSBarry Smith 
638620f4b53cSBarry Smith   Collective; No Fortran Support
63879298eaa6SMatthew G Knepley 
63889298eaa6SMatthew G Knepley   Input Parameters:
6389a1cb98faSBarry Smith + dm          - The `DM`
6390b09969d6SVaclav Hapla . numCells    - The number of cells owned by this process
6391a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE`
63929298eaa6SMatthew G Knepley . numCorners  - The number of vertices for each cell
6393a3b724e8SBarry Smith - cells       - An array of `numCells` x `numCorners` numbers, the global vertex numbers for each cell
63949298eaa6SMatthew G Knepley 
6395b09969d6SVaclav Hapla   Level: advanced
63969298eaa6SMatthew G Knepley 
6397b09969d6SVaclav Hapla   Notes:
6398b09969d6SVaclav Hapla   Two triangles sharing a face
6399a1cb98faSBarry Smith .vb
64009298eaa6SMatthew G Knepley 
6401a1cb98faSBarry Smith         2
6402a1cb98faSBarry Smith       / | \
6403a1cb98faSBarry Smith      /  |  \
6404a1cb98faSBarry Smith     /   |   \
6405a1cb98faSBarry Smith    0  0 | 1  3
6406a1cb98faSBarry Smith     \   |   /
6407a1cb98faSBarry Smith      \  |  /
6408a1cb98faSBarry Smith       \ | /
6409a1cb98faSBarry Smith         1
6410a1cb98faSBarry Smith .ve
6411a1cb98faSBarry Smith   would have input
6412a1cb98faSBarry Smith .vb
6413a1cb98faSBarry Smith   numCells = 2, numVertices = 4
6414a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
6415a1cb98faSBarry Smith .ve
6416a1cb98faSBarry Smith   which would result in the `DMPLEX`
6417a1cb98faSBarry Smith .vb
6418a1cb98faSBarry Smith 
6419a1cb98faSBarry Smith         4
6420a1cb98faSBarry Smith       / | \
6421a1cb98faSBarry Smith      /  |  \
6422a1cb98faSBarry Smith     /   |   \
6423a1cb98faSBarry Smith    2  0 | 1  5
6424a1cb98faSBarry Smith     \   |   /
6425a1cb98faSBarry Smith      \  |  /
6426a1cb98faSBarry Smith       \ | /
6427a1cb98faSBarry Smith         3
6428a1cb98faSBarry Smith .ve
6429a1cb98faSBarry Smith 
6430a1cb98faSBarry Smith   If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1.
643125b6865aSVaclav Hapla 
64321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()`
6433b09969d6SVaclav Hapla @*/
6434d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[])
6435d71ae5a4SJacob Faibussowitsch {
6436961cfab0SVaclav Hapla   PetscInt *cones, c, p, dim;
6437b09969d6SVaclav Hapla 
6438b09969d6SVaclav Hapla   PetscFunctionBegin;
64399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
64409566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
644125b6865aSVaclav Hapla   /* Get/check global number of vertices */
644225b6865aSVaclav Hapla   {
644325b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
644425b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
644525b6865aSVaclav Hapla 
644625b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
64471690c2aeSBarry Smith     NVerticesInCells = PETSC_INT_MIN;
64489371c9d4SSatish Balay     for (i = 0; i < len; i++)
64499371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
645025b6865aSVaclav Hapla     ++NVerticesInCells;
645125b6865aSVaclav Hapla 
645225b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells;
64539371c9d4SSatish Balay     else
64549371c9d4SSatish 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);
645525b6865aSVaclav Hapla   }
64569566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
645748a46eb9SPierre Jolivet   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
64589566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
64599566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
6460b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
6461ad540459SPierre Jolivet     for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells;
6462b09969d6SVaclav Hapla   }
64639566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
64649566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
64659566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
64663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6467b09969d6SVaclav Hapla }
6468b09969d6SVaclav Hapla 
6469cc4c1da9SBarry Smith /*@
6470a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
6471a1cb98faSBarry Smith 
6472cc4c1da9SBarry Smith   Collective
6473b09969d6SVaclav Hapla 
6474b09969d6SVaclav Hapla   Input Parameters:
6475a1cb98faSBarry Smith + dm           - The `DM`
6476b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
6477b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6478b09969d6SVaclav Hapla 
6479b09969d6SVaclav Hapla   Level: advanced
6480b09969d6SVaclav Hapla 
64811cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()`
6482b09969d6SVaclav Hapla @*/
6483d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[])
6484d71ae5a4SJacob Faibussowitsch {
6485b09969d6SVaclav Hapla   PetscSection coordSection;
6486b09969d6SVaclav Hapla   Vec          coordinates;
6487b09969d6SVaclav Hapla   DM           cdm;
6488b09969d6SVaclav Hapla   PetscScalar *coords;
64891edcf0b2SVaclav Hapla   PetscInt     v, vStart, vEnd, d;
6490b09969d6SVaclav Hapla 
6491b09969d6SVaclav Hapla   PetscFunctionBegin;
64929566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
64939566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
64941dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
64959566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
64969566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
64979566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
64989566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
64999566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
65001edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
65019566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
65029566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
6503b09969d6SVaclav Hapla   }
65049566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
6505b09969d6SVaclav Hapla 
65069566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
65079566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(cdm, &coordinates));
65089566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
65099566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
65109566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(coordinates, &coords));
65111edcf0b2SVaclav Hapla   for (v = 0; v < vEnd - vStart; ++v) {
6512ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d];
6513b09969d6SVaclav Hapla   }
65149566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
65159566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
65169566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
65179566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
65183ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6519b09969d6SVaclav Hapla }
6520b09969d6SVaclav Hapla 
6521b09969d6SVaclav Hapla /*@
6522a1cb98faSBarry Smith   DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input
65233df08285SMatthew G. Knepley 
6524a1cb98faSBarry Smith   Collective
6525b09969d6SVaclav Hapla 
6526b09969d6SVaclav Hapla   Input Parameters:
6527b09969d6SVaclav Hapla + comm         - The communicator
6528b09969d6SVaclav Hapla . dim          - The topological dimension of the mesh
65293df08285SMatthew G. Knepley . numCells     - The number of cells, only on process 0
6530a1cb98faSBarry Smith . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0
65313df08285SMatthew G. Knepley . numCorners   - The number of vertices for each cell, only on process 0
6532b09969d6SVaclav Hapla . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
6533ce78bad3SBarry Smith . cells        - An array of $ numCells \times numCorners$ numbers, the vertices for each cell, only on process 0
6534b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
6535ce78bad3SBarry Smith - vertexCoords - An array of $ numVertices \times spaceDim$ numbers, the coordinates of each vertex, only on process 0
6536b09969d6SVaclav Hapla 
6537b09969d6SVaclav Hapla   Output Parameter:
6538a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0
653925b6865aSVaclav Hapla 
6540b09969d6SVaclav Hapla   Level: intermediate
6541b09969d6SVaclav Hapla 
6542a1cb98faSBarry Smith   Notes:
6543a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`,
6544a1cb98faSBarry Smith   `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()`
6545a1cb98faSBarry Smith 
6546a1cb98faSBarry Smith   See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters.
6547a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters.
6548a1cb98faSBarry Smith   See `DMPlexCreateFromCellListParallelPetsc()` for parallel input
6549a1cb98faSBarry Smith 
65501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
65519298eaa6SMatthew G Knepley @*/
6552d71ae5a4SJacob 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)
6553d71ae5a4SJacob Faibussowitsch {
65543df08285SMatthew G. Knepley   PetscMPIInt rank;
65559298eaa6SMatthew G Knepley 
65569298eaa6SMatthew G Knepley   PetscFunctionBegin;
655728b400f6SJacob 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.");
65589566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
65599566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
65609566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
65619566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
6562c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells));
65639566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL));
65649298eaa6SMatthew G Knepley   if (interpolate) {
65655fd9971aSMatthew G. Knepley     DM idm;
65669298eaa6SMatthew G Knepley 
65679566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
65689566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
65699298eaa6SMatthew G Knepley     *dm = idm;
65709298eaa6SMatthew G Knepley   }
6571c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords));
65729566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL));
65733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65749298eaa6SMatthew G Knepley }
65759298eaa6SMatthew G Knepley 
6576939f6067SMatthew G. Knepley /*@
657720f4b53cSBarry Smith   DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a `DM`
6578939f6067SMatthew G. Knepley 
6579939f6067SMatthew G. Knepley   Input Parameters:
658020f4b53cSBarry Smith + dm               - The empty `DM` object, usually from `DMCreate()` and `DMSetDimension()`
6581939f6067SMatthew G. Knepley . depth            - The depth of the DAG
6582ce78bad3SBarry Smith . numPoints        - Array of size $ depth + 1 $ containing the number of points at each `depth`
6583939f6067SMatthew G. Knepley . coneSize         - The cone size of each point
6584939f6067SMatthew G. Knepley . cones            - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
6585939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point
6586ce78bad3SBarry Smith - vertexCoords     - An array of $ numPoints[0] \times spacedim $ numbers representing the coordinates of each vertex, with `spacedim` the value set via `DMSetCoordinateDim()`
6587939f6067SMatthew G. Knepley 
6588939f6067SMatthew G. Knepley   Output Parameter:
658920f4b53cSBarry Smith . dm - The `DM`
659020f4b53cSBarry Smith 
659120f4b53cSBarry Smith   Level: advanced
6592939f6067SMatthew G. Knepley 
6593a1cb98faSBarry Smith   Note:
6594a1cb98faSBarry Smith   Two triangles sharing a face would have input
6595a1cb98faSBarry Smith .vb
6596a1cb98faSBarry Smith   depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
6597a1cb98faSBarry Smith   cones = [2 3 4  3 5 4], coneOrientations = [0 0 0  0 0 0]
6598a1cb98faSBarry Smith  vertexCoords = [-1.0 0.0  0.0 -1.0  0.0 1.0  1.0 0.0]
6599a1cb98faSBarry Smith .ve
6600939f6067SMatthew G. Knepley   which would result in the DMPlex
6601a1cb98faSBarry Smith .vb
6602a1cb98faSBarry Smith         4
6603a1cb98faSBarry Smith       / | \
6604a1cb98faSBarry Smith      /  |  \
6605a1cb98faSBarry Smith     /   |   \
6606a1cb98faSBarry Smith    2  0 | 1  5
6607a1cb98faSBarry Smith     \   |   /
6608a1cb98faSBarry Smith      \  |  /
6609a1cb98faSBarry Smith       \ | /
6610a1cb98faSBarry Smith         3
6611a1cb98faSBarry Smith .ve
6612a1cb98faSBarry Smith   Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()`
6613939f6067SMatthew G. Knepley 
6614ce78bad3SBarry Smith   Developer Note:
6615ce78bad3SBarry Smith   This does not create anything so should not have create in the name.
6616ce78bad3SBarry Smith 
66171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
6618939f6067SMatthew G. Knepley @*/
6619d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
6620d71ae5a4SJacob Faibussowitsch {
66219298eaa6SMatthew G Knepley   Vec          coordinates;
66229298eaa6SMatthew G Knepley   PetscSection coordSection;
66239298eaa6SMatthew G Knepley   PetscScalar *coords;
6624811e8653SToby Isaac   PetscInt     coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off;
66259298eaa6SMatthew G Knepley 
66269298eaa6SMatthew G Knepley   PetscFunctionBegin;
66279566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
66289566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
662963a3b9bcSJacob Faibussowitsch   PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim);
66309298eaa6SMatthew G Knepley   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
66319566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, pStart, pEnd));
66329298eaa6SMatthew G Knepley   for (p = pStart; p < pEnd; ++p) {
66339566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart]));
6634ad540459SPierre Jolivet     if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart;
663597e052ccSToby Isaac   }
66361dca8a05SBarry Smith   PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]);
66379566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm)); /* Allocate space for cones */
66389298eaa6SMatthew G Knepley   for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) {
66399566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(dm, p, &cones[off]));
66409566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off]));
66419298eaa6SMatthew G Knepley   }
66429566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
66439566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
66449298eaa6SMatthew G Knepley   /* Build coordinates */
66459566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
66469566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
66479566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
66489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0]));
66499298eaa6SMatthew G Knepley   for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) {
66509566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
66519566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
66529298eaa6SMatthew G Knepley   }
66539566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
66549566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
66559566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
66569566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
66579566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
665858b7e2c1SStefano Zampini   PetscCall(VecSetBlockSize(coordinates, PetscMax(dimEmbed, 1)));
66599566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
66609318fe57SMatthew G. Knepley   if (vertexCoords) {
66619566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
66629298eaa6SMatthew G Knepley     for (v = 0; v < numPoints[0]; ++v) {
66639298eaa6SMatthew G Knepley       PetscInt off;
66649298eaa6SMatthew G Knepley 
66659566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off));
6666ad540459SPierre Jolivet       for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d];
66679298eaa6SMatthew G Knepley     }
66689318fe57SMatthew G. Knepley   }
66699566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
66709566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
66719566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
66723ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66739298eaa6SMatthew G Knepley }
66748415267dSToby Isaac 
6675a4e35b19SJacob Faibussowitsch /*
6676a1cb98faSBarry Smith   DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file.
6677a1cb98faSBarry Smith 
6678a1cb98faSBarry Smith   Collective
66798ca92349SMatthew G. Knepley 
66808ca92349SMatthew G. Knepley + comm        - The MPI communicator
66818ca92349SMatthew G. Knepley . filename    - Name of the .dat file
66828ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
66838ca92349SMatthew G. Knepley 
66848ca92349SMatthew G. Knepley   Output Parameter:
6685a1cb98faSBarry Smith . dm  - The `DM` object representing the mesh
66868ca92349SMatthew G. Knepley 
66878ca92349SMatthew G. Knepley   Level: beginner
66888ca92349SMatthew G. Knepley 
6689a1cb98faSBarry Smith   Note:
6690a1cb98faSBarry Smith   The format is the simplest possible:
6691a1cb98faSBarry Smith .vb
6692d0812dedSMatthew G. Knepley   dim Ne Nv Nc Nl
6693d0812dedSMatthew G. Knepley   v_1 v_2 ... v_Nc
6694d0812dedSMatthew G. Knepley   ...
6695d0812dedSMatthew G. Knepley   x y z marker_1 ... marker_Nl
6696a1cb98faSBarry Smith .ve
6697a1cb98faSBarry Smith 
6698a1cb98faSBarry Smith   Developer Note:
6699a1cb98faSBarry Smith   Should use a `PetscViewer` not a filename
6700a1cb98faSBarry Smith 
67016afe31f6SMartin Diehl .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
6702a4e35b19SJacob Faibussowitsch */
6703ff6a9541SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
6704d71ae5a4SJacob Faibussowitsch {
67058ca92349SMatthew G. Knepley   DMLabel      marker;
67068ca92349SMatthew G. Knepley   PetscViewer  viewer;
67078ca92349SMatthew G. Knepley   Vec          coordinates;
67088ca92349SMatthew G. Knepley   PetscSection coordSection;
67098ca92349SMatthew G. Knepley   PetscScalar *coords;
67108ca92349SMatthew G. Knepley   char         line[PETSC_MAX_PATH_LEN];
6711d0812dedSMatthew G. Knepley   PetscInt     cdim, coordSize, v, c, d;
67128ca92349SMatthew G. Knepley   PetscMPIInt  rank;
6713d0812dedSMatthew G. Knepley   int          snum, dim, Nv, Nc, Ncn, Nl;
67148ca92349SMatthew G. Knepley 
67158ca92349SMatthew G. Knepley   PetscFunctionBegin;
67169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
67179566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
67189566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
67199566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
67209566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
6721dd400576SPatrick Sanan   if (rank == 0) {
6722d0812dedSMatthew G. Knepley     PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING));
6723d0812dedSMatthew G. Knepley     snum = sscanf(line, "%d %d %d %d %d", &dim, &Nc, &Nv, &Ncn, &Nl);
6724d0812dedSMatthew G. Knepley     PetscCheck(snum == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
672525ce1634SJed Brown   } else {
6726f8d5e320SMatthew G. Knepley     Nc = Nv = Ncn = Nl = 0;
67278ca92349SMatthew G. Knepley   }
6728d0812dedSMatthew G. Knepley   PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm));
6729835f2295SStefano Zampini   cdim = dim;
67309566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
67319566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
67329566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
6733835f2295SStefano Zampini   PetscCall(DMSetDimension(*dm, dim));
67349566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, cdim));
67358ca92349SMatthew G. Knepley   /* Read topology */
6736dd400576SPatrick Sanan   if (rank == 0) {
6737f8d5e320SMatthew G. Knepley     char     format[PETSC_MAX_PATH_LEN];
6738f8d5e320SMatthew G. Knepley     PetscInt cone[8];
67398ca92349SMatthew G. Knepley     int      vbuf[8], v;
67408ca92349SMatthew G. Knepley 
67419371c9d4SSatish Balay     for (c = 0; c < Ncn; ++c) {
67429371c9d4SSatish Balay       format[c * 3 + 0] = '%';
67439371c9d4SSatish Balay       format[c * 3 + 1] = 'd';
67449371c9d4SSatish Balay       format[c * 3 + 2] = ' ';
67459371c9d4SSatish Balay     }
6746f8d5e320SMatthew G. Knepley     format[Ncn * 3 - 1] = '\0';
67479566063dSJacob Faibussowitsch     for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn));
67489566063dSJacob Faibussowitsch     PetscCall(DMSetUp(*dm));
67498ca92349SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
67509566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING));
6751f8d5e320SMatthew G. Knepley       switch (Ncn) {
6752d71ae5a4SJacob Faibussowitsch       case 2:
6753d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1]);
6754d71ae5a4SJacob Faibussowitsch         break;
6755d71ae5a4SJacob Faibussowitsch       case 3:
6756d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]);
6757d71ae5a4SJacob Faibussowitsch         break;
6758d71ae5a4SJacob Faibussowitsch       case 4:
6759d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]);
6760d71ae5a4SJacob Faibussowitsch         break;
6761d71ae5a4SJacob Faibussowitsch       case 6:
6762d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]);
6763d71ae5a4SJacob Faibussowitsch         break;
6764d71ae5a4SJacob Faibussowitsch       case 8:
6765d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]);
6766d71ae5a4SJacob Faibussowitsch         break;
6767d71ae5a4SJacob Faibussowitsch       default:
6768d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn);
6769f8d5e320SMatthew G. Knepley       }
677008401ef6SPierre Jolivet       PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
6771f8d5e320SMatthew G. Knepley       for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc;
67728ca92349SMatthew G. Knepley       /* Hexahedra are inverted */
6773f8d5e320SMatthew G. Knepley       if (Ncn == 8) {
67748ca92349SMatthew G. Knepley         PetscInt tmp = cone[1];
67758ca92349SMatthew G. Knepley         cone[1]      = cone[3];
67768ca92349SMatthew G. Knepley         cone[3]      = tmp;
67778ca92349SMatthew G. Knepley       }
67789566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(*dm, c, cone));
67798ca92349SMatthew G. Knepley     }
67808ca92349SMatthew G. Knepley   }
67819566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
67829566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
67838ca92349SMatthew G. Knepley   /* Read coordinates */
67849566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
67859566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
67869566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
67879566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
67888ca92349SMatthew G. Knepley   for (v = Nc; v < Nc + Nv; ++v) {
67899566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
67909566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
67918ca92349SMatthew G. Knepley   }
67929566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
67939566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
67949566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
67959566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
67969566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
67979566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
67989566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
67999566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
6800dd400576SPatrick Sanan   if (rank == 0) {
6801f8d5e320SMatthew G. Knepley     char   format[PETSC_MAX_PATH_LEN];
68028ca92349SMatthew G. Knepley     double x[3];
6803f8d5e320SMatthew G. Knepley     int    l, val[3];
68048ca92349SMatthew G. Knepley 
6805f8d5e320SMatthew G. Knepley     if (Nl) {
68069371c9d4SSatish Balay       for (l = 0; l < Nl; ++l) {
68079371c9d4SSatish Balay         format[l * 3 + 0] = '%';
68089371c9d4SSatish Balay         format[l * 3 + 1] = 'd';
68099371c9d4SSatish Balay         format[l * 3 + 2] = ' ';
68109371c9d4SSatish Balay       }
6811f8d5e320SMatthew G. Knepley       format[Nl * 3 - 1] = '\0';
68129566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
68139566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &marker));
6814f8d5e320SMatthew G. Knepley     }
68158ca92349SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
68169566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING));
6817f8d5e320SMatthew G. Knepley       snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]);
681808401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
6819f8d5e320SMatthew G. Knepley       switch (Nl) {
6820d71ae5a4SJacob Faibussowitsch       case 0:
6821d71ae5a4SJacob Faibussowitsch         snum = 0;
6822d71ae5a4SJacob Faibussowitsch         break;
6823d71ae5a4SJacob Faibussowitsch       case 1:
6824d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0]);
6825d71ae5a4SJacob Faibussowitsch         break;
6826d71ae5a4SJacob Faibussowitsch       case 2:
6827d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1]);
6828d71ae5a4SJacob Faibussowitsch         break;
6829d71ae5a4SJacob Faibussowitsch       case 3:
6830d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1], &val[2]);
6831d71ae5a4SJacob Faibussowitsch         break;
6832d71ae5a4SJacob Faibussowitsch       default:
6833d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl);
6834f8d5e320SMatthew G. Knepley       }
683508401ef6SPierre Jolivet       PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
68368ca92349SMatthew G. Knepley       for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d];
68379566063dSJacob Faibussowitsch       for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l]));
68388ca92349SMatthew G. Knepley     }
68398ca92349SMatthew G. Knepley   }
68409566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
68419566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
68429566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
68439566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
68448ca92349SMatthew G. Knepley   if (interpolate) {
68458ca92349SMatthew G. Knepley     DM      idm;
68468ca92349SMatthew G. Knepley     DMLabel bdlabel;
68478ca92349SMatthew G. Knepley 
68489566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
68499566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
68508ca92349SMatthew G. Knepley     *dm = idm;
68518ca92349SMatthew G. Knepley 
6852f8d5e320SMatthew G. Knepley     if (!Nl) {
68539566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
68549566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &bdlabel));
68559566063dSJacob Faibussowitsch       PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel));
68569566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelComplete(*dm, bdlabel));
68578ca92349SMatthew G. Knepley     }
6858f8d5e320SMatthew G. Knepley   }
68593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68608ca92349SMatthew G. Knepley }
68618ca92349SMatthew G. Knepley 
6862edfba7faSMatthew G. Knepley /*
6863edfba7faSMatthew G. Knepley   DMPlexCreateSTLFromFile - Create a `DMPLEX` mesh from an STL file.
6864edfba7faSMatthew G. Knepley 
6865edfba7faSMatthew G. Knepley   Collective
6866edfba7faSMatthew G. Knepley 
6867edfba7faSMatthew G. Knepley + comm        - The MPI communicator
6868edfba7faSMatthew G. Knepley . filename    - Name of the .dat file
6869edfba7faSMatthew G. Knepley - interpolate - Create faces and edges in the mesh
6870edfba7faSMatthew G. Knepley 
6871edfba7faSMatthew G. Knepley   Output Parameter:
6872edfba7faSMatthew G. Knepley . dm  - The `DM` object representing the mesh
6873edfba7faSMatthew G. Knepley 
6874edfba7faSMatthew G. Knepley   Level: beginner
6875edfba7faSMatthew G. Knepley 
6876edfba7faSMatthew G. Knepley   Notes:
6877edfba7faSMatthew G. Knepley   The binary format is:
6878edfba7faSMatthew G. Knepley .vb
6879edfba7faSMatthew G. Knepley   UINT8[80]    - Header               - 80 bytes
6880edfba7faSMatthew G. Knepley   UINT32       - Number of triangles  - 04 bytes
6881edfba7faSMatthew G. Knepley   foreach triangle                    - 50 bytes
6882edfba7faSMatthew G. Knepley     REAL32[3] - Normal vector         - 12 bytes
6883edfba7faSMatthew G. Knepley     REAL32[3] - Vertex 1              - 12 bytes
6884edfba7faSMatthew G. Knepley     REAL32[3] - Vertex 2              - 12 bytes
6885edfba7faSMatthew G. Knepley     REAL32[3] - Vertex 3              - 12 bytes
6886edfba7faSMatthew G. Knepley     UINT16    - Attribute byte count  - 02 bytes
6887edfba7faSMatthew G. Knepley   end
6888edfba7faSMatthew G. Knepley .ve
6889edfba7faSMatthew G. Knepley 
6890edfba7faSMatthew G. Knepley   The format is here <https://en.wikipedia.org/wiki/STL_(file_format)>
6891edfba7faSMatthew G. Knepley 
6892edfba7faSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
6893edfba7faSMatthew G. Knepley */
6894edfba7faSMatthew G. Knepley static PetscErrorCode DMPlexCreateSTLFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
6895edfba7faSMatthew G. Knepley {
6896edfba7faSMatthew G. Knepley   PetscViewer  viewer;
6897edfba7faSMatthew G. Knepley   Vec          coordinates;
6898edfba7faSMatthew G. Knepley   PetscSection coordSection;
6899edfba7faSMatthew G. Knepley   PetscScalar *coords;
6900edfba7faSMatthew G. Knepley   PetscInt     coordSize;
6901edfba7faSMatthew G. Knepley   char         line[PETSC_MAX_PATH_LEN];
6902edfba7faSMatthew G. Knepley   PetscBT      bt;
6903edfba7faSMatthew G. Knepley   float       *trialCoords = NULL;
6904edfba7faSMatthew G. Knepley   PetscInt    *cells       = NULL;
6905edfba7faSMatthew G. Knepley   PetscBool    isascii;
6906edfba7faSMatthew G. Knepley   PetscMPIInt  rank;
6907edfba7faSMatthew G. Knepley   PetscInt     Nc, Nv, nv = 0;
6908edfba7faSMatthew G. Knepley 
6909edfba7faSMatthew G. Knepley   PetscFunctionBegin;
6910edfba7faSMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(comm, &rank));
6911edfba7faSMatthew G. Knepley   PetscCall(PetscViewerCreate(comm, &viewer));
6912edfba7faSMatthew G. Knepley   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERBINARY));
6913edfba7faSMatthew G. Knepley   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
6914edfba7faSMatthew G. Knepley   PetscCall(PetscViewerFileSetName(viewer, filename));
6915edfba7faSMatthew G. Knepley   if (rank == 0) {
6916edfba7faSMatthew G. Knepley     int num;
6917edfba7faSMatthew G. Knepley 
6918edfba7faSMatthew G. Knepley     PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_CHAR));
6919edfba7faSMatthew G. Knepley     line[5] = 0;
6920edfba7faSMatthew G. Knepley     PetscCall(PetscStrncmp(line, "solid", 5, &isascii));
6921edfba7faSMatthew G. Knepley     PetscCheck(!isascii, comm, PETSC_ERR_SUP, "No support for ASCII yet");
6922edfba7faSMatthew G. Knepley     PetscCall(PetscViewerRead(viewer, line, 75, NULL, PETSC_CHAR));
6923edfba7faSMatthew G. Knepley     line[75] = 0;
6924edfba7faSMatthew G. Knepley     PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_INT32));
6925edfba7faSMatthew G. Knepley     PetscCall(PetscByteSwap(&num, PETSC_INT32, 1));
6926edfba7faSMatthew G. Knepley     Nc = num;
6927edfba7faSMatthew G. Knepley     // Read facet coordinates
6928edfba7faSMatthew G. Knepley     PetscCall(PetscMalloc1(Nc * 9, &trialCoords));
6929edfba7faSMatthew G. Knepley     for (PetscInt c = 0; c < Nc; ++c) {
6930edfba7faSMatthew G. Knepley       double    normal[3];
6931edfba7faSMatthew G. Knepley       short int dummy;
6932edfba7faSMatthew G. Knepley 
6933edfba7faSMatthew G. Knepley       PetscCall(PetscViewerRead(viewer, normal, 3, NULL, PETSC_FLOAT));
6934edfba7faSMatthew G. Knepley       PetscCall(PetscViewerRead(viewer, &trialCoords[c * 9 + 0], 9, NULL, PETSC_FLOAT));
6935edfba7faSMatthew G. Knepley       PetscCall(PetscByteSwap(&trialCoords[c * 9 + 0], PETSC_FLOAT, 9));
6936edfba7faSMatthew G. Knepley       PetscCall(PetscViewerRead(viewer, &dummy, 1, NULL, PETSC_SHORT));
6937edfba7faSMatthew G. Knepley     }
6938edfba7faSMatthew G. Knepley     PetscCall(PetscMalloc1(Nc * 3, &cells));
6939edfba7faSMatthew G. Knepley     // Find unique vertices
6940edfba7faSMatthew G. Knepley     PetscCall(PetscBTCreate(Nc * 3, &bt));
6941edfba7faSMatthew G. Knepley     PetscCall(PetscBTMemzero(Nc * 3, bt));
6942edfba7faSMatthew G. Knepley     PetscCall(PetscBTSet(bt, 0));
6943edfba7faSMatthew G. Knepley     PetscCall(PetscBTSet(bt, 1));
6944edfba7faSMatthew G. Knepley     PetscCall(PetscBTSet(bt, 2));
6945edfba7faSMatthew G. Knepley     Nv       = 0;
6946edfba7faSMatthew G. Knepley     cells[0] = Nc + Nv++;
6947edfba7faSMatthew G. Knepley     cells[1] = Nc + Nv++;
6948edfba7faSMatthew G. Knepley     cells[2] = Nc + Nv++;
6949edfba7faSMatthew G. Knepley     for (PetscInt v = 3; v < Nc * 3; ++v) {
6950edfba7faSMatthew G. Knepley       PetscBool match = PETSC_FALSE;
6951edfba7faSMatthew G. Knepley 
6952edfba7faSMatthew G. Knepley       for (PetscInt w = 0, x = 0; w < v; ++w) {
6953edfba7faSMatthew G. Knepley         if (PetscBTLookup(bt, w)) {
6954edfba7faSMatthew G. Knepley           if (trialCoords[v * 3 + 0] == trialCoords[w * 3 + 0] && trialCoords[v * 3 + 1] == trialCoords[w * 3 + 1] && trialCoords[v * 3 + 2] == trialCoords[w * 3 + 2]) {
6955edfba7faSMatthew G. Knepley             match    = PETSC_TRUE;
6956edfba7faSMatthew G. Knepley             cells[v] = Nc + x;
6957edfba7faSMatthew G. Knepley             break;
6958edfba7faSMatthew G. Knepley           }
6959edfba7faSMatthew G. Knepley           ++x;
6960edfba7faSMatthew G. Knepley         }
6961edfba7faSMatthew G. Knepley       }
6962edfba7faSMatthew G. Knepley       if (!match) {
6963edfba7faSMatthew G. Knepley         PetscCall(PetscBTSet(bt, v));
6964edfba7faSMatthew G. Knepley         cells[v] = Nc + Nv++;
6965edfba7faSMatthew G. Knepley       }
6966edfba7faSMatthew G. Knepley     }
6967edfba7faSMatthew G. Knepley   } else {
6968edfba7faSMatthew G. Knepley     Nc = Nv = 0;
6969edfba7faSMatthew G. Knepley   }
6970edfba7faSMatthew G. Knepley   for (PetscInt v = 3; v < Nc * 3; ++v) PetscCheck(cells[v] < Nc + Nv, comm, PETSC_ERR_PLIB, "Invalid cells[%" PetscInt_FMT "]: %" PetscInt_FMT, v, cells[v]);
6971edfba7faSMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
6972edfba7faSMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
6973edfba7faSMatthew G. Knepley   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
6974edfba7faSMatthew G. Knepley   PetscCall(DMSetDimension(*dm, 2));
6975edfba7faSMatthew G. Knepley   PetscCall(DMSetCoordinateDim(*dm, 3));
6976edfba7faSMatthew G. Knepley   for (PetscInt c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, 3));
6977edfba7faSMatthew G. Knepley   PetscCall(DMSetUp(*dm));
6978edfba7faSMatthew G. Knepley   for (PetscInt c = 0; c < Nc; ++c) PetscCall(DMPlexSetCone(*dm, c, &cells[c * 3]));
6979edfba7faSMatthew G. Knepley   PetscCall(PetscFree(cells));
6980edfba7faSMatthew G. Knepley   PetscCall(DMPlexSymmetrize(*dm));
6981edfba7faSMatthew G. Knepley   PetscCall(DMPlexStratify(*dm));
6982edfba7faSMatthew G. Knepley 
6983edfba7faSMatthew G. Knepley   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
6984edfba7faSMatthew G. Knepley   PetscCall(PetscSectionSetNumFields(coordSection, 1));
6985edfba7faSMatthew G. Knepley   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3));
6986edfba7faSMatthew G. Knepley   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
6987edfba7faSMatthew G. Knepley   for (PetscInt v = Nc; v < Nc + Nv; ++v) {
6988edfba7faSMatthew G. Knepley     PetscCall(PetscSectionSetDof(coordSection, v, 3));
6989edfba7faSMatthew G. Knepley     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3));
6990edfba7faSMatthew G. Knepley   }
6991edfba7faSMatthew G. Knepley   PetscCall(PetscSectionSetUp(coordSection));
6992edfba7faSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
6993edfba7faSMatthew G. Knepley   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
6994edfba7faSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
6995edfba7faSMatthew G. Knepley   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
6996edfba7faSMatthew G. Knepley   PetscCall(VecSetBlockSize(coordinates, 3));
6997edfba7faSMatthew G. Knepley   PetscCall(VecSetType(coordinates, VECSTANDARD));
6998edfba7faSMatthew G. Knepley   PetscCall(VecGetArray(coordinates, &coords));
6999edfba7faSMatthew G. Knepley   for (PetscInt tv = 0; tv < Nc * 3; ++tv) {
7000edfba7faSMatthew G. Knepley     if (PetscBTLookup(bt, tv)) {
7001edfba7faSMatthew G. Knepley       for (PetscInt d = 0; d < 3; ++d) coords[nv * 3 + d] = trialCoords[tv * 3 + d];
7002edfba7faSMatthew G. Knepley       ++nv;
7003edfba7faSMatthew G. Knepley     }
7004edfba7faSMatthew G. Knepley   }
7005edfba7faSMatthew G. Knepley   PetscCheck(nv == Nv, comm, PETSC_ERR_PLIB, "Number of vertices copied %" PetscInt_FMT " != %" PetscInt_FMT " nubmer of mesh vertices", nv, Nv);
7006edfba7faSMatthew G. Knepley   PetscCall(PetscFree(trialCoords));
7007edfba7faSMatthew G. Knepley   PetscCall(PetscBTDestroy(&bt));
7008edfba7faSMatthew G. Knepley   PetscCall(VecRestoreArray(coordinates, &coords));
7009edfba7faSMatthew G. Knepley   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
7010edfba7faSMatthew G. Knepley   PetscCall(VecDestroy(&coordinates));
7011edfba7faSMatthew G. Knepley   PetscCall(PetscViewerDestroy(&viewer));
7012edfba7faSMatthew G. Knepley   if (interpolate) {
7013edfba7faSMatthew G. Knepley     DM idm;
7014edfba7faSMatthew G. Knepley 
7015edfba7faSMatthew G. Knepley     PetscCall(DMPlexInterpolate(*dm, &idm));
7016edfba7faSMatthew G. Knepley     PetscCall(DMDestroy(dm));
7017edfba7faSMatthew G. Knepley     *dm = idm;
7018edfba7faSMatthew G. Knepley   }
7019edfba7faSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
7020edfba7faSMatthew G. Knepley }
7021edfba7faSMatthew G. Knepley 
7022*f536a3c1SMatthew G. Knepley /*
7023*f536a3c1SMatthew G. Knepley   DMPlexCreateShapefile - Create a `DMPLEX` mesh from the ESRI Shapefile format.
7024*f536a3c1SMatthew G. Knepley 
7025*f536a3c1SMatthew G. Knepley   Collective
7026*f536a3c1SMatthew G. Knepley 
7027*f536a3c1SMatthew G. Knepley + comm   - The MPI communicator
7028*f536a3c1SMatthew G. Knepley - viewer - `PetscViewer` for the .shp file
7029*f536a3c1SMatthew G. Knepley 
7030*f536a3c1SMatthew G. Knepley   Output Parameter:
7031*f536a3c1SMatthew G. Knepley . dm - The `DM` object representing the mesh
7032*f536a3c1SMatthew G. Knepley 
7033*f536a3c1SMatthew G. Knepley   Level: beginner
7034*f536a3c1SMatthew G. Knepley 
7035*f536a3c1SMatthew G. Knepley   Note:
7036*f536a3c1SMatthew G. Knepley   The format is specified at [Wikipedia](https://en.wikipedia.org/wiki/Shapefile) and [ESRI](https://www.esri.com/content/dam/esrisites/sitecore-archive/Files/Pdfs/library/whitepapers/pdfs/shapefile.pdf).
7037*f536a3c1SMatthew G. Knepley 
7038*f536a3c1SMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
7039*f536a3c1SMatthew G. Knepley */
7040*f536a3c1SMatthew G. Knepley static PetscErrorCode DMPlexCreateShapefile(MPI_Comm comm, PetscViewer viewer, DM *dm)
7041*f536a3c1SMatthew G. Knepley {
7042*f536a3c1SMatthew G. Knepley   Vec          coordinates;
7043*f536a3c1SMatthew G. Knepley   PetscSection coordSection;
7044*f536a3c1SMatthew G. Knepley   PetscScalar *coords;
7045*f536a3c1SMatthew G. Knepley   PetscInt     cdim   = 2, coordSize;
7046*f536a3c1SMatthew G. Knepley   int          dim    = 1, Nv, Nc, vOff;
7047*f536a3c1SMatthew G. Knepley   double      *points = NULL;
7048*f536a3c1SMatthew G. Knepley   double       mbr[4], zb[2], mb[2];
7049*f536a3c1SMatthew G. Knepley   PetscMPIInt  rank;
7050*f536a3c1SMatthew G. Knepley 
7051*f536a3c1SMatthew G. Knepley   PetscFunctionBegin;
7052*f536a3c1SMatthew G. Knepley   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7053*f536a3c1SMatthew G. Knepley   if (rank == 0) {
7054*f536a3c1SMatthew G. Knepley     PetscInt cnt;
7055*f536a3c1SMatthew G. Knepley     int      magic, dummy[5], len, version, shtype, totlen = 0;
7056*f536a3c1SMatthew G. Knepley 
7057*f536a3c1SMatthew G. Knepley     // Read header
7058*f536a3c1SMatthew G. Knepley     PetscCall(PetscViewerBinaryRead(viewer, &magic, 1, &cnt, PETSC_INT32));
7059*f536a3c1SMatthew G. Knepley     PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 0-3");
7060*f536a3c1SMatthew G. Knepley     PetscCheck(magic == 0x0000270a, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: invalid magic number %X", magic);
7061*f536a3c1SMatthew G. Knepley     PetscCall(PetscViewerBinaryRead(viewer, dummy, 5, &cnt, PETSC_INT32));
7062*f536a3c1SMatthew G. Knepley     PetscCheck(cnt == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 4-23");
7063*f536a3c1SMatthew G. Knepley     PetscCall(PetscViewerBinaryRead(viewer, &len, 1, &cnt, PETSC_INT32));
7064*f536a3c1SMatthew G. Knepley     PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 24-27");
7065*f536a3c1SMatthew G. Knepley     PetscCall(PetscViewerBinaryRead(viewer, &version, 1, &cnt, PETSC_INT32));
7066*f536a3c1SMatthew G. Knepley     PetscCall(PetscByteSwap(&version, PETSC_INT32, 1));
7067*f536a3c1SMatthew G. Knepley     PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 28-31");
7068*f536a3c1SMatthew G. Knepley     PetscCall(PetscInfo(viewer, "Shapefile: version %d file length %d\n", version, len));
7069*f536a3c1SMatthew G. Knepley     PetscCall(PetscViewerBinaryRead(viewer, &shtype, 1, &cnt, PETSC_INT32));
7070*f536a3c1SMatthew G. Knepley     PetscCall(PetscByteSwap(&shtype, PETSC_INT32, 1));
7071*f536a3c1SMatthew G. Knepley     PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 32-35");
7072*f536a3c1SMatthew G. Knepley     PetscCall(PetscInfo(viewer, "Shapefile: shape type %d\n", shtype));
7073*f536a3c1SMatthew G. Knepley     PetscCall(PetscViewerBinaryRead(viewer, mbr, 4, &cnt, PETSC_DOUBLE));
7074*f536a3c1SMatthew G. Knepley     PetscCall(PetscByteSwap(mbr, PETSC_DOUBLE, 4));
7075*f536a3c1SMatthew G. Knepley     PetscCheck(cnt == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 36-67");
7076*f536a3c1SMatthew G. Knepley     PetscCall(PetscInfo(viewer, "Shapefile: minimum bounding rectangle (%g, %g) -- (%g, %g)\n", mbr[0], mbr[1], mbr[2], mbr[3]));
7077*f536a3c1SMatthew G. Knepley     PetscCall(PetscViewerBinaryRead(viewer, zb, 2, &cnt, PETSC_DOUBLE));
7078*f536a3c1SMatthew G. Knepley     PetscCall(PetscByteSwap(zb, PETSC_DOUBLE, 2));
7079*f536a3c1SMatthew G. Knepley     PetscCheck(cnt == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 68-83");
7080*f536a3c1SMatthew G. Knepley     PetscCall(PetscInfo(viewer, "Shapefile: Z bounds (%g) -- (%g)\n", zb[0], zb[1]));
7081*f536a3c1SMatthew G. Knepley     PetscCall(PetscViewerBinaryRead(viewer, mb, 2, &cnt, PETSC_DOUBLE));
7082*f536a3c1SMatthew G. Knepley     PetscCall(PetscByteSwap(mb, PETSC_DOUBLE, 2));
7083*f536a3c1SMatthew G. Knepley     PetscCheck(cnt == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 84-99");
7084*f536a3c1SMatthew G. Knepley     PetscCall(PetscInfo(viewer, "Shapefile: M bounds (%g) -- (%g)\n", mb[0], mb[1]));
7085*f536a3c1SMatthew G. Knepley     totlen += 100;
7086*f536a3c1SMatthew G. Knepley     {
7087*f536a3c1SMatthew G. Knepley       int    rnum, rlen, rshtype, rnpart, rnp;
7088*f536a3c1SMatthew G. Knepley       double rmbr[4];
7089*f536a3c1SMatthew G. Knepley       int   *partOffsets;
7090*f536a3c1SMatthew G. Knepley 
7091*f536a3c1SMatthew G. Knepley       // Read record header
7092*f536a3c1SMatthew G. Knepley       PetscCall(PetscViewerBinaryRead(viewer, &rnum, 1, &cnt, PETSC_INT32));
7093*f536a3c1SMatthew G. Knepley       PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record header bytes 0-3");
7094*f536a3c1SMatthew G. Knepley       PetscCall(PetscViewerBinaryRead(viewer, &rlen, 1, &cnt, PETSC_INT32));
7095*f536a3c1SMatthew G. Knepley       PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record header bytes 4-7");
7096*f536a3c1SMatthew G. Knepley       PetscCall(PetscInfo(viewer, "Shapefile: record %d length %d\n", rnum, rlen));
7097*f536a3c1SMatthew G. Knepley       totlen += 8;
7098*f536a3c1SMatthew G. Knepley       // Read record
7099*f536a3c1SMatthew G. Knepley       PetscCall(PetscViewerBinaryRead(viewer, &rshtype, 1, &cnt, PETSC_INT32));
7100*f536a3c1SMatthew G. Knepley       PetscCall(PetscByteSwap(&rshtype, PETSC_INT32, 1));
7101*f536a3c1SMatthew G. Knepley       PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record bytes 0-3");
7102*f536a3c1SMatthew G. Knepley       PetscCall(PetscInfo(viewer, "Shapefile: record shape type %d\n", rshtype));
7103*f536a3c1SMatthew G. Knepley       totlen += 4;
7104*f536a3c1SMatthew G. Knepley       switch (rshtype) {
7105*f536a3c1SMatthew G. Knepley       case 5: // Polygon
7106*f536a3c1SMatthew G. Knepley         PetscCall(PetscViewerBinaryRead(viewer, rmbr, 4, &cnt, PETSC_DOUBLE));
7107*f536a3c1SMatthew G. Knepley         PetscCall(PetscByteSwap(rmbr, PETSC_DOUBLE, 4));
7108*f536a3c1SMatthew G. Knepley         PetscCheck(cnt == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record bytes 4-35");
7109*f536a3c1SMatthew G. Knepley         PetscCall(PetscInfo(viewer, "Shapefile: record minimum bounding rectangle (%g, %g) -- (%g, %g)\n", rmbr[0], rmbr[1], rmbr[2], rmbr[3]));
7110*f536a3c1SMatthew G. Knepley         PetscCall(PetscViewerBinaryRead(viewer, &rnpart, 1, &cnt, PETSC_INT32));
7111*f536a3c1SMatthew G. Knepley         PetscCall(PetscByteSwap(&rnpart, PETSC_INT32, 1));
7112*f536a3c1SMatthew G. Knepley         PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record bytes 36-39");
7113*f536a3c1SMatthew G. Knepley         PetscCall(PetscInfo(viewer, "Shapefile: record shape number of parts %d\n", rnpart));
7114*f536a3c1SMatthew G. Knepley         PetscCall(PetscViewerBinaryRead(viewer, &rnp, 1, &cnt, PETSC_INT32));
7115*f536a3c1SMatthew G. Knepley         PetscCall(PetscByteSwap(&rnp, PETSC_INT32, 1));
7116*f536a3c1SMatthew G. Knepley         PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record bytes 36-39");
7117*f536a3c1SMatthew G. Knepley         PetscCall(PetscInfo(viewer, "Shapefile: record shape number of points %d\n", rnp));
7118*f536a3c1SMatthew G. Knepley         totlen += 40;
7119*f536a3c1SMatthew G. Knepley         PetscCall(PetscMalloc1(rnpart, &partOffsets));
7120*f536a3c1SMatthew G. Knepley         PetscCall(PetscViewerBinaryRead(viewer, partOffsets, rnpart, &cnt, PETSC_INT32));
7121*f536a3c1SMatthew G. Knepley         PetscCall(PetscByteSwap(partOffsets, PETSC_INT32, rnpart));
7122*f536a3c1SMatthew G. Knepley         PetscCheck(cnt == rnpart, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record part offsets");
7123*f536a3c1SMatthew G. Knepley         totlen += 4 * rnpart;
7124*f536a3c1SMatthew G. Knepley         PetscCall(PetscMalloc1(rnp * 2, &points));
7125*f536a3c1SMatthew G. Knepley         PetscCall(PetscViewerBinaryRead(viewer, points, rnp * 2, &cnt, PETSC_DOUBLE));
7126*f536a3c1SMatthew G. Knepley         PetscCall(PetscByteSwap(points, PETSC_DOUBLE, rnp * 2));
7127*f536a3c1SMatthew G. Knepley         PetscCheck(cnt == rnp * 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record points");
7128*f536a3c1SMatthew G. Knepley         totlen += 8 * rnp * 2;
7129*f536a3c1SMatthew G. Knepley         PetscCheck(totlen == 2 * len, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unable to parse Shapefile file: only support a single object: %d != %d", totlen, 2 * len);
7130*f536a3c1SMatthew G. Knepley         // Only get the last polygon now
7131*f536a3c1SMatthew G. Knepley         vOff = partOffsets[rnpart - 1];
7132*f536a3c1SMatthew G. Knepley         Nv   = rnp - vOff;
7133*f536a3c1SMatthew G. Knepley         Nc   = Nv - 1;
7134*f536a3c1SMatthew G. Knepley         PetscCall(PetscInfo(viewer, "Shapefile: record first polygon size %d totlen %d\n", Nv, totlen));
7135*f536a3c1SMatthew G. Knepley         PetscCall(PetscFree(partOffsets));
7136*f536a3c1SMatthew G. Knepley         break;
7137*f536a3c1SMatthew G. Knepley       default:
7138*f536a3c1SMatthew G. Knepley         PetscCheck(0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only support polygons right now");
7139*f536a3c1SMatthew G. Knepley       }
7140*f536a3c1SMatthew G. Knepley     }
7141*f536a3c1SMatthew G. Knepley   } else {
7142*f536a3c1SMatthew G. Knepley     Nc = Nv = vOff = 0;
7143*f536a3c1SMatthew G. Knepley   }
7144*f536a3c1SMatthew G. Knepley   PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm));
7145*f536a3c1SMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
7146*f536a3c1SMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
7147*f536a3c1SMatthew G. Knepley   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
7148*f536a3c1SMatthew G. Knepley   PetscCall(DMSetDimension(*dm, dim));
7149*f536a3c1SMatthew G. Knepley   PetscCall(DMSetCoordinateDim(*dm, cdim));
7150*f536a3c1SMatthew G. Knepley   // Topology of a circle
7151*f536a3c1SMatthew G. Knepley   if (rank == 0) {
7152*f536a3c1SMatthew G. Knepley     for (PetscInt c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, 2));
7153*f536a3c1SMatthew G. Knepley     PetscCall(DMSetUp(*dm));
7154*f536a3c1SMatthew G. Knepley     for (PetscInt c = 0; c < Nc; ++c) {
7155*f536a3c1SMatthew G. Knepley       PetscInt cone[2] = {Nc + c, Nc + c + 1};
7156*f536a3c1SMatthew G. Knepley 
7157*f536a3c1SMatthew G. Knepley       PetscCall(DMPlexSetCone(*dm, c, cone));
7158*f536a3c1SMatthew G. Knepley     }
7159*f536a3c1SMatthew G. Knepley   }
7160*f536a3c1SMatthew G. Knepley   PetscCall(DMPlexSymmetrize(*dm));
7161*f536a3c1SMatthew G. Knepley   PetscCall(DMPlexStratify(*dm));
7162*f536a3c1SMatthew G. Knepley   // Set coordinates
7163*f536a3c1SMatthew G. Knepley   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
7164*f536a3c1SMatthew G. Knepley   PetscCall(PetscSectionSetNumFields(coordSection, 1));
7165*f536a3c1SMatthew G. Knepley   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
7166*f536a3c1SMatthew G. Knepley   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
7167*f536a3c1SMatthew G. Knepley   for (PetscInt v = Nc; v < Nc + Nv; ++v) {
7168*f536a3c1SMatthew G. Knepley     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
7169*f536a3c1SMatthew G. Knepley     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
7170*f536a3c1SMatthew G. Knepley   }
7171*f536a3c1SMatthew G. Knepley   PetscCall(PetscSectionSetUp(coordSection));
7172*f536a3c1SMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
7173*f536a3c1SMatthew G. Knepley   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
7174*f536a3c1SMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
7175*f536a3c1SMatthew G. Knepley   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
7176*f536a3c1SMatthew G. Knepley   PetscCall(VecSetBlockSize(coordinates, cdim));
7177*f536a3c1SMatthew G. Knepley   PetscCall(VecSetType(coordinates, VECSTANDARD));
7178*f536a3c1SMatthew G. Knepley   PetscCall(VecGetArray(coordinates, &coords));
7179*f536a3c1SMatthew G. Knepley   for (PetscInt v = 0; v < Nv; ++v) {
7180*f536a3c1SMatthew G. Knepley     coords[v * cdim + 0] = points[(v + vOff) * cdim + 0] - mbr[0];
7181*f536a3c1SMatthew G. Knepley     coords[v * cdim + 1] = points[(v + vOff) * cdim + 1] - mbr[1];
7182*f536a3c1SMatthew G. Knepley   }
7183*f536a3c1SMatthew G. Knepley   PetscCall(PetscFree(points));
7184*f536a3c1SMatthew G. Knepley   PetscCall(VecRestoreArray(coordinates, &coords));
7185*f536a3c1SMatthew G. Knepley   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
7186*f536a3c1SMatthew G. Knepley   PetscCall(VecDestroy(&coordinates));
7187*f536a3c1SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
7188*f536a3c1SMatthew G. Knepley }
7189*f536a3c1SMatthew G. Knepley 
7190*f536a3c1SMatthew G. Knepley /*
7191*f536a3c1SMatthew G. Knepley   DMPlexCreateShapefileFromFile - Create a `DMPLEX` mesh from the ESRI Shapefile format.
7192*f536a3c1SMatthew G. Knepley 
7193*f536a3c1SMatthew G. Knepley   Collective
7194*f536a3c1SMatthew G. Knepley 
7195*f536a3c1SMatthew G. Knepley + comm     - The MPI communicator
7196*f536a3c1SMatthew G. Knepley . filename - Name of the .shp file
7197*f536a3c1SMatthew G. Knepley 
7198*f536a3c1SMatthew G. Knepley   Output Parameter:
7199*f536a3c1SMatthew G. Knepley . dm - The `DM` object representing the mesh
7200*f536a3c1SMatthew G. Knepley 
7201*f536a3c1SMatthew G. Knepley   Level: beginner
7202*f536a3c1SMatthew G. Knepley 
7203*f536a3c1SMatthew G. Knepley   Note:
7204*f536a3c1SMatthew G. Knepley   The format is specified at [Wikipedia](https://en.wikipedia.org/wiki/Shapefile) and [ESRI](https://www.esri.com/content/dam/esrisites/sitecore-archive/Files/Pdfs/library/whitepapers/pdfs/shapefile.pdf).
7205*f536a3c1SMatthew G. Knepley 
7206*f536a3c1SMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
7207*f536a3c1SMatthew G. Knepley */
7208*f536a3c1SMatthew G. Knepley static PetscErrorCode DMPlexCreateShapefileFromFile(MPI_Comm comm, const char filename[], DM *dm)
7209*f536a3c1SMatthew G. Knepley {
7210*f536a3c1SMatthew G. Knepley   PetscViewer viewer;
7211*f536a3c1SMatthew G. Knepley 
7212*f536a3c1SMatthew G. Knepley   PetscFunctionBegin;
7213*f536a3c1SMatthew G. Knepley   PetscCall(PetscViewerCreate(comm, &viewer));
7214*f536a3c1SMatthew G. Knepley   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERBINARY));
7215*f536a3c1SMatthew G. Knepley   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
7216*f536a3c1SMatthew G. Knepley   PetscCall(PetscViewerFileSetName(viewer, filename));
7217*f536a3c1SMatthew G. Knepley   PetscCall(DMPlexCreateShapefile(comm, viewer, dm));
7218*f536a3c1SMatthew G. Knepley   PetscCall(PetscViewerDestroy(&viewer));
7219*f536a3c1SMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
7220*f536a3c1SMatthew G. Knepley }
7221*f536a3c1SMatthew G. Knepley 
7222cc4c1da9SBarry Smith /*@
7223a1cb98faSBarry Smith   DMPlexCreateFromFile - This takes a filename and produces a `DM`
7224a1cb98faSBarry Smith 
7225a1cb98faSBarry Smith   Collective
7226ca522641SMatthew G. Knepley 
7227ca522641SMatthew G. Knepley   Input Parameters:
7228ca522641SMatthew G. Knepley + comm        - The communicator
7229ca522641SMatthew G. Knepley . filename    - A file name
7230a1cb98faSBarry Smith . plexname    - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats
7231ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
7232ca522641SMatthew G. Knepley 
7233ca522641SMatthew G. Knepley   Output Parameter:
7234a1cb98faSBarry Smith . dm - The `DM`
7235ca522641SMatthew G. Knepley 
7236a1cb98faSBarry Smith   Options Database Key:
7237a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5
723802ef0d99SVaclav Hapla 
7239b44f4de4SBarry Smith   Use `-dm_plex_create_ prefix` to pass options to the internal `PetscViewer`, e.g. `-dm_plex_create_viewer_hdf5_collective`
7240bca97951SVaclav Hapla 
7241ca522641SMatthew G. Knepley   Level: beginner
7242ca522641SMatthew G. Knepley 
7243a1cb98faSBarry Smith   Notes:
7244a1cb98faSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
7245a1cb98faSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
7246a1cb98faSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
7247a1cb98faSBarry Smith   The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally
7248a1cb98faSBarry Smith   calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats.
7249a1cb98faSBarry Smith 
72501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()`
7251ca522641SMatthew G. Knepley @*/
7252d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm)
7253d71ae5a4SJacob Faibussowitsch {
7254ef3a5affSJacob Faibussowitsch   const char  extGmsh[]      = ".msh";
7255ef3a5affSJacob Faibussowitsch   const char  extGmsh2[]     = ".msh2";
7256ef3a5affSJacob Faibussowitsch   const char  extGmsh4[]     = ".msh4";
7257ef3a5affSJacob Faibussowitsch   const char  extCGNS[]      = ".cgns";
7258ef3a5affSJacob Faibussowitsch   const char  extExodus[]    = ".exo";
7259ef3a5affSJacob Faibussowitsch   const char  extExodus_e[]  = ".e";
7260ef3a5affSJacob Faibussowitsch   const char  extGenesis[]   = ".gen";
7261ef3a5affSJacob Faibussowitsch   const char  extFluent[]    = ".cas";
7262ef3a5affSJacob Faibussowitsch   const char  extHDF5[]      = ".h5";
72636f2c871aSStefano Zampini   const char  extXDMFHDF5[]  = ".xdmf.h5";
7264ef3a5affSJacob Faibussowitsch   const char  extPLY[]       = ".ply";
72655552b385SBrandon   const char  extEGADSlite[] = ".egadslite";
7266ef3a5affSJacob Faibussowitsch   const char  extEGADS[]     = ".egads";
7267ef3a5affSJacob Faibussowitsch   const char  extIGES[]      = ".igs";
72685552b385SBrandon   const char  extIGES2[]     = ".iges";
7269ef3a5affSJacob Faibussowitsch   const char  extSTEP[]      = ".stp";
72705552b385SBrandon   const char  extSTEP2[]     = ".step";
72715552b385SBrandon   const char  extBREP[]      = ".brep";
7272ef3a5affSJacob Faibussowitsch   const char  extCV[]        = ".dat";
7273edfba7faSMatthew G. Knepley   const char  extSTL[]       = ".stl";
7274*f536a3c1SMatthew G. Knepley   const char  extSHP[]       = ".shp";
7275ca522641SMatthew G. Knepley   size_t      len;
7276*f536a3c1SMatthew G. Knepley   PetscBool   isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isPLY, isEGADSlite, isEGADS, isIGES, isIGES2, isSTEP, isSTEP2, isBREP, isCV, isSTL, isSHP, isXDMFHDF5;
7277ca522641SMatthew G. Knepley   PetscMPIInt rank;
7278ca522641SMatthew G. Knepley 
7279ca522641SMatthew G. Knepley   PetscFunctionBegin;
72804f572ea9SToby Isaac   PetscAssertPointer(filename, 2);
72814f572ea9SToby Isaac   if (plexname) PetscAssertPointer(plexname, 3);
72824f572ea9SToby Isaac   PetscAssertPointer(dm, 5);
72839566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
72849566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0));
72859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
72869566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(filename, &len));
728728b400f6SJacob Faibussowitsch   PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path");
7288ef3a5affSJacob Faibussowitsch 
72899371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \
72909371c9d4SSatish Balay   do { \
7291274aaeaaSJacob Faibussowitsch     PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \
7292274aaeaaSJacob Faibussowitsch     /* don't count the null-terminator at the end */ \
7293274aaeaaSJacob Faibussowitsch     const size_t ext_len = sizeof(extension__) - 1; \
7294274aaeaaSJacob Faibussowitsch     if (len < ext_len) { \
7295ef3a5affSJacob Faibussowitsch       is_extension__ = PETSC_FALSE; \
7296ef3a5affSJacob Faibussowitsch     } else { \
7297274aaeaaSJacob Faibussowitsch       PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \
7298ef3a5affSJacob Faibussowitsch     } \
7299ef3a5affSJacob Faibussowitsch   } while (0)
7300ef3a5affSJacob Faibussowitsch 
7301ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh, isGmsh);
7302ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh2, isGmsh2);
7303ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh4, isGmsh4);
7304ef3a5affSJacob Faibussowitsch   CheckExtension(extCGNS, isCGNS);
7305ef3a5affSJacob Faibussowitsch   CheckExtension(extExodus, isExodus);
7306ef3a5affSJacob Faibussowitsch   if (!isExodus) CheckExtension(extExodus_e, isExodus);
7307ef3a5affSJacob Faibussowitsch   CheckExtension(extGenesis, isGenesis);
7308ef3a5affSJacob Faibussowitsch   CheckExtension(extFluent, isFluent);
7309ef3a5affSJacob Faibussowitsch   CheckExtension(extHDF5, isHDF5);
7310ef3a5affSJacob Faibussowitsch   CheckExtension(extPLY, isPLY);
73115552b385SBrandon   CheckExtension(extEGADSlite, isEGADSlite);
7312ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADS, isEGADS);
7313ef3a5affSJacob Faibussowitsch   CheckExtension(extIGES, isIGES);
73145552b385SBrandon   CheckExtension(extIGES2, isIGES2);
7315ef3a5affSJacob Faibussowitsch   CheckExtension(extSTEP, isSTEP);
73165552b385SBrandon   CheckExtension(extSTEP2, isSTEP2);
73175552b385SBrandon   CheckExtension(extBREP, isBREP);
7318ef3a5affSJacob Faibussowitsch   CheckExtension(extCV, isCV);
7319edfba7faSMatthew G. Knepley   CheckExtension(extSTL, isSTL);
7320*f536a3c1SMatthew G. Knepley   CheckExtension(extSHP, isSHP);
73216f2c871aSStefano Zampini   CheckExtension(extXDMFHDF5, isXDMFHDF5);
7322ef3a5affSJacob Faibussowitsch 
7323ef3a5affSJacob Faibussowitsch #undef CheckExtension
7324ef3a5affSJacob Faibussowitsch 
7325de78e4feSLisandro Dalcin   if (isGmsh || isGmsh2 || isGmsh4) {
73269566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm));
7327ca522641SMatthew G. Knepley   } else if (isCGNS) {
73289566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm));
732990c68965SMatthew G. Knepley   } else if (isExodus || isGenesis) {
73309566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm));
73312f0bd6dcSMichael Lange   } else if (isFluent) {
73329566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm));
7333cc2f8f65SMatthew G. Knepley   } else if (isHDF5) {
7334cc2f8f65SMatthew G. Knepley     PetscViewer viewer;
7335cc2f8f65SMatthew G. Knepley 
733643b242b4SVaclav 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 */
73376f2c871aSStefano Zampini     PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &isXDMFHDF5, NULL));
73389566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(comm, &viewer));
73399566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5));
73409566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_"));
73419566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetFromOptions(viewer));
73429566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
73439566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(viewer, filename));
7344cd7e8a5eSksagiyam 
73459566063dSJacob Faibussowitsch     PetscCall(DMCreate(comm, dm));
7346f4f49eeaSPierre Jolivet     PetscCall(PetscObjectSetName((PetscObject)*dm, plexname));
73479566063dSJacob Faibussowitsch     PetscCall(DMSetType(*dm, DMPLEX));
73486f2c871aSStefano Zampini     if (isXDMFHDF5) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF));
73499566063dSJacob Faibussowitsch     PetscCall(DMLoad(*dm, viewer));
73506f2c871aSStefano Zampini     if (isXDMFHDF5) PetscCall(PetscViewerPopFormat(viewer));
73519566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
73525fd9971aSMatthew G. Knepley 
73535fd9971aSMatthew G. Knepley     if (interpolate) {
73545fd9971aSMatthew G. Knepley       DM idm;
73555fd9971aSMatthew G. Knepley 
73569566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm));
73579566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
73585fd9971aSMatthew G. Knepley       *dm = idm;
73595fd9971aSMatthew G. Knepley     }
7360f2801cd6SMatthew G. Knepley   } else if (isPLY) {
73619566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm));
73625552b385SBrandon   } else if (isEGADSlite || isEGADS || isIGES || isIGES2 || isSTEP || isSTEP2 || isBREP) {
73635552b385SBrandon     PetscCall(DMPlexCreateGeomFromFile(comm, filename, dm, isEGADSlite));
73645552b385SBrandon 
73657bee2925SMatthew Knepley     if (!interpolate) {
73667bee2925SMatthew Knepley       DM udm;
73677bee2925SMatthew Knepley 
73689566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(*dm, &udm));
73699566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
73707bee2925SMatthew Knepley       *dm = udm;
73717bee2925SMatthew Knepley     }
73728ca92349SMatthew G. Knepley   } else if (isCV) {
73739566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm));
7374edfba7faSMatthew G. Knepley   } else if (isSTL) {
7375edfba7faSMatthew G. Knepley     PetscCall(DMPlexCreateSTLFromFile(comm, filename, interpolate, dm));
7376*f536a3c1SMatthew G. Knepley   } else if (isSHP) {
7377*f536a3c1SMatthew G. Knepley     PetscCall(DMPlexCreateShapefileFromFile(comm, filename, dm));
737898921bdaSJacob Faibussowitsch   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename);
73799566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(plexname, &len));
7380f4f49eeaSPierre Jolivet   if (len) PetscCall(PetscObjectSetName((PetscObject)*dm, plexname));
73819566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0));
73823ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7383ca522641SMatthew G. Knepley }
738412b8a6daSStefano Zampini 
7385cc4c1da9SBarry Smith /*@
73869f6c5813SMatthew 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.
73879f6c5813SMatthew G. Knepley 
73880528010dSStefano Zampini   Input Parameters:
73890528010dSStefano Zampini + tr     - The `DMPlexTransform`
73900528010dSStefano Zampini - prefix - An options prefix, or NULL
73919f6c5813SMatthew G. Knepley 
73929f6c5813SMatthew G. Knepley   Output Parameter:
73939f6c5813SMatthew G. Knepley . dm - The `DM`
73949f6c5813SMatthew G. Knepley 
73959f6c5813SMatthew G. Knepley   Level: beginner
73969f6c5813SMatthew G. Knepley 
739720f4b53cSBarry Smith   Notes:
739820f4b53cSBarry 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.
739920f4b53cSBarry Smith 
74009f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
74019f6c5813SMatthew G. Knepley @*/
74020528010dSStefano Zampini PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, const char prefix[], DM *dm)
74039f6c5813SMatthew G. Knepley {
74040528010dSStefano Zampini   DM           bdm, bcdm, cdm;
74050528010dSStefano Zampini   Vec          coordinates, coordinatesNew;
74060528010dSStefano Zampini   PetscSection cs;
7407817b2c36SMatthew G. Knepley   PetscInt     cdim, Nl;
74089f6c5813SMatthew G. Knepley 
74099f6c5813SMatthew G. Knepley   PetscFunctionBegin;
74109f6c5813SMatthew G. Knepley   PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm));
74119f6c5813SMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
74120528010dSStefano Zampini   ((DM_Plex *)(*dm)->data)->interpolated = DMPLEX_INTERPOLATED_FULL;
74130528010dSStefano Zampini   // Handle coordinates
74140528010dSStefano Zampini   PetscCall(DMPlexTransformGetDM(tr, &bdm));
7415817b2c36SMatthew G. Knepley   PetscCall(DMPlexTransformSetDimensions(tr, bdm, *dm));
7416817b2c36SMatthew G. Knepley   PetscCall(DMGetCoordinateDim(*dm, &cdim));
74170528010dSStefano Zampini   PetscCall(DMGetCoordinateDM(bdm, &bcdm));
74180528010dSStefano Zampini   PetscCall(DMGetCoordinateDM(*dm, &cdm));
74190528010dSStefano Zampini   PetscCall(DMCopyDisc(bcdm, cdm));
74200528010dSStefano Zampini   PetscCall(DMGetLocalSection(cdm, &cs));
74210528010dSStefano Zampini   PetscCall(PetscSectionSetNumFields(cs, 1));
74220528010dSStefano Zampini   PetscCall(PetscSectionSetFieldComponents(cs, 0, cdim));
74230528010dSStefano Zampini   PetscCall(DMGetCoordinatesLocal(bdm, &coordinates));
74240528010dSStefano Zampini   PetscCall(VecDuplicate(coordinates, &coordinatesNew));
74250528010dSStefano Zampini   PetscCall(VecCopy(coordinates, coordinatesNew));
74260528010dSStefano Zampini   PetscCall(DMSetCoordinatesLocal(*dm, coordinatesNew));
74270528010dSStefano Zampini   PetscCall(VecDestroy(&coordinatesNew));
74289f6c5813SMatthew G. Knepley 
74299f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)tr));
74309f6c5813SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr));
74319f6c5813SMatthew G. Knepley   ((DM_Plex *)(*dm)->data)->tr = tr;
74320528010dSStefano Zampini   PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE));
74330528010dSStefano Zampini   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix));
74340528010dSStefano Zampini   PetscCall(DMSetFromOptions(*dm));
74359f6c5813SMatthew G. Knepley 
74369f6c5813SMatthew G. Knepley   PetscCall(DMGetNumLabels(bdm, &Nl));
74379f6c5813SMatthew G. Knepley   for (PetscInt l = 0; l < Nl; ++l) {
74389f6c5813SMatthew G. Knepley     DMLabel     label, labelNew;
74399f6c5813SMatthew G. Knepley     const char *lname;
74409f6c5813SMatthew G. Knepley     PetscBool   isDepth, isCellType;
74419f6c5813SMatthew G. Knepley 
74429f6c5813SMatthew G. Knepley     PetscCall(DMGetLabelName(bdm, l, &lname));
74439f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "depth", &isDepth));
74449f6c5813SMatthew G. Knepley     if (isDepth) continue;
74459f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "celltype", &isCellType));
74469f6c5813SMatthew G. Knepley     if (isCellType) continue;
74479f6c5813SMatthew G. Knepley     PetscCall(DMCreateLabel(*dm, lname));
74489f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(bdm, lname, &label));
74499f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(*dm, lname, &labelNew));
74509f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL));
74519f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetLabel(labelNew, label));
74529f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetTransform(labelNew, tr));
74539f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetUp(labelNew));
74549f6c5813SMatthew G. Knepley   }
74553ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
74569f6c5813SMatthew G. Knepley }
7457