xref: /petsc/src/dm/impls/plex/plexcreate.c (revision d698cf032b9f026769ec2c47162caba78ed81a3e)
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;
1274fb89dddSMatthew G. Knepley   const PetscReal *maxCell, *Lstart, *L;
1289318fe57SMatthew G. Knepley   PetscInt         dim, cdim;
129e535cce4SJames Wright   PetscBool        use_natural;
1309318fe57SMatthew G. Knepley 
1319318fe57SMatthew G. Knepley   PetscFunctionBegin;
1329318fe57SMatthew G. Knepley   if (dm == dmNew) {
1339566063dSJacob Faibussowitsch     PetscCall(DMDestroy(ndm));
1343ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
1359318fe57SMatthew G. Knepley   }
1369318fe57SMatthew G. Knepley   dm->setupcalled = dmNew->setupcalled;
137d0812dedSMatthew G. Knepley   if (!dm->hdr.name) {
138d0812dedSMatthew G. Knepley     const char *name;
139d0812dedSMatthew G. Knepley 
140d0812dedSMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)*ndm, &name));
141d0812dedSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, name));
142d0812dedSMatthew G. Knepley   }
1439566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dmNew, &dim));
1449566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
1459566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dmNew, &cdim));
1469566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
1479566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmNew, &sf));
1489566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sf));
1499566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmNew, &coordDM));
1509566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmNew, &coords));
1519566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dm, coordDM));
1529566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coords));
1536858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM));
1546858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords));
1556858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dm, coordDM));
1566858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dm, coords));
1579318fe57SMatthew G. Knepley   /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */
1586858538eSMatthew G. Knepley   PetscCall(DMFieldDestroy(&dm->coordinates[0].field));
1596858538eSMatthew G. Knepley   dm->coordinates[0].field            = dmNew->coordinates[0].field;
16061a622f3SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc;
1614fb89dddSMatthew G. Knepley   PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L));
1624fb89dddSMatthew G. Knepley   PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L));
163e535cce4SJames Wright   PetscCall(DMGetNaturalSF(dmNew, &sf));
164e535cce4SJames Wright   PetscCall(DMSetNaturalSF(dm, sf));
165e535cce4SJames Wright   PetscCall(DMGetUseNatural(dmNew, &use_natural));
166e535cce4SJames Wright   PetscCall(DMSetUseNatural(dm, use_natural));
1679566063dSJacob Faibussowitsch   PetscCall(DMDestroy_Plex(dm));
1689566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
1699318fe57SMatthew G. Knepley   dm->data = dmNew->data;
1709318fe57SMatthew G. Knepley   ((DM_Plex *)dmNew->data)->refct++;
1711fca310dSJames Wright   {
1721fca310dSJames Wright     PetscInt       num_face_sfs;
1731fca310dSJames Wright     const PetscSF *sfs;
1741fca310dSJames Wright     PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &sfs));
1751fca310dSJames Wright     PetscCall(DMPlexSetIsoperiodicFaceSF(dm, num_face_sfs, (PetscSF *)sfs)); // for the compose function effect on dm
1761fca310dSJames Wright   }
1779566063dSJacob Faibussowitsch   PetscCall(DMDestroyLabelLinkList_Internal(dm));
1789566063dSJacob Faibussowitsch   PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL));
1799566063dSJacob Faibussowitsch   PetscCall(DMGetCoarseDM(dmNew, &coarseDM));
1809566063dSJacob Faibussowitsch   PetscCall(DMSetCoarseDM(dm, coarseDM));
1815552b385SBrandon   PetscCall(DMPlexCopyEGADSInfo_Internal(dmNew, dm));
1829566063dSJacob Faibussowitsch   PetscCall(DMDestroy(ndm));
1833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1849318fe57SMatthew G. Knepley }
1859318fe57SMatthew G. Knepley 
1869318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew
1879318fe57SMatthew G. Knepley    - Swap the DM_Plex structure
1889318fe57SMatthew G. Knepley    - Swap the coordinates
1899318fe57SMatthew G. Knepley    - Swap the point PetscSF
1909318fe57SMatthew G. Knepley */
191d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB)
192d71ae5a4SJacob Faibussowitsch {
1939318fe57SMatthew G. Knepley   DM          coordDMA, coordDMB;
1949318fe57SMatthew G. Knepley   Vec         coordsA, coordsB;
1959318fe57SMatthew G. Knepley   PetscSF     sfA, sfB;
1969318fe57SMatthew G. Knepley   DMField     fieldTmp;
1979318fe57SMatthew G. Knepley   void       *tmp;
1989318fe57SMatthew G. Knepley   DMLabelLink listTmp;
1999318fe57SMatthew G. Knepley   DMLabel     depthTmp;
2009318fe57SMatthew G. Knepley   PetscInt    tmpI;
2019318fe57SMatthew G. Knepley 
2029318fe57SMatthew G. Knepley   PetscFunctionBegin;
2033ba16761SJacob Faibussowitsch   if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS);
2049566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmA, &sfA));
2059566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dmB, &sfB));
2069566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)sfA));
2079566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmA, sfB));
2089566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dmB, sfA));
2099566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)sfA));
2109318fe57SMatthew G. Knepley 
2119566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmA, &coordDMA));
2129566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dmB, &coordDMB));
2139566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordDMA));
2149566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmA, coordDMB));
2159566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDM(dmB, coordDMA));
2169566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
2179318fe57SMatthew G. Knepley 
2189566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmA, &coordsA));
2199566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocal(dmB, &coordsB));
2209566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)coordsA));
2219566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmA, coordsB));
2229566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dmB, coordsA));
2239566063dSJacob Faibussowitsch   PetscCall(PetscObjectDereference((PetscObject)coordsA));
2249318fe57SMatthew G. Knepley 
2256858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA));
2266858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB));
2276858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordDMA));
2286858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmA, coordDMB));
2296858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinateDM(dmB, coordDMA));
2306858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordDMA));
2316858538eSMatthew G. Knepley 
2326858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA));
2336858538eSMatthew G. Knepley   PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB));
2346858538eSMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)coordsA));
2356858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB));
2366858538eSMatthew G. Knepley   PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA));
2376858538eSMatthew G. Knepley   PetscCall(PetscObjectDereference((PetscObject)coordsA));
2386858538eSMatthew G. Knepley 
2395552b385SBrandon   PetscCall(DMPlexSwapEGADSInfo_Private(dmA, dmB));
2405552b385SBrandon 
2416858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[0].field;
2426858538eSMatthew G. Knepley   dmA->coordinates[0].field = dmB->coordinates[0].field;
2436858538eSMatthew G. Knepley   dmB->coordinates[0].field = fieldTmp;
2446858538eSMatthew G. Knepley   fieldTmp                  = dmA->coordinates[1].field;
2456858538eSMatthew G. Knepley   dmA->coordinates[1].field = dmB->coordinates[1].field;
2466858538eSMatthew G. Knepley   dmB->coordinates[1].field = fieldTmp;
2479318fe57SMatthew G. Knepley   tmp                       = dmA->data;
2489318fe57SMatthew G. Knepley   dmA->data                 = dmB->data;
2499318fe57SMatthew G. Knepley   dmB->data                 = tmp;
2509318fe57SMatthew G. Knepley   listTmp                   = dmA->labels;
2519318fe57SMatthew G. Knepley   dmA->labels               = dmB->labels;
2529318fe57SMatthew G. Knepley   dmB->labels               = listTmp;
2539318fe57SMatthew G. Knepley   depthTmp                  = dmA->depthLabel;
2549318fe57SMatthew G. Knepley   dmA->depthLabel           = dmB->depthLabel;
2559318fe57SMatthew G. Knepley   dmB->depthLabel           = depthTmp;
2569318fe57SMatthew G. Knepley   depthTmp                  = dmA->celltypeLabel;
2579318fe57SMatthew G. Knepley   dmA->celltypeLabel        = dmB->celltypeLabel;
2589318fe57SMatthew G. Knepley   dmB->celltypeLabel        = depthTmp;
2599318fe57SMatthew G. Knepley   tmpI                      = dmA->levelup;
2609318fe57SMatthew G. Knepley   dmA->levelup              = dmB->levelup;
2619318fe57SMatthew G. Knepley   dmB->levelup              = tmpI;
2623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2639318fe57SMatthew G. Knepley }
2649318fe57SMatthew G. Knepley 
2653431e603SJed Brown PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm)
266d71ae5a4SJacob Faibussowitsch {
2679318fe57SMatthew G. Knepley   DM idm;
2689318fe57SMatthew G. Knepley 
2699318fe57SMatthew G. Knepley   PetscFunctionBegin;
2709566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolate(dm, &idm));
2719566063dSJacob Faibussowitsch   PetscCall(DMPlexCopyCoordinates(dm, idm));
27269d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &idm));
2733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2749318fe57SMatthew G. Knepley }
2759318fe57SMatthew G. Knepley 
2769318fe57SMatthew G. Knepley /*@C
2779318fe57SMatthew G. Knepley   DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates
2789318fe57SMatthew G. Knepley 
27920f4b53cSBarry Smith   Collective
2809318fe57SMatthew G. Knepley 
2819318fe57SMatthew G. Knepley   Input Parameters:
28260225df5SJacob Faibussowitsch + dm        - The `DMPLEX`
28320f4b53cSBarry Smith . degree    - The degree of the finite element or `PETSC_DECIDE`
284e44f6aebSMatthew G. Knepley . project   - Flag to project current coordinates into the space
2859318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface
2869318fe57SMatthew G. Knepley 
2879318fe57SMatthew G. Knepley   Level: advanced
2889318fe57SMatthew G. Knepley 
2891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPointFunc`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()`
2909318fe57SMatthew G. Knepley @*/
291e44f6aebSMatthew G. Knepley PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscBool project, PetscPointFunc coordFunc)
292d71ae5a4SJacob Faibussowitsch {
2939318fe57SMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
294e44f6aebSMatthew G. Knepley   PetscFE  fe   = NULL;
2959318fe57SMatthew G. Knepley   DM       cdm;
296ac9d17c7SMatthew G. Knepley   PetscInt dim, cdim, dE, qorder, height;
2979318fe57SMatthew G. Knepley 
298e44f6aebSMatthew G. Knepley   PetscFunctionBegin;
2999566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
300ac9d17c7SMatthew G. Knepley   cdim = dim;
3019566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dE));
3029318fe57SMatthew G. Knepley   qorder = degree;
303e44f6aebSMatthew G. Knepley   PetscCall(DMGetCoordinateDM(dm, &cdm));
304d0609cedSBarry Smith   PetscObjectOptionsBegin((PetscObject)cdm);
305dc431b0cSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0));
306ac9d17c7SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_coordinate_dim", "Set the coordinate dimension", "DMPlexCreateCoordinateSpace", cdim, &cdim, NULL, dim));
307d0609cedSBarry Smith   PetscOptionsEnd();
3081df12153SMatthew G. Knepley   PetscCall(DMPlexGetVTKCellHeight(dm, &height));
309ac9d17c7SMatthew G. Knepley   if (cdim > dim) {
310ac9d17c7SMatthew G. Knepley     DM           cdm;
311ac9d17c7SMatthew G. Knepley     PetscSection cs, csNew;
312ac9d17c7SMatthew G. Knepley     Vec          coordinates, coordinatesNew;
313ac9d17c7SMatthew G. Knepley     VecType      vectype;
314ac9d17c7SMatthew G. Knepley     IS           idx;
315ac9d17c7SMatthew G. Knepley     PetscInt    *indices;
316ac9d17c7SMatthew G. Knepley     PetscInt     bs, n;
317ac9d17c7SMatthew G. Knepley 
318ac9d17c7SMatthew G. Knepley     // Recreate coordinate section
319ac9d17c7SMatthew G. Knepley     {
320ac9d17c7SMatthew G. Knepley       const char *fieldName = NULL, *compName = NULL;
321ac9d17c7SMatthew G. Knepley       PetscInt    Nc, pStart, pEnd;
322ac9d17c7SMatthew G. Knepley 
323ac9d17c7SMatthew G. Knepley       PetscCall(DMGetCoordinateDM(dm, &cdm));
324ac9d17c7SMatthew G. Knepley       PetscCall(DMGetLocalSection(cdm, &cs));
325ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cs), &csNew));
326ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetNumFields(csNew, 1));
327ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionGetFieldName(cs, 0, &fieldName));
328ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetFieldName(csNew, 0, fieldName));
329ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionGetFieldComponents(cs, 0, &Nc));
330ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetFieldComponents(csNew, 0, cdim));
331ac9d17c7SMatthew G. Knepley       for (PetscInt c = 0; c < Nc; ++c) {
332ac9d17c7SMatthew G. Knepley         PetscCall(PetscSectionGetComponentName(cs, 0, c, &compName));
333ac9d17c7SMatthew G. Knepley         PetscCall(PetscSectionSetComponentName(csNew, 0, c, compName));
334ac9d17c7SMatthew G. Knepley       }
335ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionGetChart(cs, &pStart, &pEnd));
336ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetChart(csNew, pStart, pEnd));
337ac9d17c7SMatthew G. Knepley       for (PetscInt p = pStart; p < pEnd; ++p) {
338ac9d17c7SMatthew G. Knepley         PetscCall(PetscSectionSetDof(csNew, p, cdim));
339ac9d17c7SMatthew G. Knepley         PetscCall(PetscSectionSetFieldDof(csNew, p, 0, cdim));
340ac9d17c7SMatthew G. Knepley       }
341ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetUp(csNew));
342ac9d17c7SMatthew G. Knepley     }
343ac9d17c7SMatthew G. Knepley     PetscCall(DMSetLocalSection(cdm, csNew));
344ac9d17c7SMatthew G. Knepley     PetscCall(PetscSectionDestroy(&csNew));
345ac9d17c7SMatthew G. Knepley     // Inject coordinates into higher dimension
346ac9d17c7SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
347ac9d17c7SMatthew G. Knepley     PetscCall(VecGetBlockSize(coordinates, &bs));
348ac9d17c7SMatthew G. Knepley     PetscCheck(bs == dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension");
349ac9d17c7SMatthew G. Knepley     PetscCall(VecCreate(PetscObjectComm((PetscObject)coordinates), &coordinatesNew));
350ac9d17c7SMatthew G. Knepley     PetscCall(VecGetType(coordinates, &vectype));
351ac9d17c7SMatthew G. Knepley     PetscCall(VecSetType(coordinatesNew, vectype));
352ac9d17c7SMatthew G. Knepley     PetscCall(VecGetLocalSize(coordinates, &n));
353ac9d17c7SMatthew G. Knepley     PetscCheck(!(n % bs), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension");
354ac9d17c7SMatthew G. Knepley     n /= bs;
355ac9d17c7SMatthew G. Knepley     PetscCall(VecSetSizes(coordinatesNew, n * cdim, PETSC_DETERMINE));
356ac9d17c7SMatthew G. Knepley     PetscCall(VecSetUp(coordinatesNew));
357ac9d17c7SMatthew G. Knepley     PetscCall(PetscMalloc1(n * bs, &indices));
358ac9d17c7SMatthew G. Knepley     for (PetscInt i = 0; i < n; ++i)
359ac9d17c7SMatthew G. Knepley       for (PetscInt b = 0; b < bs; ++b) indices[i * bs + b] = i * cdim + b;
360ac9d17c7SMatthew G. Knepley     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n * bs, indices, PETSC_OWN_POINTER, &idx));
361ac9d17c7SMatthew G. Knepley     PetscCall(VecISCopy(coordinatesNew, idx, SCATTER_FORWARD, coordinates));
362ac9d17c7SMatthew G. Knepley     PetscCall(ISDestroy(&idx));
363ac9d17c7SMatthew G. Knepley     PetscCall(DMSetCoordinatesLocal(dm, coordinatesNew));
364ac9d17c7SMatthew G. Knepley     PetscCall(VecDestroy(&coordinatesNew));
365ac9d17c7SMatthew G. Knepley     PetscCall(DMSetCoordinateDim(dm, cdim));
366ac9d17c7SMatthew G. Knepley     {
367ac9d17c7SMatthew G. Knepley       PetscInt gn;
368ac9d17c7SMatthew G. Knepley 
369ac9d17c7SMatthew G. Knepley       PetscCall(DMGetCoordinates(dm, &coordinatesNew));
370ac9d17c7SMatthew G. Knepley       PetscCall(VecGetLocalSize(coordinatesNew, &gn));
371ac9d17c7SMatthew 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);
372ac9d17c7SMatthew G. Knepley     }
373ac9d17c7SMatthew G. Knepley     dE = cdim;
374ac9d17c7SMatthew G. Knepley   }
375e44f6aebSMatthew G. Knepley   if (degree >= 0) {
376e44f6aebSMatthew G. Knepley     DMPolytopeType ct = DM_POLYTOPE_UNKNOWN;
377e44f6aebSMatthew G. Knepley     PetscInt       cStart, cEnd, gct;
378dc431b0cSMatthew G. Knepley 
3791df12153SMatthew G. Knepley     PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd));
380dc431b0cSMatthew G. Knepley     if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct));
381e44f6aebSMatthew G. Knepley     gct = (PetscInt)ct;
382462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &gct, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm)));
383e44f6aebSMatthew G. Knepley     ct = (DMPolytopeType)gct;
384e44f6aebSMatthew G. Knepley     // Work around current bug in PetscDualSpaceSetUp_Lagrange()
385e44f6aebSMatthew G. Knepley     //   Can be seen in plex_tutorials-ex10_1
386e44f6aebSMatthew G. Knepley     if (ct != DM_POLYTOPE_SEG_PRISM_TENSOR && ct != DM_POLYTOPE_TRI_PRISM_TENSOR && ct != DM_POLYTOPE_QUAD_PRISM_TENSOR) PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe));
3874f9ab2b4SJed Brown   }
388e44f6aebSMatthew G. Knepley   PetscCall(DMSetCoordinateDisc(dm, fe, project));
3899566063dSJacob Faibussowitsch   PetscCall(PetscFEDestroy(&fe));
3909318fe57SMatthew G. Knepley   mesh->coordFunc = coordFunc;
3913ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3929318fe57SMatthew G. Knepley }
3939318fe57SMatthew G. Knepley 
3941df5d5c5SMatthew G. Knepley /*@
3951df5d5c5SMatthew G. Knepley   DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement.
3961df5d5c5SMatthew G. Knepley 
397d083f849SBarry Smith   Collective
3981df5d5c5SMatthew G. Knepley 
3991df5d5c5SMatthew G. Knepley   Input Parameters:
400a1cb98faSBarry Smith + comm            - The communicator for the `DM` object
4011df5d5c5SMatthew G. Knepley . dim             - The spatial dimension
4021df5d5c5SMatthew G. Knepley . simplex         - Flag for simplicial cells, otherwise they are tensor product cells
4031df5d5c5SMatthew G. Knepley . interpolate     - Flag to create intermediate mesh pieces (edges, faces)
4041df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell
4051df5d5c5SMatthew G. Knepley 
4061df5d5c5SMatthew G. Knepley   Output Parameter:
40760225df5SJacob Faibussowitsch . newdm - The `DM` object
4081df5d5c5SMatthew G. Knepley 
4091df5d5c5SMatthew G. Knepley   Level: beginner
4101df5d5c5SMatthew G. Knepley 
4111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()`
4121df5d5c5SMatthew G. Knepley @*/
413d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm)
414d71ae5a4SJacob Faibussowitsch {
4151df5d5c5SMatthew G. Knepley   DM          dm;
4161df5d5c5SMatthew G. Knepley   PetscMPIInt rank;
4171df5d5c5SMatthew G. Knepley 
4181df5d5c5SMatthew G. Knepley   PetscFunctionBegin;
4199566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, &dm));
4209566063dSJacob Faibussowitsch   PetscCall(DMSetType(dm, DMPLEX));
4219566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
42246139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
4239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
424ce78fa2fSMatthew G. Knepley   switch (dim) {
425ce78fa2fSMatthew G. Knepley   case 2:
4269566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular"));
4279566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral"));
428ce78fa2fSMatthew G. Knepley     break;
429ce78fa2fSMatthew G. Knepley   case 3:
4309566063dSJacob Faibussowitsch     if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral"));
4319566063dSJacob Faibussowitsch     else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral"));
432ce78fa2fSMatthew G. Knepley     break;
433d71ae5a4SJacob Faibussowitsch   default:
434d71ae5a4SJacob Faibussowitsch     SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
435ce78fa2fSMatthew G. Knepley   }
4361df5d5c5SMatthew G. Knepley   if (rank) {
4371df5d5c5SMatthew G. Knepley     PetscInt numPoints[2] = {0, 0};
4389566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL));
4391df5d5c5SMatthew G. Knepley   } else {
4401df5d5c5SMatthew G. Knepley     switch (dim) {
4411df5d5c5SMatthew G. Knepley     case 2:
4421df5d5c5SMatthew G. Knepley       if (simplex) {
4431df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {4, 2};
4441df5d5c5SMatthew G. Knepley         PetscInt    coneSize[6]         = {3, 3, 0, 0, 0, 0};
4451df5d5c5SMatthew G. Knepley         PetscInt    cones[6]            = {2, 3, 4, 5, 4, 3};
4461df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
4471df5d5c5SMatthew G. Knepley         PetscScalar vertexCoords[8]     = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5};
4481df5d5c5SMatthew G. Knepley 
4499566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
4501df5d5c5SMatthew G. Knepley       } else {
4511df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {6, 2};
4521df5d5c5SMatthew G. Knepley         PetscInt    coneSize[8]         = {4, 4, 0, 0, 0, 0, 0, 0};
4531df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {2, 3, 4, 5, 3, 6, 7, 4};
4541df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
4551df5d5c5SMatthew 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};
4561df5d5c5SMatthew G. Knepley 
4579566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
4581df5d5c5SMatthew G. Knepley       }
4591df5d5c5SMatthew G. Knepley       break;
4601df5d5c5SMatthew G. Knepley     case 3:
4611df5d5c5SMatthew G. Knepley       if (simplex) {
4621df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]        = {5, 2};
4631df5d5c5SMatthew G. Knepley         PetscInt    coneSize[7]         = {4, 4, 0, 0, 0, 0, 0};
4641df5d5c5SMatthew G. Knepley         PetscInt    cones[8]            = {4, 3, 5, 2, 5, 3, 4, 6};
4651df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
4661df5d5c5SMatthew 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};
4671df5d5c5SMatthew G. Knepley 
4689566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
4691df5d5c5SMatthew G. Knepley       } else {
4701df5d5c5SMatthew G. Knepley         PetscInt    numPoints[2]         = {12, 2};
4711df5d5c5SMatthew G. Knepley         PetscInt    coneSize[14]         = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
4721df5d5c5SMatthew G. Knepley         PetscInt    cones[16]            = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8};
4731df5d5c5SMatthew G. Knepley         PetscInt    coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
4749371c9d4SSatish 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};
4751df5d5c5SMatthew G. Knepley 
4769566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
4771df5d5c5SMatthew G. Knepley       }
4781df5d5c5SMatthew G. Knepley       break;
479d71ae5a4SJacob Faibussowitsch     default:
480d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim);
4811df5d5c5SMatthew G. Knepley     }
4821df5d5c5SMatthew G. Knepley   }
48346139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
4841df5d5c5SMatthew G. Knepley   *newdm = dm;
4851df5d5c5SMatthew G. Knepley   if (refinementLimit > 0.0) {
4861df5d5c5SMatthew G. Knepley     DM          rdm;
4871df5d5c5SMatthew G. Knepley     const char *name;
4881df5d5c5SMatthew G. Knepley 
4899566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE));
4909566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit));
4919566063dSJacob Faibussowitsch     PetscCall(DMRefine(*newdm, comm, &rdm));
4929566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject)*newdm, &name));
4939566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)rdm, name));
4949566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
4951df5d5c5SMatthew G. Knepley     *newdm = rdm;
4961df5d5c5SMatthew G. Knepley   }
4971df5d5c5SMatthew G. Knepley   if (interpolate) {
4985fd9971aSMatthew G. Knepley     DM idm;
4991df5d5c5SMatthew G. Knepley 
5009566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*newdm, &idm));
5019566063dSJacob Faibussowitsch     PetscCall(DMDestroy(newdm));
5021df5d5c5SMatthew G. Knepley     *newdm = idm;
5031df5d5c5SMatthew G. Knepley   }
5043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5051df5d5c5SMatthew G. Knepley }
5061df5d5c5SMatthew G. Knepley 
507d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
508d71ae5a4SJacob Faibussowitsch {
5099318fe57SMatthew G. Knepley   const PetscInt numVertices    = 2;
5109318fe57SMatthew G. Knepley   PetscInt       markerRight    = 1;
5119318fe57SMatthew G. Knepley   PetscInt       markerLeft     = 1;
5129318fe57SMatthew G. Knepley   PetscBool      markerSeparate = PETSC_FALSE;
5139318fe57SMatthew G. Knepley   Vec            coordinates;
5149318fe57SMatthew G. Knepley   PetscSection   coordSection;
5159318fe57SMatthew G. Knepley   PetscScalar   *coords;
5169318fe57SMatthew G. Knepley   PetscInt       coordSize;
5179318fe57SMatthew G. Knepley   PetscMPIInt    rank;
5189318fe57SMatthew G. Knepley   PetscInt       cdim = 1, v;
519552f7358SJed Brown 
5209318fe57SMatthew G. Knepley   PetscFunctionBegin;
5219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
5229318fe57SMatthew G. Knepley   if (markerSeparate) {
5239318fe57SMatthew G. Knepley     markerRight = 2;
5249318fe57SMatthew G. Knepley     markerLeft  = 1;
5259318fe57SMatthew G. Knepley   }
5269566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
527c5853193SPierre Jolivet   if (rank == 0) {
5289566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numVertices));
5299566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
5309566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft));
5319566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight));
5329318fe57SMatthew G. Knepley   }
5339566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
5349566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
5359318fe57SMatthew G. Knepley   /* Build coordinates */
5369566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, cdim));
5379566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
5389566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
5399566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, 0, numVertices));
5409566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
5419318fe57SMatthew G. Knepley   for (v = 0; v < numVertices; ++v) {
5429566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
5439566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
5449318fe57SMatthew G. Knepley   }
5459566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
5469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
5479566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
5489566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
5499566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
5509566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
5519566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
5529566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
5539318fe57SMatthew G. Knepley   coords[0] = lower[0];
5549318fe57SMatthew G. Knepley   coords[1] = upper[0];
5559566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
5569566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
5579566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
5583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5599318fe57SMatthew G. Knepley }
56026492d91SMatthew G. Knepley 
561d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[])
562d71ae5a4SJacob Faibussowitsch {
5631df21d24SMatthew G. Knepley   const PetscInt numVertices    = (edges[0] + 1) * (edges[1] + 1);
5641df21d24SMatthew G. Knepley   const PetscInt numEdges       = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1];
565552f7358SJed Brown   PetscInt       markerTop      = 1;
566552f7358SJed Brown   PetscInt       markerBottom   = 1;
567552f7358SJed Brown   PetscInt       markerRight    = 1;
568552f7358SJed Brown   PetscInt       markerLeft     = 1;
569552f7358SJed Brown   PetscBool      markerSeparate = PETSC_FALSE;
570552f7358SJed Brown   Vec            coordinates;
571552f7358SJed Brown   PetscSection   coordSection;
572552f7358SJed Brown   PetscScalar   *coords;
573552f7358SJed Brown   PetscInt       coordSize;
574552f7358SJed Brown   PetscMPIInt    rank;
575552f7358SJed Brown   PetscInt       v, vx, vy;
576552f7358SJed Brown 
577552f7358SJed Brown   PetscFunctionBegin;
5789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
579552f7358SJed Brown   if (markerSeparate) {
5801df21d24SMatthew G. Knepley     markerTop    = 3;
5811df21d24SMatthew G. Knepley     markerBottom = 1;
5821df21d24SMatthew G. Knepley     markerRight  = 2;
5831df21d24SMatthew G. Knepley     markerLeft   = 4;
584552f7358SJed Brown   }
5859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
586dd400576SPatrick Sanan   if (rank == 0) {
587552f7358SJed Brown     PetscInt e, ex, ey;
588552f7358SJed Brown 
5899566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices));
59048a46eb9SPierre Jolivet     for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
5919566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
592552f7358SJed Brown     for (vx = 0; vx <= edges[0]; vx++) {
593552f7358SJed Brown       for (ey = 0; ey < edges[1]; ey++) {
594552f7358SJed Brown         PetscInt edge   = vx * edges[1] + ey + edges[0] * (edges[1] + 1);
595552f7358SJed Brown         PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges;
596da80777bSKarl Rupp         PetscInt cone[2];
597552f7358SJed Brown 
5989371c9d4SSatish Balay         cone[0] = vertex;
5999371c9d4SSatish Balay         cone[1] = vertex + edges[0] + 1;
6009566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
601552f7358SJed Brown         if (vx == edges[0]) {
6029566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
6039566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
604552f7358SJed Brown           if (ey == edges[1] - 1) {
6059566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
6069566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight));
607552f7358SJed Brown           }
608552f7358SJed Brown         } else if (vx == 0) {
6099566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
6109566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
611552f7358SJed Brown           if (ey == edges[1] - 1) {
6129566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
6139566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft));
614552f7358SJed Brown           }
615552f7358SJed Brown         }
616552f7358SJed Brown       }
617552f7358SJed Brown     }
618552f7358SJed Brown     for (vy = 0; vy <= edges[1]; vy++) {
619552f7358SJed Brown       for (ex = 0; ex < edges[0]; ex++) {
620552f7358SJed Brown         PetscInt edge   = vy * edges[0] + ex;
621552f7358SJed Brown         PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges;
622da80777bSKarl Rupp         PetscInt cone[2];
623552f7358SJed Brown 
6249371c9d4SSatish Balay         cone[0] = vertex;
6259371c9d4SSatish Balay         cone[1] = vertex + 1;
6269566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, edge, cone));
627552f7358SJed Brown         if (vy == edges[1]) {
6289566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
6299566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
630552f7358SJed Brown           if (ex == edges[0] - 1) {
6319566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
6329566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop));
633552f7358SJed Brown           }
634552f7358SJed Brown         } else if (vy == 0) {
6359566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
6369566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
637552f7358SJed Brown           if (ex == edges[0] - 1) {
6389566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
6399566063dSJacob Faibussowitsch             PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom));
640552f7358SJed Brown           }
641552f7358SJed Brown         }
642552f7358SJed Brown       }
643552f7358SJed Brown     }
644552f7358SJed Brown   }
6459566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
6469566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
647552f7358SJed Brown   /* Build coordinates */
6489566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 2));
6499566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
6509566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
6519566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices));
6529566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2));
653552f7358SJed Brown   for (v = numEdges; v < numEdges + numVertices; ++v) {
6549566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 2));
6559566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2));
656552f7358SJed Brown   }
6579566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
6589566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
6599566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
6609566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
6619566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
6629566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 2));
6639566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
6649566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
665552f7358SJed Brown   for (vy = 0; vy <= edges[1]; ++vy) {
666552f7358SJed Brown     for (vx = 0; vx <= edges[0]; ++vx) {
667552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx;
668552f7358SJed Brown       coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy;
669552f7358SJed Brown     }
670552f7358SJed Brown   }
6719566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
6729566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
6739566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
6743ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
675552f7358SJed Brown }
676552f7358SJed Brown 
677d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[])
678d71ae5a4SJacob Faibussowitsch {
6799e8abbc3SMichael Lange   PetscInt     vertices[3], numVertices;
6807b59f5a9SMichael Lange   PetscInt     numFaces       = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2];
681c2df9bbfSMatthew G. Knepley   PetscInt     markerTop      = 1;
682c2df9bbfSMatthew G. Knepley   PetscInt     markerBottom   = 1;
683c2df9bbfSMatthew G. Knepley   PetscInt     markerFront    = 1;
684c2df9bbfSMatthew G. Knepley   PetscInt     markerBack     = 1;
685c2df9bbfSMatthew G. Knepley   PetscInt     markerRight    = 1;
686c2df9bbfSMatthew G. Knepley   PetscInt     markerLeft     = 1;
687c2df9bbfSMatthew G. Knepley   PetscBool    markerSeparate = PETSC_FALSE;
688552f7358SJed Brown   Vec          coordinates;
689552f7358SJed Brown   PetscSection coordSection;
690552f7358SJed Brown   PetscScalar *coords;
691552f7358SJed Brown   PetscInt     coordSize;
692552f7358SJed Brown   PetscMPIInt  rank;
693552f7358SJed Brown   PetscInt     v, vx, vy, vz;
6947b59f5a9SMichael Lange   PetscInt     voffset, iface = 0, cone[4];
695552f7358SJed Brown 
696552f7358SJed Brown   PetscFunctionBegin;
6971dca8a05SBarry 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");
6989566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
699c2df9bbfSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
700c2df9bbfSMatthew G. Knepley   if (markerSeparate) {
701c2df9bbfSMatthew G. Knepley     markerBottom = 1;
702c2df9bbfSMatthew G. Knepley     markerTop    = 2;
703c2df9bbfSMatthew G. Knepley     markerFront  = 3;
704c2df9bbfSMatthew G. Knepley     markerBack   = 4;
705c2df9bbfSMatthew G. Knepley     markerRight  = 5;
706c2df9bbfSMatthew G. Knepley     markerLeft   = 6;
707c2df9bbfSMatthew G. Knepley   }
7089371c9d4SSatish Balay   vertices[0] = faces[0] + 1;
7099371c9d4SSatish Balay   vertices[1] = faces[1] + 1;
7109371c9d4SSatish Balay   vertices[2] = faces[2] + 1;
7119e8abbc3SMichael Lange   numVertices = vertices[0] * vertices[1] * vertices[2];
712dd400576SPatrick Sanan   if (rank == 0) {
713552f7358SJed Brown     PetscInt f;
714552f7358SJed Brown 
7159566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices));
71648a46eb9SPierre Jolivet     for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
7179566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
7187b59f5a9SMichael Lange 
7197b59f5a9SMichael Lange     /* Side 0 (Top) */
7207b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
7217b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
7227b59f5a9SMichael Lange         voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx;
7239371c9d4SSatish Balay         cone[0] = voffset;
7249371c9d4SSatish Balay         cone[1] = voffset + 1;
7259371c9d4SSatish Balay         cone[2] = voffset + vertices[0] + 1;
7269371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
7279566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
728c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop));
729c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop));
730c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop));
731c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop));
732c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop));
7337b59f5a9SMichael Lange         iface++;
734552f7358SJed Brown       }
735552f7358SJed Brown     }
7367b59f5a9SMichael Lange 
7377b59f5a9SMichael Lange     /* Side 1 (Bottom) */
7387b59f5a9SMichael Lange     for (vy = 0; vy < faces[1]; vy++) {
7397b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
7407b59f5a9SMichael Lange         voffset = numFaces + vy * (faces[0] + 1) + vx;
7419371c9d4SSatish Balay         cone[0] = voffset + 1;
7429371c9d4SSatish Balay         cone[1] = voffset;
7439371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
7449371c9d4SSatish Balay         cone[3] = voffset + vertices[0] + 1;
7459566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
746c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom));
747c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom));
748c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom));
749c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom));
750c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom));
7517b59f5a9SMichael Lange         iface++;
752552f7358SJed Brown       }
753552f7358SJed Brown     }
7547b59f5a9SMichael Lange 
7557b59f5a9SMichael Lange     /* Side 2 (Front) */
7567b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
7577b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
7587b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vx;
7599371c9d4SSatish Balay         cone[0] = voffset;
7609371c9d4SSatish Balay         cone[1] = voffset + 1;
7619371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + 1;
7629371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1];
7639566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
764c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront));
765c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront));
766c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront));
767c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront));
768c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront));
7697b59f5a9SMichael Lange         iface++;
770552f7358SJed Brown       }
7717b59f5a9SMichael Lange     }
7727b59f5a9SMichael Lange 
7737b59f5a9SMichael Lange     /* Side 3 (Back) */
7747b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
7757b59f5a9SMichael Lange       for (vx = 0; vx < faces[0]; vx++) {
7767b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx;
7779371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
7789371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1] + 1;
7799371c9d4SSatish Balay         cone[2] = voffset + 1;
7809371c9d4SSatish Balay         cone[3] = voffset;
7819566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
782c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack));
783c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack));
784c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack));
785c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack));
786c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack));
7877b59f5a9SMichael Lange         iface++;
7887b59f5a9SMichael Lange       }
7897b59f5a9SMichael Lange     }
7907b59f5a9SMichael Lange 
7917b59f5a9SMichael Lange     /* Side 4 (Left) */
7927b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
7937b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
7947b59f5a9SMichael Lange         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0];
7959371c9d4SSatish Balay         cone[0] = voffset;
7969371c9d4SSatish Balay         cone[1] = voffset + vertices[0] * vertices[1];
7979371c9d4SSatish Balay         cone[2] = voffset + vertices[0] * vertices[1] + vertices[0];
7989371c9d4SSatish Balay         cone[3] = voffset + vertices[0];
7999566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
800c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft));
801c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft));
802c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft));
803c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft));
804c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft));
8057b59f5a9SMichael Lange         iface++;
8067b59f5a9SMichael Lange       }
8077b59f5a9SMichael Lange     }
8087b59f5a9SMichael Lange 
8097b59f5a9SMichael Lange     /* Side 5 (Right) */
8107b59f5a9SMichael Lange     for (vz = 0; vz < faces[2]; vz++) {
8117b59f5a9SMichael Lange       for (vy = 0; vy < faces[1]; vy++) {
812aab5bcd8SJed Brown         voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0];
8139371c9d4SSatish Balay         cone[0] = voffset + vertices[0] * vertices[1];
8149371c9d4SSatish Balay         cone[1] = voffset;
8159371c9d4SSatish Balay         cone[2] = voffset + vertices[0];
8169371c9d4SSatish Balay         cone[3] = voffset + vertices[0] * vertices[1] + vertices[0];
8179566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, iface, cone));
818c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight));
819c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight));
820c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight));
821c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight));
822c2df9bbfSMatthew G. Knepley         PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight));
8237b59f5a9SMichael Lange         iface++;
8247b59f5a9SMichael Lange       }
825552f7358SJed Brown     }
826552f7358SJed Brown   }
8279566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
8289566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
829552f7358SJed Brown   /* Build coordinates */
8309566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, 3));
8319566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
8329566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
8339566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices));
8349566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3));
835552f7358SJed Brown   for (v = numFaces; v < numFaces + numVertices; ++v) {
8369566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, 3));
8379566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3));
838552f7358SJed Brown   }
8399566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
8409566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
8419566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
8429566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
8439566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
8449566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, 3));
8459566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
8469566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
847552f7358SJed Brown   for (vz = 0; vz <= faces[2]; ++vz) {
848552f7358SJed Brown     for (vy = 0; vy <= faces[1]; ++vy) {
849552f7358SJed Brown       for (vx = 0; vx <= faces[0]; ++vx) {
850552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx;
851552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy;
852552f7358SJed Brown         coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz;
853552f7358SJed Brown       }
854552f7358SJed Brown     }
855552f7358SJed Brown   }
8569566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
8579566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
8589566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
8593ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
860552f7358SJed Brown }
861552f7358SJed Brown 
862d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate)
863d71ae5a4SJacob Faibussowitsch {
8649318fe57SMatthew G. Knepley   PetscFunctionBegin;
8659318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
86646139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
8679566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim - 1));
8689566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim));
8699318fe57SMatthew G. Knepley   switch (dim) {
870d71ae5a4SJacob Faibussowitsch   case 1:
871d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces));
872d71ae5a4SJacob Faibussowitsch     break;
873d71ae5a4SJacob Faibussowitsch   case 2:
874d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces));
875d71ae5a4SJacob Faibussowitsch     break;
876d71ae5a4SJacob Faibussowitsch   case 3:
877d71ae5a4SJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces));
878d71ae5a4SJacob Faibussowitsch     break;
879d71ae5a4SJacob Faibussowitsch   default:
880d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim);
8819318fe57SMatthew G. Knepley   }
88246139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
8839566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
8843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8859318fe57SMatthew G. Knepley }
8869318fe57SMatthew G. Knepley 
8879318fe57SMatthew G. Knepley /*@C
8889318fe57SMatthew G. Knepley   DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra).
8899318fe57SMatthew G. Knepley 
8909318fe57SMatthew G. Knepley   Collective
8919318fe57SMatthew G. Knepley 
8929318fe57SMatthew G. Knepley   Input Parameters:
893a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
89420f4b53cSBarry Smith . dim         - The spatial dimension of the box, so the resulting mesh is has dimension `dim`-1
89520f4b53cSBarry Smith . faces       - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
89620f4b53cSBarry Smith . lower       - The lower left corner, or `NULL` for (0, 0, 0)
89720f4b53cSBarry Smith . upper       - The upper right corner, or `NULL` for (1, 1, 1)
8989318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
8999318fe57SMatthew G. Knepley 
9009318fe57SMatthew G. Knepley   Output Parameter:
901a1cb98faSBarry Smith . dm - The `DM` object
9029318fe57SMatthew G. Knepley 
9039318fe57SMatthew G. Knepley   Level: beginner
9049318fe57SMatthew G. Knepley 
9051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()`
9069318fe57SMatthew G. Knepley @*/
907d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm)
908d71ae5a4SJacob Faibussowitsch {
9099318fe57SMatthew G. Knepley   PetscInt  fac[3] = {1, 1, 1};
9109318fe57SMatthew G. Knepley   PetscReal low[3] = {0, 0, 0};
9119318fe57SMatthew G. Knepley   PetscReal upp[3] = {1, 1, 1};
9129318fe57SMatthew G. Knepley 
9139318fe57SMatthew G. Knepley   PetscFunctionBegin;
9149566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
9159566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
9169566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate));
9173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
9189318fe57SMatthew G. Knepley }
9199318fe57SMatthew G. Knepley 
920d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd)
921d71ae5a4SJacob Faibussowitsch {
922fdbf62faSLisandro Dalcin   PetscInt     i, fStart, fEnd, numCells = 0, numVerts = 0;
923fdbf62faSLisandro Dalcin   PetscInt     numPoints[2], *coneSize, *cones, *coneOrientations;
924fdbf62faSLisandro Dalcin   PetscScalar *vertexCoords;
925fdbf62faSLisandro Dalcin   PetscReal    L, maxCell;
926fdbf62faSLisandro Dalcin   PetscBool    markerSeparate = PETSC_FALSE;
927fdbf62faSLisandro Dalcin   PetscInt     markerLeft = 1, faceMarkerLeft = 1;
928fdbf62faSLisandro Dalcin   PetscInt     markerRight = 1, faceMarkerRight = 2;
929fdbf62faSLisandro Dalcin   PetscBool    wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE;
930fdbf62faSLisandro Dalcin   PetscMPIInt  rank;
931fdbf62faSLisandro Dalcin 
932fdbf62faSLisandro Dalcin   PetscFunctionBegin;
9334f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
934fdbf62faSLisandro Dalcin 
9359566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, 1));
9369566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
9379566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
938fdbf62faSLisandro Dalcin 
9399566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
940dd400576SPatrick Sanan   if (rank == 0) numCells = segments;
941dd400576SPatrick Sanan   if (rank == 0) numVerts = segments + (wrap ? 0 : 1);
942fdbf62faSLisandro Dalcin 
9439371c9d4SSatish Balay   numPoints[0] = numVerts;
9449371c9d4SSatish Balay   numPoints[1] = numCells;
9459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords));
9469566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts));
947ad540459SPierre Jolivet   for (i = 0; i < numCells; ++i) coneSize[i] = 2;
948ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0;
9499371c9d4SSatish Balay   for (i = 0; i < numCells; ++i) {
9509371c9d4SSatish Balay     cones[2 * i]     = numCells + i % numVerts;
9519371c9d4SSatish Balay     cones[2 * i + 1] = numCells + (i + 1) % numVerts;
9529371c9d4SSatish Balay   }
953ad540459SPierre Jolivet   for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells);
9549566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
9559566063dSJacob Faibussowitsch   PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords));
956fdbf62faSLisandro Dalcin 
9579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
9589371c9d4SSatish Balay   if (markerSeparate) {
9599371c9d4SSatish Balay     markerLeft  = faceMarkerLeft;
9609371c9d4SSatish Balay     markerRight = faceMarkerRight;
9619371c9d4SSatish Balay   }
962dd400576SPatrick Sanan   if (!wrap && rank == 0) {
9639566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
9649566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft));
9659566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight));
9669566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft));
9679566063dSJacob Faibussowitsch     PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight));
968fdbf62faSLisandro Dalcin   }
969fdbf62faSLisandro Dalcin   if (wrap) {
970fdbf62faSLisandro Dalcin     L       = upper - lower;
971fdbf62faSLisandro Dalcin     maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments));
9724fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L));
973fdbf62faSLisandro Dalcin   }
9749566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
9753ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
976fdbf62faSLisandro Dalcin }
977fdbf62faSLisandro Dalcin 
9784054ae39SJames Wright // Creates "Face Sets" label based on the standard box labeling conventions
979d7d2d1d2SJames Wright static PetscErrorCode DMPlexSetBoxLabel_Internal(DM dm, const DMBoundaryType periodicity[])
9804054ae39SJames Wright {
9816ff49feeSJames Wright   DM              cdm;
9826ff49feeSJames Wright   PetscSection    csection;
9836ff49feeSJames Wright   Vec             coordinates;
9844054ae39SJames Wright   DMLabel         label;
9856ff49feeSJames Wright   IS              faces_is;
9862b4f33d9SJames Wright   PetscInt        dim, num_face = 0;
9874054ae39SJames Wright   const PetscInt *faces;
9884054ae39SJames Wright   PetscInt        faceMarkerBottom, faceMarkerTop, faceMarkerFront, faceMarkerBack, faceMarkerRight, faceMarkerLeft;
9894054ae39SJames Wright 
9904054ae39SJames Wright   PetscFunctionBeginUser;
9914054ae39SJames Wright   PetscCall(DMGetDimension(dm, &dim));
992d7c1f440SPierre 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);
9934054ae39SJames Wright   // Get Face Sets label
9944054ae39SJames Wright   PetscCall(DMGetLabel(dm, "Face Sets", &label));
9954054ae39SJames Wright   if (label) {
9964054ae39SJames Wright     PetscCall(DMLabelReset(label));
9974054ae39SJames Wright   } else {
9984054ae39SJames Wright     PetscCall(DMCreateLabel(dm, "Face Sets"));
9994054ae39SJames Wright     PetscCall(DMGetLabel(dm, "Face Sets", &label));
10004054ae39SJames Wright   }
10014054ae39SJames Wright   PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label));
10026ff49feeSJames Wright   PetscCall(DMGetStratumIS(dm, "Face Sets", 1, &faces_is));
10034054ae39SJames Wright 
10044054ae39SJames Wright   switch (dim) {
10054054ae39SJames Wright   case 2:
10064054ae39SJames Wright     faceMarkerTop    = 3;
10074054ae39SJames Wright     faceMarkerBottom = 1;
10084054ae39SJames Wright     faceMarkerRight  = 2;
10094054ae39SJames Wright     faceMarkerLeft   = 4;
10104054ae39SJames Wright     break;
10114054ae39SJames Wright   case 3:
10124054ae39SJames Wright     faceMarkerBottom = 1;
10134054ae39SJames Wright     faceMarkerTop    = 2;
10144054ae39SJames Wright     faceMarkerFront  = 3;
10154054ae39SJames Wright     faceMarkerBack   = 4;
10164054ae39SJames Wright     faceMarkerRight  = 5;
10174054ae39SJames Wright     faceMarkerLeft   = 6;
10184054ae39SJames Wright     break;
10194054ae39SJames Wright   default:
10204054ae39SJames Wright     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
10214054ae39SJames Wright   }
10224054ae39SJames Wright 
10232b4f33d9SJames Wright   if (faces_is) PetscCall(ISGetLocalSize(faces_is, &num_face));
10242b4f33d9SJames Wright   if (faces_is) PetscCall(ISGetIndices(faces_is, &faces));
10256ff49feeSJames Wright   PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
10266ff49feeSJames Wright   PetscCall(DMGetCoordinateDM(dm, &cdm));
10276ff49feeSJames Wright   PetscCall(DMGetLocalSection(cdm, &csection));
10284054ae39SJames Wright   for (PetscInt f = 0; f < num_face; ++f) {
10296ff49feeSJames Wright     PetscScalar *coords = NULL;
10306ff49feeSJames Wright     PetscInt     face = faces[f], flip = 1, label_value = -1, coords_size;
10314054ae39SJames Wright 
10324054ae39SJames Wright     { // Determine if orientation of face is flipped
10334054ae39SJames Wright       PetscInt        num_cells_support, num_faces, start = -1;
10344054ae39SJames Wright       const PetscInt *orients, *cell_faces, *cells;
10354054ae39SJames Wright 
10364054ae39SJames Wright       PetscCall(DMPlexGetSupport(dm, face, &cells));
10374054ae39SJames Wright       PetscCall(DMPlexGetSupportSize(dm, face, &num_cells_support));
10384054ae39SJames 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);
10394054ae39SJames Wright       PetscCall(DMPlexGetCone(dm, cells[0], &cell_faces));
10404054ae39SJames Wright       PetscCall(DMPlexGetConeSize(dm, cells[0], &num_faces));
10414054ae39SJames Wright       for (PetscInt i = 0; i < num_faces; i++) {
10424054ae39SJames Wright         if (cell_faces[i] == face) start = i;
10434054ae39SJames Wright       }
10444054ae39SJames Wright       PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Could not find face %" PetscInt_FMT " in cone of its support", face);
10454054ae39SJames Wright       PetscCall(DMPlexGetConeOrientation(dm, cells[0], &orients));
10464054ae39SJames Wright       if (orients[start] < 0) flip = -1;
10474054ae39SJames Wright     }
10484054ae39SJames Wright 
10496ff49feeSJames Wright     // Cannot use DMPlexComputeCellGeometryFVM() for high-order geometry, so must calculate normal vectors manually
10506ff49feeSJames Wright     // Use the vertices (depth 0) of coordinate DM to calculate normal vector
10516ff49feeSJames Wright     PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords));
10524054ae39SJames Wright     switch (dim) {
10534054ae39SJames Wright     case 2: {
10546ff49feeSJames Wright       PetscScalar vec[2];
10556ff49feeSJames Wright 
10566ff49feeSJames Wright       for (PetscInt d = 0; d < dim; ++d) vec[d] = flip * (PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]));
10576ff49feeSJames Wright       PetscScalar normal[] = {vec[1], -vec[0]};
10586ff49feeSJames Wright       if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) {
10596ff49feeSJames Wright         label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft;
10604054ae39SJames Wright       } else {
10616ff49feeSJames Wright         label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerTop : faceMarkerBottom;
10624054ae39SJames Wright       }
10634054ae39SJames Wright     } break;
10644054ae39SJames Wright     case 3: {
10656ff49feeSJames Wright       PetscScalar vec1[3], vec2[3], normal[3];
10666ff49feeSJames Wright 
10676ff49feeSJames Wright       for (PetscInt d = 0; d < dim; ++d) {
10686ff49feeSJames Wright         vec1[d] = PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]);
10696ff49feeSJames Wright         vec2[d] = PetscRealPart(coords[2 * dim + d]) - PetscRealPart(coords[1 * dim + d]);
10706ff49feeSJames Wright       }
10716ff49feeSJames Wright 
10726ff49feeSJames Wright       // Calculate normal vector via cross-product
10736ff49feeSJames Wright       normal[0] = flip * ((vec1[1] * vec2[2]) - (vec1[2] * vec2[1]));
10746ff49feeSJames Wright       normal[1] = flip * ((vec1[2] * vec2[0]) - (vec1[0] * vec2[2]));
10756ff49feeSJames Wright       normal[2] = flip * ((vec1[0] * vec2[1]) - (vec1[1] * vec2[0]));
10766ff49feeSJames Wright 
10776ff49feeSJames Wright       if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) {
10786ff49feeSJames Wright         if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[2])) {
10796ff49feeSJames Wright           label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft;
10804054ae39SJames Wright         } else {
10816ff49feeSJames Wright           label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom;
10824054ae39SJames Wright         }
10834054ae39SJames Wright       } else {
10846ff49feeSJames Wright         if (PetscAbsScalar(normal[1]) > PetscAbsScalar(normal[2])) {
10856ff49feeSJames Wright           label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerBack : faceMarkerFront;
10864054ae39SJames Wright         } else {
10876ff49feeSJames Wright           label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom;
10884054ae39SJames Wright         }
10894054ae39SJames Wright       }
10904054ae39SJames Wright     } break;
10914054ae39SJames Wright     }
10924054ae39SJames Wright 
10934054ae39SJames Wright     PetscInt previous_label_value; // always 1 due to DMPlexMarkBoundaryFaces call above
10944054ae39SJames Wright     PetscCall(DMGetLabelValue(dm, "Face Sets", face, &previous_label_value));
10954054ae39SJames Wright     PetscCall(DMClearLabelValue(dm, "Face Sets", face, previous_label_value));
10964054ae39SJames Wright     PetscCall(DMSetLabelValue(dm, "Face Sets", face, label_value));
10976ff49feeSJames Wright     PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords));
10984054ae39SJames Wright   }
10992b4f33d9SJames Wright   if (faces_is) PetscCall(ISRestoreIndices(faces_is, &faces));
11006ff49feeSJames Wright   PetscCall(ISDestroy(&faces_is));
1101d7d2d1d2SJames Wright 
1102d7d2d1d2SJames Wright   // Create Isoperiodic SF from newly-created face labels
1103d7d2d1d2SJames Wright   PetscSF     periodicsfs[3];
1104d7d2d1d2SJames Wright   PetscInt    periodic_sf_index  = 0;
1105d7d2d1d2SJames Wright   PetscScalar transform[3][4][4] = {{{0.}}};
1106d7d2d1d2SJames Wright   for (PetscInt d = 0; d < dim; d++) {
1107d7d2d1d2SJames Wright     IS              donor_is, periodic_is;
1108d7d2d1d2SJames Wright     const PetscInt *donor_faces = NULL, *periodic_faces = NULL;
1109d7d2d1d2SJames Wright     PetscInt        num_donor = 0, num_periodic = 0;
1110d7d2d1d2SJames Wright     PetscSF         centroidsf;
1111d7d2d1d2SJames Wright     PetscReal       donor_to_periodic_distance;
1112d7d2d1d2SJames Wright     const PetscInt  face_pairings[2][3][2] = {
1113d7d2d1d2SJames Wright       // 2D face pairings, {donor, periodic}
1114d7d2d1d2SJames Wright       {{4, 2}, {1, 3}},
1115d7d2d1d2SJames Wright       // 3D face pairings
1116d7d2d1d2SJames Wright       {{5, 6}, {3, 4}, {1, 2}}
1117d7d2d1d2SJames Wright     };
1118d7d2d1d2SJames Wright 
1119d7d2d1d2SJames Wright     if (periodicity[d] != DM_BOUNDARY_PERIODIC) continue;
1120d7d2d1d2SJames Wright     {
1121d7d2d1d2SJames Wright       // Compute centroidsf, which is the mapping from donor faces to periodic faces
1122d7d2d1d2SJames Wright       // Matches the centroid of the faces together, ignoring the periodic direction component (which should not match between donor and periodic face)
1123d7d2d1d2SJames Wright       PetscInt     coords_size, centroid_comps = dim - 1;
1124d7d2d1d2SJames Wright       PetscScalar *coords = NULL;
1125d7d2d1d2SJames Wright       PetscReal   *donor_centroids, *periodic_centroids;
1126d7d2d1d2SJames 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
1127d7d2d1d2SJames Wright 
1128d7d2d1d2SJames Wright       PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][0], &donor_is));
1129d7d2d1d2SJames Wright       PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][1], &periodic_is));
1130d7d2d1d2SJames Wright       if (donor_is) {
1131d7d2d1d2SJames Wright         PetscCall(ISGetLocalSize(donor_is, &num_donor));
1132d7d2d1d2SJames Wright         PetscCall(ISGetIndices(donor_is, &donor_faces));
1133d7d2d1d2SJames Wright       }
1134d7d2d1d2SJames Wright       if (periodic_is) {
1135d7d2d1d2SJames Wright         PetscCall(ISGetLocalSize(periodic_is, &num_periodic));
1136d7d2d1d2SJames Wright         PetscCall(ISGetIndices(periodic_is, &periodic_faces));
1137d7d2d1d2SJames Wright       }
1138d7d2d1d2SJames Wright       PetscCall(PetscCalloc2(num_donor * centroid_comps, &donor_centroids, num_periodic * centroid_comps, &periodic_centroids));
1139d7d2d1d2SJames Wright       for (PetscInt f = 0; f < num_donor; f++) {
1140d7d2d1d2SJames Wright         PetscInt face = donor_faces[f], num_coords;
1141d7d2d1d2SJames Wright         PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords));
1142d7d2d1d2SJames Wright         num_coords = coords_size / dim;
1143d7d2d1d2SJames Wright         for (PetscInt c = 0; c < num_coords; c++) {
1144d7d2d1d2SJames Wright           PetscInt comp_index = 0;
1145d7d2d1d2SJames Wright           loc_periodic[0]     = PetscRealPart(coords[c * dim + d]);
1146d7d2d1d2SJames Wright           for (PetscInt i = 0; i < dim; i++) {
1147d7d2d1d2SJames Wright             if (i == d) continue; // Periodic direction not used for centroid calculation
1148d7d2d1d2SJames Wright             donor_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords;
1149d7d2d1d2SJames Wright             comp_index++;
1150d7d2d1d2SJames Wright           }
1151d7d2d1d2SJames Wright         }
1152d7d2d1d2SJames Wright         PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords));
1153d7d2d1d2SJames Wright       }
1154d7d2d1d2SJames Wright 
1155d7d2d1d2SJames Wright       for (PetscInt f = 0; f < num_periodic; f++) {
1156d7d2d1d2SJames Wright         PetscInt face = periodic_faces[f], num_coords;
1157d7d2d1d2SJames Wright         PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords));
1158d7d2d1d2SJames Wright         num_coords = coords_size / dim;
1159d7d2d1d2SJames Wright         for (PetscInt c = 0; c < num_coords; c++) {
1160d7d2d1d2SJames Wright           PetscInt comp_index = 0;
1161d7d2d1d2SJames Wright           loc_periodic[1]     = PetscRealPart(coords[c * dim + d]);
1162d7d2d1d2SJames Wright           for (PetscInt i = 0; i < dim; i++) {
1163d7d2d1d2SJames Wright             if (i == d) continue; // Periodic direction not used for centroid calculation
1164d7d2d1d2SJames Wright             periodic_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords;
1165d7d2d1d2SJames Wright             comp_index++;
1166d7d2d1d2SJames Wright           }
1167d7d2d1d2SJames Wright         }
1168d7d2d1d2SJames Wright         PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords));
1169d7d2d1d2SJames Wright       }
1170d7d2d1d2SJames Wright       PetscCallMPI(MPIU_Allreduce(loc_periodic, loc_periodic_global, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm)));
1171d7d2d1d2SJames Wright       donor_to_periodic_distance = loc_periodic_global[1] - loc_periodic_global[0];
1172d7d2d1d2SJames Wright 
1173d7d2d1d2SJames Wright       PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &centroidsf));
1174d7d2d1d2SJames Wright       PetscCall(PetscSFSetGraphFromCoordinates(centroidsf, num_donor, num_periodic, centroid_comps, 1e-10, donor_centroids, periodic_centroids));
1175d7d2d1d2SJames Wright       PetscCall(PetscSFViewFromOptions(centroidsf, NULL, "-dm_plex_box_label_centroid_sf_view"));
1176d7d2d1d2SJames Wright       PetscCall(PetscFree2(donor_centroids, periodic_centroids));
1177d7d2d1d2SJames Wright     }
1178d7d2d1d2SJames Wright 
1179d7d2d1d2SJames Wright     { // Create Isoperiodic SF using centroidsSF
1180d7d2d1d2SJames Wright       PetscInt           pStart, pEnd;
1181d7d2d1d2SJames Wright       PetscInt          *leaf_faces;
1182d7d2d1d2SJames Wright       const PetscSFNode *firemote;
1183d7d2d1d2SJames Wright       PetscSFNode       *isoperiodic_leaves;
1184d7d2d1d2SJames Wright 
1185d7d2d1d2SJames Wright       PetscCall(PetscMalloc1(num_periodic, &leaf_faces));
1186d7d2d1d2SJames Wright       PetscCall(PetscSFBcastBegin(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE));
1187d7d2d1d2SJames Wright       PetscCall(PetscSFBcastEnd(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE));
1188d7d2d1d2SJames Wright 
1189d7d2d1d2SJames Wright       PetscCall(PetscMalloc1(num_periodic, &isoperiodic_leaves));
1190d7d2d1d2SJames Wright       PetscCall(PetscSFGetGraph(centroidsf, NULL, NULL, NULL, &firemote));
1191d7d2d1d2SJames Wright       for (PetscInt l = 0; l < num_periodic; ++l) {
1192d7d2d1d2SJames Wright         isoperiodic_leaves[l].index = leaf_faces[l];
1193d7d2d1d2SJames Wright         isoperiodic_leaves[l].rank  = firemote[l].rank;
1194d7d2d1d2SJames Wright       }
1195d7d2d1d2SJames Wright 
1196d7d2d1d2SJames Wright       PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
1197d7d2d1d2SJames Wright       PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &periodicsfs[periodic_sf_index]));
1198d7d2d1d2SJames Wright       PetscCall(PetscSFSetGraph(periodicsfs[periodic_sf_index], pEnd - pStart, num_periodic, (PetscInt *)periodic_faces, PETSC_COPY_VALUES, isoperiodic_leaves, PETSC_OWN_POINTER));
1199d7d2d1d2SJames Wright       PetscCall(PetscSFViewFromOptions(periodicsfs[periodic_sf_index], NULL, "-dm_plex_box_label_periodic_sf_view"));
1200d7d2d1d2SJames Wright       PetscCall(PetscFree(leaf_faces));
1201d7d2d1d2SJames Wright     }
1202d7d2d1d2SJames Wright 
1203d7d2d1d2SJames Wright     transform[periodic_sf_index][0][0] = 1;
1204d7d2d1d2SJames Wright     transform[periodic_sf_index][1][1] = 1;
1205d7d2d1d2SJames Wright     transform[periodic_sf_index][2][2] = 1;
1206d7d2d1d2SJames Wright     transform[periodic_sf_index][3][3] = 1;
1207d7d2d1d2SJames Wright     transform[periodic_sf_index][d][3] = donor_to_periodic_distance;
1208d7d2d1d2SJames Wright 
1209d7d2d1d2SJames Wright     periodic_sf_index++;
1210d7d2d1d2SJames Wright     PetscCall(PetscSFDestroy(&centroidsf));
1211d7d2d1d2SJames Wright     if (donor_is) {
1212d7d2d1d2SJames Wright       PetscCall(ISRestoreIndices(donor_is, &donor_faces));
1213d7d2d1d2SJames Wright       PetscCall(ISDestroy(&donor_is));
1214d7d2d1d2SJames Wright     }
1215d7d2d1d2SJames Wright     if (periodic_is) {
1216d7d2d1d2SJames Wright       PetscCall(ISRestoreIndices(periodic_is, &periodic_faces));
1217d7d2d1d2SJames Wright       PetscCall(ISDestroy(&periodic_is));
1218d7d2d1d2SJames Wright     }
1219d7d2d1d2SJames Wright     PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][0]));
1220d7d2d1d2SJames Wright     PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][1]));
1221d7d2d1d2SJames Wright   }
1222d7d2d1d2SJames Wright   PetscCall(DMPlexSetIsoperiodicFaceSF(dm, periodic_sf_index, periodicsfs));
1223d7d2d1d2SJames Wright   PetscCall(DMPlexSetIsoperiodicFaceTransform(dm, periodic_sf_index, (const PetscScalar *)transform));
1224d7d2d1d2SJames Wright   for (PetscInt p = 0; p < periodic_sf_index; p++) PetscCall(PetscSFDestroy(&periodicsfs[p]));
1225d7d2d1d2SJames Wright 
1226d7d2d1d2SJames Wright   { // Update coordinate DM with new Face Sets label
1227d7d2d1d2SJames Wright     DM      cdm;
1228d7d2d1d2SJames Wright     DMLabel oldFaceSets, newFaceSets;
1229d7d2d1d2SJames Wright     PetscCall(DMGetCoordinateDM(dm, &cdm));
1230d7d2d1d2SJames Wright     PetscCall(DMGetLabel(cdm, "Face Sets", &oldFaceSets));
1231d7d2d1d2SJames Wright     if (oldFaceSets) PetscCall(DMRemoveLabelBySelf(cdm, &oldFaceSets, PETSC_FALSE));
1232d7d2d1d2SJames Wright     PetscCall(DMLabelDuplicate(label, &newFaceSets));
1233d7d2d1d2SJames Wright     PetscCall(DMAddLabel(cdm, newFaceSets));
1234d7d2d1d2SJames Wright     PetscCall(DMLabelDestroy(&newFaceSets));
1235d7d2d1d2SJames Wright   }
12364054ae39SJames Wright   PetscFunctionReturn(PETSC_SUCCESS);
12374054ae39SJames Wright }
12384054ae39SJames Wright 
1239*d698cf03SStefano Zampini static PetscErrorCode DMPlexCreateSquareMesh_Simplex_CrissCross(DM dm, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType bd[])
1240*d698cf03SStefano Zampini {
1241*d698cf03SStefano Zampini   PetscInt       markerTop = 1, faceMarkerTop = 3;
1242*d698cf03SStefano Zampini   PetscInt       markerBottom = 1, faceMarkerBottom = 1;
1243*d698cf03SStefano Zampini   PetscInt       markerRight = 1, faceMarkerRight = 2;
1244*d698cf03SStefano Zampini   PetscInt       markerLeft = 1, faceMarkerLeft = 4;
1245*d698cf03SStefano Zampini   PetscBool      markerSeparate = PETSC_FALSE;
1246*d698cf03SStefano Zampini   DMBoundaryType bdX = bd[0], bdY = bd[1];
1247*d698cf03SStefano Zampini   PetscMPIInt    rank;
1248*d698cf03SStefano Zampini 
1249*d698cf03SStefano Zampini   PetscFunctionBegin;
1250*d698cf03SStefano Zampini   PetscCheck(bdX == DM_BOUNDARY_NONE || bdX == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdX]);
1251*d698cf03SStefano Zampini   PetscCheck(bdY == DM_BOUNDARY_NONE || bdY == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdY]);
1252*d698cf03SStefano Zampini   PetscCall(DMSetDimension(dm, 2));
1253*d698cf03SStefano Zampini   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
1254*d698cf03SStefano Zampini   PetscCall(DMCreateLabel(dm, "marker"));
1255*d698cf03SStefano Zampini   PetscCall(DMCreateLabel(dm, "Face Sets"));
1256*d698cf03SStefano Zampini   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
1257*d698cf03SStefano Zampini   if (markerSeparate) {
1258*d698cf03SStefano Zampini     markerBottom = faceMarkerBottom;
1259*d698cf03SStefano Zampini     markerTop    = faceMarkerTop;
1260*d698cf03SStefano Zampini     markerRight  = faceMarkerRight;
1261*d698cf03SStefano Zampini     markerLeft   = faceMarkerLeft;
1262*d698cf03SStefano Zampini   }
1263*d698cf03SStefano Zampini   {
1264*d698cf03SStefano Zampini     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
1265*d698cf03SStefano Zampini     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
1266*d698cf03SStefano Zampini     const PetscInt numZEdges    = rank == 0 ? 4 * edges[0] * edges[1] : 0; /* Z-edges are the 4 internal edges per cell */
1267*d698cf03SStefano Zampini     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC ? edges[0] : edges[0] + 1) : 0;
1268*d698cf03SStefano Zampini     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC ? edges[1] : edges[1] + 1) : 0;
1269*d698cf03SStefano Zampini     const PetscInt numZVertices = rank == 0 ? edges[0] * edges[1] : 0;
1270*d698cf03SStefano Zampini     const PetscInt numCells     = 4 * numXEdges * numYEdges;
1271*d698cf03SStefano Zampini     const PetscInt numTotXEdges = numXEdges * numYVertices;
1272*d698cf03SStefano Zampini     const PetscInt numTotYEdges = numYEdges * numXVertices;
1273*d698cf03SStefano Zampini     const PetscInt numVertices  = numXVertices * numYVertices + numZVertices;
1274*d698cf03SStefano Zampini     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numZEdges;
1275*d698cf03SStefano Zampini     const PetscInt firstVertex  = numCells;
1276*d698cf03SStefano Zampini     const PetscInt firstXEdge   = numCells + numVertices;
1277*d698cf03SStefano Zampini     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
1278*d698cf03SStefano Zampini     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
1279*d698cf03SStefano Zampini     Vec            coordinates;
1280*d698cf03SStefano Zampini     PetscSection   coordSection;
1281*d698cf03SStefano Zampini     PetscScalar   *coords;
1282*d698cf03SStefano Zampini     PetscInt       coordSize;
1283*d698cf03SStefano Zampini     PetscInt       v, vx, vy;
1284*d698cf03SStefano Zampini     PetscInt       c, e, ex, ey;
1285*d698cf03SStefano Zampini 
1286*d698cf03SStefano Zampini     PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVertices));
1287*d698cf03SStefano Zampini     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 3));
1288*d698cf03SStefano Zampini     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
1289*d698cf03SStefano Zampini     PetscCall(DMSetUp(dm));
1290*d698cf03SStefano Zampini 
1291*d698cf03SStefano Zampini     /* Build cells and Z-edges */
1292*d698cf03SStefano Zampini     for (ey = 0; ey < numYEdges; ++ey) {
1293*d698cf03SStefano Zampini       for (ex = 0; ex < numXEdges; ++ex) {
1294*d698cf03SStefano Zampini         const PetscInt exp1 = (ex + 1) % numXVertices;
1295*d698cf03SStefano Zampini         const PetscInt eyp1 = (ey + 1) % numYVertices;
1296*d698cf03SStefano Zampini         const PetscInt ez   = firstZEdge + 4 * (ey * numXEdges + ex);
1297*d698cf03SStefano Zampini         const PetscInt vc   = firstVertex + numXVertices * numYVertices + ey * numXEdges + ex;
1298*d698cf03SStefano Zampini         const PetscInt v0   = firstVertex + ey * numXVertices + ex;
1299*d698cf03SStefano Zampini         const PetscInt v1   = firstVertex + ey * numXVertices + exp1;
1300*d698cf03SStefano Zampini         const PetscInt v2   = firstVertex + eyp1 * numXVertices + exp1;
1301*d698cf03SStefano Zampini         const PetscInt v3   = firstVertex + eyp1 * numXVertices + ex;
1302*d698cf03SStefano Zampini         const PetscInt e0   = firstXEdge + ey * numXEdges + ex;
1303*d698cf03SStefano Zampini         const PetscInt e1   = firstYEdge + exp1 * numYEdges + ey;
1304*d698cf03SStefano Zampini         const PetscInt e2   = firstXEdge + eyp1 * numXEdges + ex;
1305*d698cf03SStefano Zampini         const PetscInt e3   = firstYEdge + ex * numYEdges + ey;
1306*d698cf03SStefano Zampini 
1307*d698cf03SStefano Zampini         const PetscInt cones[] = {ez, e0, ez + 1, ez + 1, e1, ez + 2, ez + 2, e2, ez + 3, ez + 3, e3, ez};
1308*d698cf03SStefano Zampini         const PetscInt ornts[] = {-1, 0, 0, -1, 0, 0, -1, -1, 0, -1, -1, 0};
1309*d698cf03SStefano Zampini         const PetscInt verts[] = {v0, vc, v1, vc, v2, vc, v3, vc};
1310*d698cf03SStefano Zampini 
1311*d698cf03SStefano Zampini         for (c = 0; c < 4; c++) {
1312*d698cf03SStefano Zampini           PetscInt cell = 4 * (ey * numXEdges + ex) + c;
1313*d698cf03SStefano Zampini           PetscInt edge = ez + c;
1314*d698cf03SStefano Zampini 
1315*d698cf03SStefano Zampini           PetscCall(DMPlexSetCone(dm, cell, cones + 3 * c));
1316*d698cf03SStefano Zampini           PetscCall(DMPlexSetConeOrientation(dm, cell, ornts + 3 * c));
1317*d698cf03SStefano Zampini           PetscCall(DMPlexSetCone(dm, edge, verts + 2 * c));
1318*d698cf03SStefano Zampini         }
1319*d698cf03SStefano Zampini       }
1320*d698cf03SStefano Zampini     }
1321*d698cf03SStefano Zampini 
1322*d698cf03SStefano Zampini     /* Build Y edges*/
1323*d698cf03SStefano Zampini     for (vx = 0; vx < numXVertices; vx++) {
1324*d698cf03SStefano Zampini       for (ey = 0; ey < numYEdges; ey++) {
1325*d698cf03SStefano Zampini         const PetscInt edge   = firstYEdge + vx * numYEdges + ey;
1326*d698cf03SStefano Zampini         const PetscInt v0     = firstVertex + ey * numXVertices + vx;
1327*d698cf03SStefano Zampini         const PetscInt v1     = firstVertex + ((ey + 1) % numYVertices) * numXVertices + vx;
1328*d698cf03SStefano Zampini         const PetscInt cone[] = {v0, v1};
1329*d698cf03SStefano Zampini 
1330*d698cf03SStefano Zampini         PetscCall(DMPlexSetCone(dm, edge, cone));
1331*d698cf03SStefano Zampini         if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
1332*d698cf03SStefano Zampini           if (vx == numXVertices - 1) {
1333*d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
1334*d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1335*d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1336*d698cf03SStefano Zampini             if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1337*d698cf03SStefano Zampini           } else if (vx == 0) {
1338*d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
1339*d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1340*d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1341*d698cf03SStefano Zampini             if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
1342*d698cf03SStefano Zampini           }
1343*d698cf03SStefano Zampini         }
1344*d698cf03SStefano Zampini       }
1345*d698cf03SStefano Zampini     }
1346*d698cf03SStefano Zampini 
1347*d698cf03SStefano Zampini     /* Build X edges*/
1348*d698cf03SStefano Zampini     for (vy = 0; vy < numYVertices; vy++) {
1349*d698cf03SStefano Zampini       for (ex = 0; ex < numXEdges; ex++) {
1350*d698cf03SStefano Zampini         const PetscInt edge   = firstXEdge + vy * numXEdges + ex;
1351*d698cf03SStefano Zampini         const PetscInt v0     = firstVertex + vy * numXVertices + ex;
1352*d698cf03SStefano Zampini         const PetscInt v1     = firstVertex + vy * numXVertices + (ex + 1) % numXVertices;
1353*d698cf03SStefano Zampini         const PetscInt cone[] = {v0, v1};
1354*d698cf03SStefano Zampini 
1355*d698cf03SStefano Zampini         PetscCall(DMPlexSetCone(dm, edge, cone));
1356*d698cf03SStefano Zampini         if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
1357*d698cf03SStefano Zampini           if (vy == numYVertices - 1) {
1358*d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
1359*d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1360*d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1361*d698cf03SStefano Zampini             if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1362*d698cf03SStefano Zampini           } else if (vy == 0) {
1363*d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
1364*d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1365*d698cf03SStefano Zampini             PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1366*d698cf03SStefano Zampini             if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
1367*d698cf03SStefano Zampini           }
1368*d698cf03SStefano Zampini         }
1369*d698cf03SStefano Zampini       }
1370*d698cf03SStefano Zampini     }
1371*d698cf03SStefano Zampini 
1372*d698cf03SStefano Zampini     /* Compute support, stratify, and celltype label */
1373*d698cf03SStefano Zampini     PetscCall(DMPlexSymmetrize(dm));
1374*d698cf03SStefano Zampini     PetscCall(DMPlexStratify(dm));
1375*d698cf03SStefano Zampini     PetscCall(DMPlexComputeCellTypes(dm));
1376*d698cf03SStefano Zampini 
1377*d698cf03SStefano Zampini     /* Build coordinates */
1378*d698cf03SStefano Zampini     PetscCall(DMGetCoordinateSection(dm, &coordSection));
1379*d698cf03SStefano Zampini     PetscCall(PetscSectionSetNumFields(coordSection, 1));
1380*d698cf03SStefano Zampini     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2));
1381*d698cf03SStefano Zampini     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
1382*d698cf03SStefano Zampini     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
1383*d698cf03SStefano Zampini       PetscCall(PetscSectionSetDof(coordSection, v, 2));
1384*d698cf03SStefano Zampini       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2));
1385*d698cf03SStefano Zampini     }
1386*d698cf03SStefano Zampini     PetscCall(PetscSectionSetUp(coordSection));
1387*d698cf03SStefano Zampini     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
1388*d698cf03SStefano Zampini     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
1389*d698cf03SStefano Zampini     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
1390*d698cf03SStefano Zampini     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
1391*d698cf03SStefano Zampini     PetscCall(VecSetBlockSize(coordinates, 2));
1392*d698cf03SStefano Zampini     PetscCall(VecSetType(coordinates, VECSTANDARD));
1393*d698cf03SStefano Zampini     PetscCall(VecGetArray(coordinates, &coords));
1394*d698cf03SStefano Zampini     for (vy = 0; vy < numYVertices; ++vy) {
1395*d698cf03SStefano Zampini       for (vx = 0; vx < numXVertices; ++vx) {
1396*d698cf03SStefano Zampini         coords[2 * (vy * numXVertices + vx) + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
1397*d698cf03SStefano Zampini         coords[2 * (vy * numXVertices + vx) + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
1398*d698cf03SStefano Zampini       }
1399*d698cf03SStefano Zampini     }
1400*d698cf03SStefano Zampini     for (ey = 0; ey < numYEdges; ++ey) {
1401*d698cf03SStefano Zampini       for (ex = 0; ex < numXEdges; ++ex) {
1402*d698cf03SStefano Zampini         const PetscInt c = ey * numXEdges + ex + numYVertices * numXVertices;
1403*d698cf03SStefano Zampini 
1404*d698cf03SStefano Zampini         coords[2 * c + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * (ex + 0.5);
1405*d698cf03SStefano Zampini         coords[2 * c + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * (ey + 0.5);
1406*d698cf03SStefano Zampini       }
1407*d698cf03SStefano Zampini     }
1408*d698cf03SStefano Zampini     PetscCall(VecRestoreArray(coordinates, &coords));
1409*d698cf03SStefano Zampini     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
1410*d698cf03SStefano Zampini     PetscCall(VecDestroy(&coordinates));
1411*d698cf03SStefano Zampini 
1412*d698cf03SStefano Zampini     /* handle periodic BC */
1413*d698cf03SStefano Zampini     if (bdX == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_PERIODIC) {
1414*d698cf03SStefano Zampini       PetscReal L[2]       = {-1., -1.};
1415*d698cf03SStefano Zampini       PetscReal maxCell[2] = {-1., -1.};
1416*d698cf03SStefano Zampini 
1417*d698cf03SStefano Zampini       for (PetscInt d = 0; d < 2; ++d) {
1418*d698cf03SStefano Zampini         if (bd[d] != DM_BOUNDARY_NONE) {
1419*d698cf03SStefano Zampini           L[d]       = upper[d] - lower[d];
1420*d698cf03SStefano Zampini           maxCell[d] = 1.1 * (L[d] / PetscMax(1, edges[d]));
1421*d698cf03SStefano Zampini         }
1422*d698cf03SStefano Zampini       }
1423*d698cf03SStefano Zampini       PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1424*d698cf03SStefano Zampini     }
1425*d698cf03SStefano Zampini   }
1426*d698cf03SStefano Zampini   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
1427*d698cf03SStefano Zampini   PetscFunctionReturn(PETSC_SUCCESS);
1428*d698cf03SStefano Zampini }
1429*d698cf03SStefano Zampini 
1430d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
1431d71ae5a4SJacob Faibussowitsch {
14329318fe57SMatthew G. Knepley   DM        boundary, vol;
1433c22d3578SMatthew G. Knepley   DMLabel   bdlabel;
1434*d698cf03SStefano Zampini   PetscBool crisscross = PETSC_FALSE;
1435d6218766SMatthew G. Knepley 
1436d6218766SMatthew G. Knepley   PetscFunctionBegin;
14374f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
1438*d698cf03SStefano Zampini   if (dim == 2) PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_box_crisscross", &crisscross, NULL));
1439*d698cf03SStefano Zampini   if (crisscross) {
1440*d698cf03SStefano Zampini     PetscCall(DMPlexCreateSquareMesh_Simplex_CrissCross(dm, faces, lower, upper, periodicity));
1441*d698cf03SStefano Zampini   } else {
1442c22d3578SMatthew 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");
14439566063dSJacob Faibussowitsch     PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary));
14449566063dSJacob Faibussowitsch     PetscCall(DMSetType(boundary, DMPLEX));
1445*d698cf03SStefano Zampini     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)boundary, ((PetscObject)dm)->prefix));
14469566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE));
14479566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol));
1448c22d3578SMatthew G. Knepley     PetscCall(DMGetLabel(vol, "marker", &bdlabel));
1449c22d3578SMatthew G. Knepley     if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel));
14505de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol));
145169d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &vol));
1452*d698cf03SStefano Zampini     PetscCall(DMDestroy(&boundary));
1453*d698cf03SStefano Zampini   }
14544054ae39SJames Wright   if (interpolate) {
14554054ae39SJames Wright     PetscCall(DMPlexInterpolateInPlace_Internal(dm));
1456d7d2d1d2SJames Wright     PetscCall(DMPlexSetBoxLabel_Internal(dm, periodicity));
14574054ae39SJames Wright   }
14583ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1459d6218766SMatthew G. Knepley }
1460d6218766SMatthew G. Knepley 
1461d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ)
1462d71ae5a4SJacob Faibussowitsch {
1463ed0e4b50SMatthew G. Knepley   DMLabel     cutLabel  = NULL;
1464f4eb4c5dSMatthew G. Knepley   PetscInt    markerTop = 1, faceMarkerTop = 1;
1465f4eb4c5dSMatthew G. Knepley   PetscInt    markerBottom = 1, faceMarkerBottom = 1;
1466f4eb4c5dSMatthew G. Knepley   PetscInt    markerFront = 1, faceMarkerFront = 1;
1467f4eb4c5dSMatthew G. Knepley   PetscInt    markerBack = 1, faceMarkerBack = 1;
1468f4eb4c5dSMatthew G. Knepley   PetscInt    markerRight = 1, faceMarkerRight = 1;
1469f4eb4c5dSMatthew G. Knepley   PetscInt    markerLeft = 1, faceMarkerLeft = 1;
14703dfda0b1SToby Isaac   PetscInt    dim;
1471d8211ee3SMatthew G. Knepley   PetscBool   markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE;
14723dfda0b1SToby Isaac   PetscMPIInt rank;
14733dfda0b1SToby Isaac 
14743dfda0b1SToby Isaac   PetscFunctionBegin;
14759566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
14769566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
14779566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
14789566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
14799566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
14809371c9d4SSatish 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) {
14819371c9d4SSatish Balay     if (cutMarker) {
14829371c9d4SSatish Balay       PetscCall(DMCreateLabel(dm, "periodic_cut"));
14839371c9d4SSatish Balay       PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
14849371c9d4SSatish Balay     }
1485d8211ee3SMatthew G. Knepley   }
14863dfda0b1SToby Isaac   switch (dim) {
14873dfda0b1SToby Isaac   case 2:
1488f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 3;
1489f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
1490f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 2;
1491f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 4;
14923dfda0b1SToby Isaac     break;
14933dfda0b1SToby Isaac   case 3:
1494f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
1495f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 2;
1496f4eb4c5dSMatthew G. Knepley     faceMarkerFront  = 3;
1497f4eb4c5dSMatthew G. Knepley     faceMarkerBack   = 4;
1498f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 5;
1499f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 6;
15003dfda0b1SToby Isaac     break;
1501d71ae5a4SJacob Faibussowitsch   default:
1502d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
15033dfda0b1SToby Isaac   }
15049566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
1505f4eb4c5dSMatthew G. Knepley   if (markerSeparate) {
1506f4eb4c5dSMatthew G. Knepley     markerBottom = faceMarkerBottom;
1507f4eb4c5dSMatthew G. Knepley     markerTop    = faceMarkerTop;
1508f4eb4c5dSMatthew G. Knepley     markerFront  = faceMarkerFront;
1509f4eb4c5dSMatthew G. Knepley     markerBack   = faceMarkerBack;
1510f4eb4c5dSMatthew G. Knepley     markerRight  = faceMarkerRight;
1511f4eb4c5dSMatthew G. Knepley     markerLeft   = faceMarkerLeft;
15123dfda0b1SToby Isaac   }
15133dfda0b1SToby Isaac   {
1514dd400576SPatrick Sanan     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
1515dd400576SPatrick Sanan     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
1516dd400576SPatrick Sanan     const PetscInt numZEdges    = rank == 0 ? edges[2] : 0;
1517dd400576SPatrick Sanan     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0;
1518dd400576SPatrick Sanan     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0;
1519dd400576SPatrick Sanan     const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0;
15203dfda0b1SToby Isaac     const PetscInt numCells     = numXEdges * numYEdges * numZEdges;
15213dfda0b1SToby Isaac     const PetscInt numXFaces    = numYEdges * numZEdges;
15223dfda0b1SToby Isaac     const PetscInt numYFaces    = numXEdges * numZEdges;
15233dfda0b1SToby Isaac     const PetscInt numZFaces    = numXEdges * numYEdges;
15243dfda0b1SToby Isaac     const PetscInt numTotXFaces = numXVertices * numXFaces;
15253dfda0b1SToby Isaac     const PetscInt numTotYFaces = numYVertices * numYFaces;
15263dfda0b1SToby Isaac     const PetscInt numTotZFaces = numZVertices * numZFaces;
15273dfda0b1SToby Isaac     const PetscInt numFaces     = numTotXFaces + numTotYFaces + numTotZFaces;
15283dfda0b1SToby Isaac     const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices;
15293dfda0b1SToby Isaac     const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices;
15303dfda0b1SToby Isaac     const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices;
15313dfda0b1SToby Isaac     const PetscInt numVertices  = numXVertices * numYVertices * numZVertices;
15323dfda0b1SToby Isaac     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numTotZEdges;
15333dfda0b1SToby Isaac     const PetscInt firstVertex  = (dim == 2) ? numFaces : numCells;
15343dfda0b1SToby Isaac     const PetscInt firstXFace   = (dim == 2) ? 0 : numCells + numVertices;
15353dfda0b1SToby Isaac     const PetscInt firstYFace   = firstXFace + numTotXFaces;
15363dfda0b1SToby Isaac     const PetscInt firstZFace   = firstYFace + numTotYFaces;
15373dfda0b1SToby Isaac     const PetscInt firstXEdge   = numCells + numFaces + numVertices;
15383dfda0b1SToby Isaac     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
15393dfda0b1SToby Isaac     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
15403dfda0b1SToby Isaac     Vec            coordinates;
15413dfda0b1SToby Isaac     PetscSection   coordSection;
15423dfda0b1SToby Isaac     PetscScalar   *coords;
15433dfda0b1SToby Isaac     PetscInt       coordSize;
15443dfda0b1SToby Isaac     PetscInt       v, vx, vy, vz;
15453dfda0b1SToby Isaac     PetscInt       c, f, fx, fy, fz, e, ex, ey, ez;
15463dfda0b1SToby Isaac 
15479566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices));
154848a46eb9SPierre Jolivet     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
154948a46eb9SPierre Jolivet     for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
155048a46eb9SPierre Jolivet     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
15519566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
15523dfda0b1SToby Isaac     /* Build cells */
15533dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
15543dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
15553dfda0b1SToby Isaac         for (fx = 0; fx < numXEdges; ++fx) {
15563dfda0b1SToby Isaac           PetscInt cell  = (fz * numYEdges + fy) * numXEdges + fx;
15573dfda0b1SToby Isaac           PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
15583dfda0b1SToby Isaac           PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices);
15593dfda0b1SToby Isaac           PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
15603dfda0b1SToby Isaac           PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices);
15613dfda0b1SToby Isaac           PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
15623dfda0b1SToby Isaac           PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices);
15633dfda0b1SToby Isaac           /* B,  T,  F,  K,  R,  L */
1564b5a892a1SMatthew G. Knepley           PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */
156542206facSLisandro Dalcin           PetscInt cone[6];
15663dfda0b1SToby Isaac 
15673dfda0b1SToby Isaac           /* no boundary twisting in 3D */
15689371c9d4SSatish Balay           cone[0] = faceB;
15699371c9d4SSatish Balay           cone[1] = faceT;
15709371c9d4SSatish Balay           cone[2] = faceF;
15719371c9d4SSatish Balay           cone[3] = faceK;
15729371c9d4SSatish Balay           cone[4] = faceR;
15739371c9d4SSatish Balay           cone[5] = faceL;
15749566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, cell, cone));
15759566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, cell, ornt));
15769566063dSJacob Faibussowitsch           if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
15779566063dSJacob Faibussowitsch           if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
15789566063dSJacob Faibussowitsch           if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
15793dfda0b1SToby Isaac         }
15803dfda0b1SToby Isaac       }
15813dfda0b1SToby Isaac     }
15823dfda0b1SToby Isaac     /* Build x faces */
15833dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
15843dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
15853dfda0b1SToby Isaac         for (fx = 0; fx < numXVertices; ++fx) {
15863dfda0b1SToby Isaac           PetscInt face    = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
15873dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
15883dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz;
15893dfda0b1SToby Isaac           PetscInt edgeB   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
15903dfda0b1SToby Isaac           PetscInt edgeT   = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy;
1591b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
15923dfda0b1SToby Isaac           PetscInt cone[4];
15933dfda0b1SToby Isaac 
15943dfda0b1SToby Isaac           if (dim == 3) {
15953dfda0b1SToby Isaac             /* markers */
15963dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
15973dfda0b1SToby Isaac               if (fx == numXVertices - 1) {
15989566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight));
15999566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerRight));
16009371c9d4SSatish Balay               } else if (fx == 0) {
16019566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft));
16029566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft));
16033dfda0b1SToby Isaac               }
16043dfda0b1SToby Isaac             }
16053dfda0b1SToby Isaac           }
16069371c9d4SSatish Balay           cone[0] = edgeB;
16079371c9d4SSatish Balay           cone[1] = edgeR;
16089371c9d4SSatish Balay           cone[2] = edgeT;
16099371c9d4SSatish Balay           cone[3] = edgeL;
16109566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
16119566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
16123dfda0b1SToby Isaac         }
16133dfda0b1SToby Isaac       }
16143dfda0b1SToby Isaac     }
16153dfda0b1SToby Isaac     /* Build y faces */
16163dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
161742206facSLisandro Dalcin       for (fx = 0; fx < numXEdges; ++fx) {
16183dfda0b1SToby Isaac         for (fy = 0; fy < numYVertices; ++fy) {
16193dfda0b1SToby Isaac           PetscInt face    = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
16203dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
16213dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz;
16223dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
16233dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx;
1624b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
16253dfda0b1SToby Isaac           PetscInt cone[4];
16263dfda0b1SToby Isaac 
16273dfda0b1SToby Isaac           if (dim == 3) {
16283dfda0b1SToby Isaac             /* markers */
16293dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
16303dfda0b1SToby Isaac               if (fy == numYVertices - 1) {
16319566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack));
16329566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBack));
16339371c9d4SSatish Balay               } else if (fy == 0) {
16349566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront));
16359566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerFront));
16363dfda0b1SToby Isaac               }
16373dfda0b1SToby Isaac             }
16383dfda0b1SToby Isaac           }
16399371c9d4SSatish Balay           cone[0] = edgeB;
16409371c9d4SSatish Balay           cone[1] = edgeR;
16419371c9d4SSatish Balay           cone[2] = edgeT;
16429371c9d4SSatish Balay           cone[3] = edgeL;
16439566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
16449566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
16453dfda0b1SToby Isaac         }
16463dfda0b1SToby Isaac       }
16473dfda0b1SToby Isaac     }
16483dfda0b1SToby Isaac     /* Build z faces */
16493dfda0b1SToby Isaac     for (fy = 0; fy < numYEdges; ++fy) {
16503dfda0b1SToby Isaac       for (fx = 0; fx < numXEdges; ++fx) {
16513dfda0b1SToby Isaac         for (fz = 0; fz < numZVertices; fz++) {
16523dfda0b1SToby Isaac           PetscInt face    = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
16533dfda0b1SToby Isaac           PetscInt edgeL   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
16543dfda0b1SToby Isaac           PetscInt edgeR   = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy;
16553dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
16563dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx;
1657b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
16583dfda0b1SToby Isaac           PetscInt cone[4];
16593dfda0b1SToby Isaac 
16603dfda0b1SToby Isaac           if (dim == 2) {
16619371c9d4SSatish Balay             if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) {
16629371c9d4SSatish Balay               edgeR += numYEdges - 1 - 2 * fy;
16639371c9d4SSatish Balay               ornt[1] = -1;
16649371c9d4SSatish Balay             }
16659371c9d4SSatish Balay             if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) {
16669371c9d4SSatish Balay               edgeT += numXEdges - 1 - 2 * fx;
16679371c9d4SSatish Balay               ornt[2] = 0;
16689371c9d4SSatish Balay             }
16699566063dSJacob Faibussowitsch             if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
16709566063dSJacob Faibussowitsch             if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
1671d1c88043SMatthew G. Knepley           } else {
16723dfda0b1SToby Isaac             /* markers */
16733dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
16743dfda0b1SToby Isaac               if (fz == numZVertices - 1) {
16759566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop));
16769566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerTop));
16779371c9d4SSatish Balay               } else if (fz == 0) {
16789566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom));
16799566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom));
16803dfda0b1SToby Isaac               }
16813dfda0b1SToby Isaac             }
16823dfda0b1SToby Isaac           }
16839371c9d4SSatish Balay           cone[0] = edgeB;
16849371c9d4SSatish Balay           cone[1] = edgeR;
16859371c9d4SSatish Balay           cone[2] = edgeT;
16869371c9d4SSatish Balay           cone[3] = edgeL;
16879566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
16889566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
16893dfda0b1SToby Isaac         }
16903dfda0b1SToby Isaac       }
16913dfda0b1SToby Isaac     }
16923dfda0b1SToby Isaac     /* Build Z edges*/
16933dfda0b1SToby Isaac     for (vy = 0; vy < numYVertices; vy++) {
16943dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
16953dfda0b1SToby Isaac         for (ez = 0; ez < numZEdges; ez++) {
16963dfda0b1SToby Isaac           const PetscInt edge    = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez;
16973dfda0b1SToby Isaac           const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx;
16983dfda0b1SToby Isaac           const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx;
16993dfda0b1SToby Isaac           PetscInt       cone[2];
17003dfda0b1SToby Isaac 
17019371c9d4SSatish Balay           cone[0] = vertexB;
17029371c9d4SSatish Balay           cone[1] = vertexT;
1703c2df9bbfSMatthew G. Knepley           PetscCall(DMPlexSetCone(dm, edge, cone));
17043dfda0b1SToby Isaac           if (dim == 3) {
17053dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
17063dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
17079566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1708c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1709c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1710c2df9bbfSMatthew G. Knepley               } else if (vx == 0) {
17119566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1712c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1713c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
17143dfda0b1SToby Isaac               }
17153dfda0b1SToby Isaac             }
17163dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
17173dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
17189566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1719c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1720c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1721c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
17229566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1723c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1724c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
17253dfda0b1SToby Isaac               }
17263dfda0b1SToby Isaac             }
17273dfda0b1SToby Isaac           }
17283dfda0b1SToby Isaac         }
17293dfda0b1SToby Isaac       }
17303dfda0b1SToby Isaac     }
17313dfda0b1SToby Isaac     /* Build Y edges*/
17323dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
17333dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
17343dfda0b1SToby Isaac         for (ey = 0; ey < numYEdges; ey++) {
17353dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx;
17363dfda0b1SToby Isaac           const PetscInt edge    = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey;
17373dfda0b1SToby Isaac           const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx;
17383dfda0b1SToby Isaac           const PetscInt vertexK = firstVertex + nextv;
17393dfda0b1SToby Isaac           PetscInt       cone[2];
17403dfda0b1SToby Isaac 
17419371c9d4SSatish Balay           cone[0] = vertexF;
17429371c9d4SSatish Balay           cone[1] = vertexK;
17439566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
17443dfda0b1SToby Isaac           if (dim == 2) {
17453dfda0b1SToby Isaac             if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
17463dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
17479566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
17489566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
17499566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1750c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1751d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
17529566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
17539566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
17549566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1755c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
17563dfda0b1SToby Isaac               }
1757d8211ee3SMatthew G. Knepley             } else {
17584c67ea77SStefano Zampini               if (vx == 0 && cutLabel) {
17599566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
17609566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1761c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
17623dfda0b1SToby Isaac               }
1763d8211ee3SMatthew G. Knepley             }
1764d8211ee3SMatthew G. Knepley           } else {
17653dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
17663dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
17679566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1768c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1769c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1770d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
17719566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1772c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1773c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
17743dfda0b1SToby Isaac               }
17753dfda0b1SToby Isaac             }
17763dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
17773dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
17789566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1779c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1780c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1781d8211ee3SMatthew G. Knepley               } else if (vz == 0) {
17829566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1783c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1784c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
17853dfda0b1SToby Isaac               }
17863dfda0b1SToby Isaac             }
17873dfda0b1SToby Isaac           }
17883dfda0b1SToby Isaac         }
17893dfda0b1SToby Isaac       }
17903dfda0b1SToby Isaac     }
17913dfda0b1SToby Isaac     /* Build X edges*/
17923dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
17933dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; vy++) {
17943dfda0b1SToby Isaac         for (ex = 0; ex < numXEdges; ex++) {
17953dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices;
17963dfda0b1SToby Isaac           const PetscInt edge    = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex;
17973dfda0b1SToby Isaac           const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex;
17983dfda0b1SToby Isaac           const PetscInt vertexR = firstVertex + nextv;
17993dfda0b1SToby Isaac           PetscInt       cone[2];
18003dfda0b1SToby Isaac 
18019371c9d4SSatish Balay           cone[0] = vertexL;
18029371c9d4SSatish Balay           cone[1] = vertexR;
18039566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
18043dfda0b1SToby Isaac           if (dim == 2) {
18053dfda0b1SToby Isaac             if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
18063dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
18079566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
18089566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
18099566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1810c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1811d8211ee3SMatthew G. Knepley               } else if (vy == 0) {
18129566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
18139566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
18149566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1815c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
18163dfda0b1SToby Isaac               }
1817d8211ee3SMatthew G. Knepley             } else {
18184c67ea77SStefano Zampini               if (vy == 0 && cutLabel) {
18199566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
18209566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1821c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
18223dfda0b1SToby Isaac               }
1823d8211ee3SMatthew G. Knepley             }
1824d8211ee3SMatthew G. Knepley           } else {
18253dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
18263dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
18279566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1828c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1829c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1830c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
18319566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1832c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1833c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
18343dfda0b1SToby Isaac               }
18353dfda0b1SToby Isaac             }
18363dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
18373dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
18389566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1839c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1840c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1841c2df9bbfSMatthew G. Knepley               } else if (vz == 0) {
18429566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1843c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1844c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
18453dfda0b1SToby Isaac               }
18463dfda0b1SToby Isaac             }
18473dfda0b1SToby Isaac           }
18483dfda0b1SToby Isaac         }
18493dfda0b1SToby Isaac       }
18503dfda0b1SToby Isaac     }
18519566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
18529566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
18533dfda0b1SToby Isaac     /* Build coordinates */
18549566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
18559566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
18569566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
18579566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
18583dfda0b1SToby Isaac     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
18599566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
18609566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
18613dfda0b1SToby Isaac     }
18629566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
18639566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
18649566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
18659566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
18669566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
18679566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
18689566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
18699566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
18703dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; ++vz) {
18713dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; ++vy) {
18723dfda0b1SToby Isaac         for (vx = 0; vx < numXVertices; ++vx) {
18733dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
18743dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
1875ad540459SPierre Jolivet           if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz;
18763dfda0b1SToby Isaac         }
18773dfda0b1SToby Isaac       }
18783dfda0b1SToby Isaac     }
18799566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
18809566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
18819566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
18823dfda0b1SToby Isaac   }
18833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18843dfda0b1SToby Isaac }
18853dfda0b1SToby Isaac 
1886d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1887d71ae5a4SJacob Faibussowitsch {
18889318fe57SMatthew G. Knepley   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
18899318fe57SMatthew G. Knepley   PetscInt       fac[3] = {0, 0, 0}, d;
1890552f7358SJed Brown 
1891552f7358SJed Brown   PetscFunctionBegin;
18924f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
18939318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
18949566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
18959371c9d4SSatish Balay   for (d = 0; d < dim; ++d) {
18969371c9d4SSatish Balay     fac[d] = faces[d];
18979371c9d4SSatish Balay     bdt[d] = periodicity[d];
18989371c9d4SSatish Balay   }
18999566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2]));
19009371c9d4SSatish 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))) {
19016858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
19026858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1903552f7358SJed Brown 
19049318fe57SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
19056858538eSMatthew G. Knepley       if (periodicity[d] != DM_BOUNDARY_NONE) {
19069318fe57SMatthew G. Knepley         L[d]       = upper[d] - lower[d];
19079318fe57SMatthew G. Knepley         maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d]));
1908768d5fceSMatthew G. Knepley       }
19096858538eSMatthew G. Knepley     }
19104fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1911768d5fceSMatthew G. Knepley   }
19129566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
19133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
19149318fe57SMatthew G. Knepley }
19159318fe57SMatthew G. Knepley 
19165dca41c3SJed 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)
1917d71ae5a4SJacob Faibussowitsch {
19189318fe57SMatthew G. Knepley   PetscFunctionBegin;
191946139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
19205dca41c3SJed Brown   if (shape == DM_SHAPE_ZBOX) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
19216725e60dSJed Brown   else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0]));
19229566063dSJacob Faibussowitsch   else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
19239566063dSJacob Faibussowitsch   else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity));
19249318fe57SMatthew G. Knepley   if (!interpolate && dim > 1 && !simplex) {
1925768d5fceSMatthew G. Knepley     DM udm;
1926768d5fceSMatthew G. Knepley 
19279566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(dm, &udm));
19289566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, udm));
192969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &udm));
1930768d5fceSMatthew G. Knepley   }
193146139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
19323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1933c8c68bd8SToby Isaac }
1934c8c68bd8SToby Isaac 
19355d83a8b1SBarry Smith /*@
1936768d5fceSMatthew G. Knepley   DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra).
1937768d5fceSMatthew G. Knepley 
1938d083f849SBarry Smith   Collective
1939768d5fceSMatthew G. Knepley 
1940768d5fceSMatthew G. Knepley   Input Parameters:
1941a1cb98faSBarry Smith + comm               - The communicator for the `DM` object
1942768d5fceSMatthew G. Knepley . dim                - The spatial dimension
1943a1cb98faSBarry Smith . simplex            - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells
194420f4b53cSBarry Smith . faces              - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
194520f4b53cSBarry Smith . lower              - The lower left corner, or `NULL` for (0, 0, 0)
194620f4b53cSBarry Smith . upper              - The upper right corner, or `NULL` for (1, 1, 1)
194720f4b53cSBarry Smith . periodicity        - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE`
194842108689Sksagiyam . interpolate        - Flag to create intermediate mesh pieces (edges, faces)
194942108689Sksagiyam . localizationHeight - Flag to localize edges and faces in addition to cells; only significant for periodic meshes
195042108689Sksagiyam - sparseLocalize     - Flag to localize coordinates only for cells near the periodic boundary; only significant for periodic meshes
1951768d5fceSMatthew G. Knepley 
1952768d5fceSMatthew G. Knepley   Output Parameter:
1953a1cb98faSBarry Smith . dm - The `DM` object
1954768d5fceSMatthew G. Knepley 
1955768d5fceSMatthew G. Knepley   Level: beginner
1956768d5fceSMatthew G. Knepley 
1957a1cb98faSBarry Smith   Note:
1958a1cb98faSBarry Smith   To customize this mesh using options, use
1959a1cb98faSBarry Smith .vb
1960a1cb98faSBarry Smith   DMCreate(comm, &dm);
1961a1cb98faSBarry Smith   DMSetType(dm, DMPLEX);
1962a1cb98faSBarry Smith   DMSetFromOptions(dm);
1963a1cb98faSBarry Smith .ve
1964a1cb98faSBarry Smith   and use the options in `DMSetFromOptions()`.
1965a1cb98faSBarry Smith 
1966a4e35b19SJacob Faibussowitsch   Here is the numbering returned for 2 faces in each direction for tensor cells\:
1967a1cb98faSBarry Smith .vb
1968a1cb98faSBarry Smith  10---17---11---18----12
1969a1cb98faSBarry Smith   |         |         |
1970a1cb98faSBarry Smith   |         |         |
1971a1cb98faSBarry Smith  20    2   22    3    24
1972a1cb98faSBarry Smith   |         |         |
1973a1cb98faSBarry Smith   |         |         |
1974a1cb98faSBarry Smith   7---15----8---16----9
1975a1cb98faSBarry Smith   |         |         |
1976a1cb98faSBarry Smith   |         |         |
1977a1cb98faSBarry Smith  19    0   21    1   23
1978a1cb98faSBarry Smith   |         |         |
1979a1cb98faSBarry Smith   |         |         |
1980a1cb98faSBarry Smith   4---13----5---14----6
1981a1cb98faSBarry Smith .ve
1982a1cb98faSBarry Smith   and for simplicial cells
1983a1cb98faSBarry Smith .vb
1984a1cb98faSBarry Smith  14----8---15----9----16
1985a1cb98faSBarry Smith   |\     5  |\      7 |
1986a1cb98faSBarry Smith   | \       | \       |
1987a1cb98faSBarry Smith  13   2    14    3    15
1988a1cb98faSBarry Smith   | 4   \   | 6   \   |
1989a1cb98faSBarry Smith   |       \ |       \ |
1990a1cb98faSBarry Smith  11----6---12----7----13
1991a1cb98faSBarry Smith   |\        |\        |
1992a1cb98faSBarry Smith   | \    1  | \     3 |
1993a1cb98faSBarry Smith  10   0    11    1    12
1994a1cb98faSBarry Smith   | 0   \   | 2   \   |
1995a1cb98faSBarry Smith   |       \ |       \ |
1996a1cb98faSBarry Smith   8----4----9----5----10
1997a1cb98faSBarry Smith .ve
1998a1cb98faSBarry Smith 
19991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
2000768d5fceSMatthew G. Knepley @*/
200142108689Sksagiyam 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)
2002d71ae5a4SJacob Faibussowitsch {
20039318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
2004fdbf62faSLisandro Dalcin   PetscReal      low[3] = {0, 0, 0};
2005fdbf62faSLisandro Dalcin   PetscReal      upp[3] = {1, 1, 1};
2006fdbf62faSLisandro Dalcin   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
2007552f7358SJed Brown 
2008768d5fceSMatthew G. Knepley   PetscFunctionBegin;
20099566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
20109566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
20115dca41c3SJed Brown   PetscCall(DMPlexCreateBoxMesh_Internal(*dm, DM_SHAPE_BOX, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate));
201242108689Sksagiyam   if (periodicity) {
201342108689Sksagiyam     DM cdm;
201442108689Sksagiyam 
201542108689Sksagiyam     PetscCall(DMGetCoordinateDM(*dm, &cdm));
201642108689Sksagiyam     PetscCall(DMPlexSetMaxProjectionHeight(cdm, localizationHeight));
201742108689Sksagiyam     PetscCall(DMSetSparseLocalize(*dm, sparseLocalize));
201842108689Sksagiyam     PetscCall(DMLocalizeCoordinates(*dm));
201942108689Sksagiyam   }
20203ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20219318fe57SMatthew G. Knepley }
2022fdbf62faSLisandro Dalcin 
2023d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
2024d71ae5a4SJacob Faibussowitsch {
20259318fe57SMatthew G. Knepley   DM       bdm, vol;
20269318fe57SMatthew G. Knepley   PetscInt i;
20279318fe57SMatthew G. Knepley 
20289318fe57SMatthew G. Knepley   PetscFunctionBegin;
20291fcf445aSMatthew G. Knepley   // TODO Now we can support periodicity
203008401ef6SPierre Jolivet   for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported");
20319566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm));
20329566063dSJacob Faibussowitsch   PetscCall(DMSetType(bdm, DMPLEX));
20339566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(bdm, 2));
203446139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, bdm, 0, 0, 0));
20359566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE));
20361fcf445aSMatthew G. Knepley   PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, NULL, NULL, &vol));
203746139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, bdm, 0, 0, 0));
20389566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&bdm));
203969d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
20409318fe57SMatthew G. Knepley   if (lower[2] != 0.0) {
20419318fe57SMatthew G. Knepley     Vec          v;
20429318fe57SMatthew G. Knepley     PetscScalar *x;
20439318fe57SMatthew G. Knepley     PetscInt     cDim, n;
20449318fe57SMatthew G. Knepley 
20459566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &v));
20469566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(v, &cDim));
20479566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(v, &n));
20489566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v, &x));
20499318fe57SMatthew G. Knepley     x += cDim;
20509318fe57SMatthew G. Knepley     for (i = 0; i < n; i += cDim) x[i] += lower[2];
20519566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v, &x));
20529566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, v));
20539318fe57SMatthew G. Knepley   }
20543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2055552f7358SJed Brown }
2056552f7358SJed Brown 
205700dabe28SStefano Zampini /*@
205839f4f5dbSPierre Jolivet   DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tessellating the (x,y) plane and extruding in the third direction using wedge cells.
205900dabe28SStefano Zampini 
2060d083f849SBarry Smith   Collective
206100dabe28SStefano Zampini 
206200dabe28SStefano Zampini   Input Parameters:
2063a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
206420f4b53cSBarry Smith . faces       - Number of faces per dimension, or `NULL` for (1, 1, 1)
206520f4b53cSBarry Smith . lower       - The lower left corner, or `NULL` for (0, 0, 0)
206620f4b53cSBarry Smith . upper       - The upper right corner, or `NULL` for (1, 1, 1)
206720f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE`
2068a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first
206900dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces)
207000dabe28SStefano Zampini 
207100dabe28SStefano Zampini   Output Parameter:
2072a1cb98faSBarry Smith . dm - The `DM` object
207300dabe28SStefano Zampini 
207400dabe28SStefano Zampini   Level: beginner
207500dabe28SStefano Zampini 
20761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
207700dabe28SStefano Zampini @*/
2078d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm)
2079d71ae5a4SJacob Faibussowitsch {
20809318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
208100dabe28SStefano Zampini   PetscReal      low[3] = {0, 0, 0};
208200dabe28SStefano Zampini   PetscReal      upp[3] = {1, 1, 1};
208300dabe28SStefano Zampini   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
208400dabe28SStefano Zampini 
208500dabe28SStefano Zampini   PetscFunctionBegin;
20869566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
20879566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
20889566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt));
2089d410b0cfSMatthew G. Knepley   if (!interpolate) {
2090d410b0cfSMatthew G. Knepley     DM udm;
209100dabe28SStefano Zampini 
20929566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(*dm, &udm));
209369d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(*dm, &udm));
209400dabe28SStefano Zampini   }
20957ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
20963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
209700dabe28SStefano Zampini }
209800dabe28SStefano Zampini 
2099cfb853baSMatthew G. Knepley /*
2100cfb853baSMatthew 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.
2101cfb853baSMatthew G. Knepley 
2102cfb853baSMatthew G. Knepley   Input Parameters:
2103cfb853baSMatthew G. Knepley + len - The length of the tuple
2104cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max)
2105cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition
2106cfb853baSMatthew G. Knepley 
2107cfb853baSMatthew G. Knepley   Output Parameter:
210820f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max`
2109cfb853baSMatthew G. Knepley 
2110cfb853baSMatthew G. Knepley   Level: developer
2111cfb853baSMatthew G. Knepley 
211220f4b53cSBarry Smith   Note:
211320f4b53cSBarry Smith   Ordering is lexicographic with lowest index as least significant in ordering.
211420f4b53cSBarry 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}.
211520f4b53cSBarry Smith 
2116cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal()
2117cfb853baSMatthew G. Knepley */
2118cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[])
2119cfb853baSMatthew G. Knepley {
2120cfb853baSMatthew G. Knepley   PetscInt i;
2121cfb853baSMatthew G. Knepley 
2122cfb853baSMatthew G. Knepley   PetscFunctionBegin;
2123cfb853baSMatthew G. Knepley   for (i = 0; i < len; ++i) {
2124cfb853baSMatthew G. Knepley     if (tup[i] < max[i] - 1) {
2125cfb853baSMatthew G. Knepley       break;
2126cfb853baSMatthew G. Knepley     } else {
2127cfb853baSMatthew G. Knepley       tup[i] = 0;
2128cfb853baSMatthew G. Knepley     }
2129cfb853baSMatthew G. Knepley   }
2130cfb853baSMatthew G. Knepley   if (i == len) tup[i - 1] = max[i - 1];
2131cfb853baSMatthew G. Knepley   else ++tup[i];
21323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2133cfb853baSMatthew G. Knepley }
2134cfb853baSMatthew G. Knepley 
2135cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[])
2136cfb853baSMatthew G. Knepley {
21378d2ec52aSSatish Balay   PetscInt idx = tup[len - 1];
2138cfb853baSMatthew G. Knepley 
21398d2ec52aSSatish Balay   for (PetscInt i = len - 2; i >= 0; --i) {
2140cfb853baSMatthew G. Knepley     idx *= max[i];
2141cfb853baSMatthew G. Knepley     idx += tup[i];
2142cfb853baSMatthew G. Knepley   }
2143cfb853baSMatthew G. Knepley   return idx;
2144cfb853baSMatthew G. Knepley }
2145cfb853baSMatthew G. Knepley 
21468d2ec52aSSatish Balay static void IndexToTuple_Private(PetscInt len, const PetscInt max[], PetscInt idx, PetscInt tup[])
2147cfb853baSMatthew G. Knepley {
21488d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
21498d2ec52aSSatish Balay     tup[i] = idx % max[i];
21508d2ec52aSSatish Balay     idx    = (idx - tup[i]) / max[i];
21518d2ec52aSSatish Balay   }
21528d2ec52aSSatish Balay }
21538d2ec52aSSatish Balay 
21548d2ec52aSSatish Balay static void TupleToRanks_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt tup[], PetscInt ranks[])
21558d2ec52aSSatish Balay {
21568d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
21578d2ec52aSSatish Balay     const PetscInt div = max[i] / procs[i];
21588d2ec52aSSatish Balay     const PetscInt rem = max[i] % procs[i];
21598d2ec52aSSatish Balay     const PetscInt idx = (tup[i] < 0 ? max[i] + tup[i] : tup[i]) % max[i];
21608d2ec52aSSatish Balay 
21618d2ec52aSSatish Balay     if (idx < rem * (div + 1)) ranks[i] = idx / (div + 1);
21628d2ec52aSSatish Balay     else ranks[i] = rem + (idx - rem * (div + 1)) / div;
21638d2ec52aSSatish Balay   }
21648d2ec52aSSatish Balay }
21658d2ec52aSSatish Balay 
21668d2ec52aSSatish Balay static void RanksToSizes_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt ranks[], PetscInt sizes[])
21678d2ec52aSSatish Balay {
21688d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
21698d2ec52aSSatish Balay     const PetscInt div = max[i] / procs[i];
21708d2ec52aSSatish Balay     const PetscInt rem = max[i] % procs[i];
21718d2ec52aSSatish Balay 
21728d2ec52aSSatish Balay     sizes[i] = ranks[i] < rem ? div + 1 : div;
21738d2ec52aSSatish Balay   }
21748d2ec52aSSatish Balay }
21758d2ec52aSSatish Balay 
21768d2ec52aSSatish Balay /*
21778d2ec52aSSatish 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.
21788d2ec52aSSatish Balay 
21798d2ec52aSSatish 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.
21808d2ec52aSSatish Balay 
21818d2ec52aSSatish 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.
2182dfe9cfe5SMatthew Knepley 
2183dfe9cfe5SMatthew Knepley   Parallel Layout:
2184dfe9cfe5SMatthew Knepley 
2185dfe9cfe5SMatthew 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.
21868d2ec52aSSatish Balay */
21878d2ec52aSSatish Balay static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], PetscInt overlap, const DMBoundaryType bd[])
21888d2ec52aSSatish Balay {
21898d2ec52aSSatish Balay   const PetscInt debug = ((DM_Plex *)dm->data)->printAdj;
21908d2ec52aSSatish Balay   PetscSF        sf;
2191cfb853baSMatthew G. Knepley   Vec            coordinates;
2192cfb853baSMatthew G. Knepley   PetscSection   coordSection;
2193cfb853baSMatthew G. Knepley   DMLabel        cutLabel    = NULL;
2194cfb853baSMatthew G. Knepley   PetscBool      cutMarker   = PETSC_FALSE;
2195cfb853baSMatthew G. Knepley   PetscBool      periodic    = PETSC_FALSE;
21968d2ec52aSSatish Balay   PetscInt       numCells    = 1;
21978d2ec52aSSatish Balay   PetscInt       numVertices = 1;
21988d2ec52aSSatish Balay   PetscSFNode   *remotes;
2199cfb853baSMatthew G. Knepley   PetscScalar   *coords;
22008d2ec52aSSatish Balay   PetscInt      *procs;     // The number of processes along each dimension
22018d2ec52aSSatish Balay   PetscInt      *lrank;     // Rank in each dimension, lrank[d] \in [0, procs[d])
22028d2ec52aSSatish Balay   PetscInt      *ledges;    // The number of edges along each dimension for this process
22038d2ec52aSSatish Balay   PetscInt      *vstart;    // The first vertex along each dimension on this processes
22048d2ec52aSSatish Balay   PetscInt      *vertices;  // The number of vertices along each dimension on this process
22058d2ec52aSSatish Balay   PetscInt      *rvert;     // The global (not local) vertex number along each dimension
22068d2ec52aSSatish Balay   PetscInt      *rrank;     // The rank along each dimension for the process owning rvert[]
22078d2ec52aSSatish Balay   PetscInt      *rvertices; // The number of vertices along each dimension for the process rrank[]
22088d2ec52aSSatish Balay   PetscInt      *vert, *vtmp, *supp, cone[2], *leaves;
22098d2ec52aSSatish Balay   PetscInt       cell = 0, coordSize, Nl = 0, Nl2 = 0;
22108d2ec52aSSatish Balay   PetscMPIInt    rank, size;
22118d2ec52aSSatish Balay   MPI_Comm       comm;
2212cfb853baSMatthew G. Knepley 
2213cfb853baSMatthew G. Knepley   PetscFunctionBegin;
22148d2ec52aSSatish Balay   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
22158d2ec52aSSatish Balay   PetscCallMPI(MPI_Comm_rank(comm, &rank));
22168d2ec52aSSatish Balay   PetscCallMPI(MPI_Comm_size(comm, &size));
2217cfb853baSMatthew G. Knepley   PetscCall(DMSetDimension(dm, dim));
22188d2ec52aSSatish Balay   PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
22198d2ec52aSSatish Balay   PetscCall(PetscCalloc4(dim, &procs, dim, &lrank, dim, &rrank, 2 * dim, &supp));
22208d2ec52aSSatish Balay   PetscCall(PetscCalloc7(dim, &ledges, dim, &vertices, dim, &rvertices, dim, &vert, dim, &rvert, dim, &vstart, dim, &vtmp));
2221cfb853baSMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "marker"));
2222cfb853baSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
22238d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE;
2224cfb853baSMatthew G. Knepley   if (periodic && cutMarker) {
2225cfb853baSMatthew G. Knepley     PetscCall(DMCreateLabel(dm, "periodic_cut"));
2226cfb853baSMatthew G. Knepley     PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
2227cfb853baSMatthew G. Knepley   }
22288d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, comm, PETSC_ERR_SUP, "Hypercubic mesh must be periodic now");
22298d2ec52aSSatish Balay   overlap = overlap == PETSC_DETERMINE ? 1 : overlap;
22308d2ec52aSSatish Balay   PetscCheck(overlap >= 1, comm, PETSC_ERR_SUP, "Overlap %" PetscInt_FMT " must be greater than 0", overlap);
22318d2ec52aSSatish Balay   if (size > 1) {
22328d2ec52aSSatish Balay     PetscInt Npr = 1;
22338d2ec52aSSatish Balay 
22348d2ec52aSSatish Balay     // Make process grid
22358d2ec52aSSatish Balay     if (debug) PetscCall(PetscPrintf(comm, "Process grid:"));
22368d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
22378d2ec52aSSatish Balay       procs[d] = PetscRintReal(PetscPowReal(size, 1. / dim));
22388d2ec52aSSatish Balay       Npr *= procs[d];
22398d2ec52aSSatish Balay       if (debug) PetscCall(PetscPrintf(comm, " %" PetscInt_FMT, procs[d]));
22408d2ec52aSSatish Balay     }
22418d2ec52aSSatish Balay     if (debug) PetscCall(PetscPrintf(comm, "\n"));
22428d2ec52aSSatish Balay     PetscCheck(Npr == size, comm, PETSC_ERR_PLIB, "Process grid size %" PetscInt_FMT " != %d comm size", Npr, size);
22438d2ec52aSSatish Balay     IndexToTuple_Private(dim, procs, rank, lrank);
22448d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
22458d2ec52aSSatish Balay       ledges[d] = edges[d] / procs[d] + (edges[d] % procs[d] > lrank[d] ? 1 : 0);
22468d2ec52aSSatish Balay       vstart[d] = 0;
22478d2ec52aSSatish Balay       for (PetscInt r = 0; r < lrank[d]; ++r) vstart[d] += edges[d] / procs[d] + (edges[d] % procs[d] > r ? 1 : 0);
22488d2ec52aSSatish Balay       vstart[d] -= overlap; // For halo
22498d2ec52aSSatish Balay     }
22508d2ec52aSSatish Balay   } else {
22518d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
22528d2ec52aSSatish Balay       procs[d]  = 1;
22538d2ec52aSSatish Balay       ledges[d] = edges[d];
22548d2ec52aSSatish Balay     }
22558d2ec52aSSatish Balay   }
22568d2ec52aSSatish Balay   // Calculate local patch size
22578d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) {
22588d2ec52aSSatish Balay     vertices[d] = ledges[d] + (procs[d] > 1 ? 2 * overlap : 0);
2259cfb853baSMatthew G. Knepley     numVertices *= vertices[d];
2260cfb853baSMatthew G. Knepley   }
2261cfb853baSMatthew G. Knepley   numCells = numVertices * dim;
2262cfb853baSMatthew G. Knepley   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
22638d2ec52aSSatish Balay   for (PetscInt c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2));
22648d2ec52aSSatish Balay   for (PetscInt v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim));
2265cfb853baSMatthew G. Knepley   PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */
2266cfb853baSMatthew G. Knepley   /* Build cell cones and vertex supports */
2267cfb853baSMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "celltype"));
22688d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Topology for rank %d:\n", rank));
2269cfb853baSMatthew G. Knepley   while (vert[dim - 1] < vertices[dim - 1]) {
2270cfb853baSMatthew G. Knepley     const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells;
2271cfb853baSMatthew G. Knepley     PetscInt       s      = 0;
22728d2ec52aSSatish Balay     PetscBool      leaf   = PETSC_FALSE;
2273cfb853baSMatthew G. Knepley 
22748d2ec52aSSatish Balay     if (debug) {
22758d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex));
22768d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d]));
22778d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "\n"));
22788d2ec52aSSatish Balay     }
2279cfb853baSMatthew G. Knepley     PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT));
22808d2ec52aSSatish Balay     // Define edge cones
22818d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
22828d2ec52aSSatish Balay       for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e];
2283cfb853baSMatthew G. Knepley       vtmp[d] = (vert[d] + 1) % vertices[d];
2284cfb853baSMatthew G. Knepley       cone[0] = vertex;
2285cfb853baSMatthew G. Knepley       cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells;
22868d2ec52aSSatish Balay       if (debug) {
22878d2ec52aSSatish Balay         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ":", cone[1]));
22888d2ec52aSSatish Balay         for (PetscInt e = 0; e < dim; ++e) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vtmp[e]));
22898d2ec52aSSatish Balay         PetscCall(PetscSynchronizedPrintf(comm, "\n"));
22908d2ec52aSSatish Balay       }
2291cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetCone(dm, cell, cone));
2292cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT));
22938d2ec52aSSatish Balay       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1]));
2294cfb853baSMatthew G. Knepley       ++cell;
22958d2ec52aSSatish Balay       // Shared vertices are any in the first or last overlap layers
22968d2ec52aSSatish Balay       if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE;
2297cfb853baSMatthew G. Knepley     }
22988d2ec52aSSatish Balay     if (size > 1 && leaf) ++Nl;
22998d2ec52aSSatish Balay     // Define vertex supports
23008d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
23018d2ec52aSSatish Balay       for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e];
2302cfb853baSMatthew G. Knepley       vtmp[d]   = (vert[d] + vertices[d] - 1) % vertices[d];
2303cfb853baSMatthew G. Knepley       supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d;
2304cfb853baSMatthew G. Knepley       supp[s++] = (vertex - numCells) * dim + d;
2305cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetSupport(dm, vertex, supp));
2306cfb853baSMatthew G. Knepley     }
2307cfb853baSMatthew G. Knepley     PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert));
2308cfb853baSMatthew G. Knepley   }
23098d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
2310cfb853baSMatthew G. Knepley   PetscCall(DMPlexStratify(dm));
23118d2ec52aSSatish Balay   // Allocate for SF
23128d2ec52aSSatish Balay   PetscCall(PetscMalloc1(Nl, &leaves));
23138d2ec52aSSatish Balay   PetscCall(PetscMalloc1(Nl, &remotes));
23148d2ec52aSSatish Balay   // Build coordinates
2315cfb853baSMatthew G. Knepley   PetscCall(DMGetCoordinateSection(dm, &coordSection));
2316cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetNumFields(coordSection, 1));
2317cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
2318cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
23198d2ec52aSSatish Balay   for (PetscInt v = numCells; v < numCells + numVertices; ++v) {
2320cfb853baSMatthew G. Knepley     PetscCall(PetscSectionSetDof(coordSection, v, dim));
2321cfb853baSMatthew G. Knepley     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
2322cfb853baSMatthew G. Knepley   }
2323cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetUp(coordSection));
2324cfb853baSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
23258d2ec52aSSatish Balay   PetscCall(VecCreate(comm, &coordinates));
2326cfb853baSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
2327cfb853baSMatthew G. Knepley   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
2328cfb853baSMatthew G. Knepley   PetscCall(VecSetBlockSize(coordinates, dim));
2329cfb853baSMatthew G. Knepley   PetscCall(VecSetType(coordinates, VECSTANDARD));
2330cfb853baSMatthew G. Knepley   PetscCall(VecGetArray(coordinates, &coords));
23318d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Geometry for rank %d:\n", rank));
23328d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) vert[d] = 0;
2333cfb853baSMatthew G. Knepley   while (vert[dim - 1] < vertices[dim - 1]) {
2334cfb853baSMatthew G. Knepley     const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert);
23358d2ec52aSSatish Balay     PetscBool      leaf   = PETSC_FALSE;
2336cfb853baSMatthew G. Knepley 
23378d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
23388d2ec52aSSatish Balay       coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / edges[d]) * (vert[d] + vstart[d]);
23398d2ec52aSSatish Balay       if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE;
23408d2ec52aSSatish Balay     }
23418d2ec52aSSatish Balay     if (size > 1 && leaf) {
23428d2ec52aSSatish Balay       PetscInt rnumCells = 1;
23438d2ec52aSSatish Balay 
23448d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) rvert[d] = vert[d] + vstart[d];
23458d2ec52aSSatish Balay       TupleToRanks_Private(dim, edges, procs, rvert, rrank);
23468d2ec52aSSatish Balay       leaves[Nl2]       = vertex + numCells;
23478d2ec52aSSatish Balay       remotes[Nl2].rank = TupleToIndex_Private(dim, procs, rrank);
23488d2ec52aSSatish Balay       RanksToSizes_Private(dim, edges, procs, rrank, rvertices);
23498d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) {
23508d2ec52aSSatish Balay         rvertices[d] += 2 * overlap; // Add halo
23518d2ec52aSSatish Balay         rnumCells *= rvertices[d];
23528d2ec52aSSatish Balay       }
23538d2ec52aSSatish Balay       rnumCells *= dim;
23548d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) {
23558d2ec52aSSatish Balay         const PetscInt diff = rrank[d] - lrank[d];
23568d2ec52aSSatish Balay 
23578d2ec52aSSatish Balay         if (!diff) rvert[d] = vert[d];                                     // Vertex is local
23588d2ec52aSSatish Balay         else if (rvert[d] < 0) rvert[d] = rvertices[d] - 1 + rvert[d];     // Wrap around at the bottom
23598d2ec52aSSatish Balay         else if (rvert[d] >= edges[d]) rvert[d] = rvert[d] - edges[d] + 1; // Wrap around at the top
23608d2ec52aSSatish Balay         else if (diff == -1) rvert[d] = rvertices[d] - 1 + (vert[d] - overlap);
23618d2ec52aSSatish Balay         else if (diff == 1) rvert[d] = (vertices[d] - vert[d] - 1) + overlap;
23628d2ec52aSSatish Balay         else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Process distance %" PetscInt_FMT " in direction %" PetscInt_FMT " should not be possible", diff, d);
23638d2ec52aSSatish Balay       }
23648d2ec52aSSatish Balay       remotes[Nl2].index = TupleToIndex_Private(dim, rvertices, rvert) + rnumCells;
23658d2ec52aSSatish Balay       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Shared Vertex %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", leaves[Nl2], remotes[Nl2].rank, remotes[Nl2].index));
23668d2ec52aSSatish Balay       ++Nl2;
23678d2ec52aSSatish Balay     }
23688d2ec52aSSatish Balay     if (debug) {
23698d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex));
23708d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d] + vstart[d]));
23718d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %g", (double)PetscRealPart(coords[vertex * dim + d])));
23728d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "\n"));
23738d2ec52aSSatish Balay     }
2374cfb853baSMatthew G. Knepley     PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert));
2375cfb853baSMatthew G. Knepley   }
23768d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
2377cfb853baSMatthew G. Knepley   PetscCall(VecRestoreArray(coordinates, &coords));
2378cfb853baSMatthew G. Knepley   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
2379cfb853baSMatthew G. Knepley   PetscCall(VecDestroy(&coordinates));
23808d2ec52aSSatish Balay   // Build SF
23818d2ec52aSSatish Balay   PetscCheck(Nl == Nl2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Initial number of leaves %" PetscInt_FMT " != %" PetscInt_FMT " final number", Nl, Nl2);
23828d2ec52aSSatish Balay   PetscCall(DMGetPointSF(dm, &sf));
23838d2ec52aSSatish Balay   PetscCall(PetscSFSetGraph(sf, numCells + numVertices, Nl, leaves, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER));
23848d2ec52aSSatish Balay   if (debug) PetscCall(PetscSFView(sf, PETSC_VIEWER_STDOUT_WORLD));
2385cfb853baSMatthew G. Knepley   //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper));
2386cfb853baSMatthew G. Knepley   // Attach the extent
2387cfb853baSMatthew G. Knepley   {
2388cfb853baSMatthew G. Knepley     PetscContainer c;
23898d2ec52aSSatish Balay     PetscInt      *extent, *lextent;
2390cfb853baSMatthew G. Knepley 
2391cfb853baSMatthew G. Knepley     PetscCall(PetscMalloc1(dim, &extent));
23928d2ec52aSSatish Balay     PetscCall(PetscMalloc1(dim, &lextent));
23938d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
23948d2ec52aSSatish Balay       extent[d]  = edges[d];
23958d2ec52aSSatish Balay       lextent[d] = ledges[d];
23968d2ec52aSSatish Balay     }
2397cfb853baSMatthew G. Knepley     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c));
239849abdd8aSBarry Smith     PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault));
2399cfb853baSMatthew G. Knepley     PetscCall(PetscContainerSetPointer(c, extent));
2400cfb853baSMatthew G. Knepley     PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c));
2401cfb853baSMatthew G. Knepley     PetscCall(PetscContainerDestroy(&c));
24028d2ec52aSSatish Balay     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c));
24038d2ec52aSSatish Balay     PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault));
24048d2ec52aSSatish Balay     PetscCall(PetscContainerSetPointer(c, lextent));
24058d2ec52aSSatish Balay     PetscCall(PetscObjectCompose((PetscObject)dm, "_lextent", (PetscObject)c));
24068d2ec52aSSatish Balay     PetscCall(PetscContainerDestroy(&c));
2407cfb853baSMatthew G. Knepley   }
24088d2ec52aSSatish Balay   PetscCall(PetscFree4(procs, lrank, rrank, supp));
24098d2ec52aSSatish Balay   PetscCall(PetscFree7(ledges, vertices, rvertices, vert, rvert, vstart, vtmp));
24103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2411cfb853baSMatthew G. Knepley }
2412cfb853baSMatthew G. Knepley 
2413cfb853baSMatthew G. Knepley /*@C
2414aaa8cc7dSPierre Jolivet   DMPlexCreateHypercubicMesh - Creates a periodic mesh on the tensor product of unit intervals using only vertices and edges.
2415cfb853baSMatthew G. Knepley 
2416cfb853baSMatthew G. Knepley   Collective
2417cfb853baSMatthew G. Knepley 
2418cfb853baSMatthew G. Knepley   Input Parameters:
24198d2ec52aSSatish Balay + comm    - The communicator for the `DM` object
2420cfb853baSMatthew G. Knepley . dim     - The spatial dimension
242120f4b53cSBarry Smith . edges   - Number of edges per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
242220f4b53cSBarry Smith . lower   - The lower left corner, or `NULL` for (0, 0, 0)
24238d2ec52aSSatish Balay . upper   - The upper right corner, or `NULL` for (1, 1, 1)
24248d2ec52aSSatish Balay - overlap - The number of vertices in each direction to include in the overlap (default is 1)
2425cfb853baSMatthew G. Knepley 
2426cfb853baSMatthew G. Knepley   Output Parameter:
2427cfb853baSMatthew G. Knepley . dm - The DM object
2428cfb853baSMatthew G. Knepley 
242920f4b53cSBarry Smith   Level: beginner
243020f4b53cSBarry Smith 
243120f4b53cSBarry Smith   Note:
243220f4b53cSBarry Smith   If you want to customize this mesh using options, you just need to
243320f4b53cSBarry Smith .vb
243420f4b53cSBarry Smith   DMCreate(comm, &dm);
243520f4b53cSBarry Smith   DMSetType(dm, DMPLEX);
243620f4b53cSBarry Smith   DMSetFromOptions(dm);
243720f4b53cSBarry Smith .ve
243820f4b53cSBarry Smith   and use the options on the `DMSetFromOptions()` page.
2439cfb853baSMatthew G. Knepley 
2440cfb853baSMatthew G. Knepley   The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively,
244120f4b53cSBarry Smith .vb
244220f4b53cSBarry Smith  18--0-19--2-20--4-18
244320f4b53cSBarry Smith   |     |     |     |
244420f4b53cSBarry Smith  13    15    17    13
244520f4b53cSBarry Smith   |     |     |     |
244620f4b53cSBarry Smith  24-12-25-14-26-16-24
244720f4b53cSBarry Smith   |     |     |     |
244820f4b53cSBarry Smith   7     9    11     7
244920f4b53cSBarry Smith   |     |     |     |
245020f4b53cSBarry Smith  21--6-22--8-23-10-21
245120f4b53cSBarry Smith   |     |     |     |
245220f4b53cSBarry Smith   1     3     5     1
245320f4b53cSBarry Smith   |     |     |     |
245420f4b53cSBarry Smith  18--0-19--2-20--4-18
245520f4b53cSBarry Smith .ve
2456cfb853baSMatthew G. Knepley 
245776fbde31SPierre Jolivet .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
2458cfb853baSMatthew G. Knepley @*/
24598d2ec52aSSatish Balay PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], PetscInt overlap, DM *dm)
2460cfb853baSMatthew G. Knepley {
2461cfb853baSMatthew G. Knepley   PetscInt       *edg;
2462cfb853baSMatthew G. Knepley   PetscReal      *low, *upp;
2463cfb853baSMatthew G. Knepley   DMBoundaryType *bdt;
2464cfb853baSMatthew G. Knepley   PetscInt        d;
2465cfb853baSMatthew G. Knepley 
2466cfb853baSMatthew G. Knepley   PetscFunctionBegin;
2467cfb853baSMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
2468cfb853baSMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
2469cfb853baSMatthew G. Knepley   PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt));
2470cfb853baSMatthew G. Knepley   for (d = 0; d < dim; ++d) {
2471cfb853baSMatthew G. Knepley     edg[d] = edges ? edges[d] : 1;
2472cfb853baSMatthew G. Knepley     low[d] = lower ? lower[d] : 0.;
2473cfb853baSMatthew G. Knepley     upp[d] = upper ? upper[d] : 1.;
2474cfb853baSMatthew G. Knepley     bdt[d] = DM_BOUNDARY_PERIODIC;
2475cfb853baSMatthew G. Knepley   }
24768d2ec52aSSatish Balay   PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, overlap, bdt));
2477cfb853baSMatthew G. Knepley   PetscCall(PetscFree4(edg, low, upp, bdt));
24783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2479cfb853baSMatthew G. Knepley }
2480cfb853baSMatthew G. Knepley 
2481cc4c1da9SBarry Smith /*@
2482a1cb98faSBarry Smith   DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database.
2483a9074c1eSMatthew G. Knepley 
248420f4b53cSBarry Smith   Logically Collective
2485a9074c1eSMatthew G. Knepley 
2486a9074c1eSMatthew G. Knepley   Input Parameters:
248720f4b53cSBarry Smith + dm     - the `DM` context
2488a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names
2489a9074c1eSMatthew G. Knepley 
2490a1cb98faSBarry Smith   Level: advanced
2491a1cb98faSBarry Smith 
2492a1cb98faSBarry Smith   Note:
2493a9074c1eSMatthew G. Knepley   A hyphen (-) must NOT be given at the beginning of the prefix name.
2494a9074c1eSMatthew G. Knepley   The first character of all runtime options is AUTOMATICALLY the hyphen.
2495a9074c1eSMatthew G. Knepley 
24961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()`
2497a9074c1eSMatthew G. Knepley @*/
2498d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[])
2499d71ae5a4SJacob Faibussowitsch {
2500a9074c1eSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
2501a9074c1eSMatthew G. Knepley 
2502a9074c1eSMatthew G. Knepley   PetscFunctionBegin;
2503a9074c1eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
25049566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
25059566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix));
25063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2507a9074c1eSMatthew G. Knepley }
2508a9074c1eSMatthew G. Knepley 
25099318fe57SMatthew G. Knepley /* Remap geometry to cylinder
251061a622f3SMatthew G. Knepley    TODO: This only works for a single refinement, then it is broken
251161a622f3SMatthew G. Knepley 
25129318fe57SMatthew G. Knepley      Interior square: Linear interpolation is correct
25139318fe57SMatthew G. Knepley      The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing
25149318fe57SMatthew G. Knepley      such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance
25150510c589SMatthew G. Knepley 
25169318fe57SMatthew G. Knepley        phi     = arctan(y/x)
25179318fe57SMatthew G. Knepley        d_close = sqrt(1/8 + 1/4 sin^2(phi))
25189318fe57SMatthew G. Knepley        d_far   = sqrt(1/2 + sin^2(phi))
25190510c589SMatthew G. Knepley 
25209318fe57SMatthew G. Knepley      so we remap them using
25210510c589SMatthew G. Knepley 
25229318fe57SMatthew G. Knepley        x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close)
25239318fe57SMatthew G. Knepley        y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close)
25240510c589SMatthew G. Knepley 
25259318fe57SMatthew G. Knepley      If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y.
25269318fe57SMatthew G. Knepley */
2527d71ae5a4SJacob 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[])
2528d71ae5a4SJacob Faibussowitsch {
25299318fe57SMatthew G. Knepley   const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
25309318fe57SMatthew G. Knepley   const PetscReal ds2 = 0.5 * dis;
253122cc497dSMatthew G. Knepley 
25329318fe57SMatthew G. Knepley   if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) {
25339318fe57SMatthew G. Knepley     f0[0] = u[0];
25349318fe57SMatthew G. Knepley     f0[1] = u[1];
25359318fe57SMatthew G. Knepley   } else {
25369318fe57SMatthew G. Knepley     PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc;
25370510c589SMatthew G. Knepley 
25389318fe57SMatthew G. Knepley     x    = PetscRealPart(u[0]);
25399318fe57SMatthew G. Knepley     y    = PetscRealPart(u[1]);
25409318fe57SMatthew G. Knepley     phi  = PetscAtan2Real(y, x);
25419318fe57SMatthew G. Knepley     sinp = PetscSinReal(phi);
25429318fe57SMatthew G. Knepley     cosp = PetscCosReal(phi);
25439318fe57SMatthew G. Knepley     if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) {
25449318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / sinp);
25459318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / sinp);
25469318fe57SMatthew G. Knepley       xc = ds2 * x / PetscAbsReal(y);
25479318fe57SMatthew G. Knepley       yc = ds2 * PetscSignReal(y);
25489318fe57SMatthew G. Knepley     } else {
25499318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / cosp);
25509318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / cosp);
25519318fe57SMatthew G. Knepley       xc = ds2 * PetscSignReal(x);
25529318fe57SMatthew G. Knepley       yc = ds2 * y / PetscAbsReal(x);
25539318fe57SMatthew G. Knepley     }
25549318fe57SMatthew G. Knepley     f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc);
25559318fe57SMatthew G. Knepley     f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc);
25569318fe57SMatthew G. Knepley   }
25579318fe57SMatthew G. Knepley   f0[2] = u[2];
25589318fe57SMatthew G. Knepley }
25590510c589SMatthew G. Knepley 
256049704ca5SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ, PetscInt Nr)
2561d71ae5a4SJacob Faibussowitsch {
25620510c589SMatthew G. Knepley   const PetscInt dim = 3;
25639318fe57SMatthew G. Knepley   PetscInt       numCells, numVertices;
2564d8c47e87SMatthew G. Knepley   PetscMPIInt    rank;
25650510c589SMatthew G. Knepley 
25660510c589SMatthew G. Knepley   PetscFunctionBegin;
256746139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
25689566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
25699566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
25700510c589SMatthew G. Knepley   /* Create topology */
25710510c589SMatthew G. Knepley   {
25720510c589SMatthew G. Knepley     PetscInt cone[8], c;
25730510c589SMatthew G. Knepley 
2574dd400576SPatrick Sanan     numCells    = rank == 0 ? 5 : 0;
2575dd400576SPatrick Sanan     numVertices = rank == 0 ? 16 : 0;
2576006a8963SMatthew G. Knepley     if (periodicZ == DM_BOUNDARY_PERIODIC) {
2577ae8bcbbbSMatthew G. Knepley       numCells *= 3;
2578dd400576SPatrick Sanan       numVertices = rank == 0 ? 24 : 0;
2579006a8963SMatthew G. Knepley     }
25809566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
25819566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8));
25829566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
2583dd400576SPatrick Sanan     if (rank == 0) {
2584006a8963SMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
25859371c9d4SSatish Balay         cone[0] = 15;
25869371c9d4SSatish Balay         cone[1] = 18;
25879371c9d4SSatish Balay         cone[2] = 17;
25889371c9d4SSatish Balay         cone[3] = 16;
25899371c9d4SSatish Balay         cone[4] = 31;
25909371c9d4SSatish Balay         cone[5] = 32;
25919371c9d4SSatish Balay         cone[6] = 33;
25929371c9d4SSatish Balay         cone[7] = 34;
25939566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
25949371c9d4SSatish Balay         cone[0] = 16;
25959371c9d4SSatish Balay         cone[1] = 17;
25969371c9d4SSatish Balay         cone[2] = 24;
25979371c9d4SSatish Balay         cone[3] = 23;
25989371c9d4SSatish Balay         cone[4] = 32;
25999371c9d4SSatish Balay         cone[5] = 36;
26009371c9d4SSatish Balay         cone[6] = 37;
26019371c9d4SSatish Balay         cone[7] = 33; /* 22 25 26 21 */
26029566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
26039371c9d4SSatish Balay         cone[0] = 18;
26049371c9d4SSatish Balay         cone[1] = 27;
26059371c9d4SSatish Balay         cone[2] = 24;
26069371c9d4SSatish Balay         cone[3] = 17;
26079371c9d4SSatish Balay         cone[4] = 34;
26089371c9d4SSatish Balay         cone[5] = 33;
26099371c9d4SSatish Balay         cone[6] = 37;
26109371c9d4SSatish Balay         cone[7] = 38;
26119566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
26129371c9d4SSatish Balay         cone[0] = 29;
26139371c9d4SSatish Balay         cone[1] = 27;
26149371c9d4SSatish Balay         cone[2] = 18;
26159371c9d4SSatish Balay         cone[3] = 15;
26169371c9d4SSatish Balay         cone[4] = 35;
26179371c9d4SSatish Balay         cone[5] = 31;
26189371c9d4SSatish Balay         cone[6] = 34;
26199371c9d4SSatish Balay         cone[7] = 38;
26209566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
26219371c9d4SSatish Balay         cone[0] = 29;
26229371c9d4SSatish Balay         cone[1] = 15;
26239371c9d4SSatish Balay         cone[2] = 16;
26249371c9d4SSatish Balay         cone[3] = 23;
26259371c9d4SSatish Balay         cone[4] = 35;
26269371c9d4SSatish Balay         cone[5] = 36;
26279371c9d4SSatish Balay         cone[6] = 32;
26289371c9d4SSatish Balay         cone[7] = 31;
26299566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
2630006a8963SMatthew G. Knepley 
26319371c9d4SSatish Balay         cone[0] = 31;
26329371c9d4SSatish Balay         cone[1] = 34;
26339371c9d4SSatish Balay         cone[2] = 33;
26349371c9d4SSatish Balay         cone[3] = 32;
26359371c9d4SSatish Balay         cone[4] = 19;
26369371c9d4SSatish Balay         cone[5] = 22;
26379371c9d4SSatish Balay         cone[6] = 21;
26389371c9d4SSatish Balay         cone[7] = 20;
26399566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
26409371c9d4SSatish Balay         cone[0] = 32;
26419371c9d4SSatish Balay         cone[1] = 33;
26429371c9d4SSatish Balay         cone[2] = 37;
26439371c9d4SSatish Balay         cone[3] = 36;
26449371c9d4SSatish Balay         cone[4] = 22;
26459371c9d4SSatish Balay         cone[5] = 25;
26469371c9d4SSatish Balay         cone[6] = 26;
26479371c9d4SSatish Balay         cone[7] = 21;
26489566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 6, cone));
26499371c9d4SSatish Balay         cone[0] = 34;
26509371c9d4SSatish Balay         cone[1] = 38;
26519371c9d4SSatish Balay         cone[2] = 37;
26529371c9d4SSatish Balay         cone[3] = 33;
26539371c9d4SSatish Balay         cone[4] = 20;
26549371c9d4SSatish Balay         cone[5] = 21;
26559371c9d4SSatish Balay         cone[6] = 26;
26569371c9d4SSatish Balay         cone[7] = 28;
26579566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 7, cone));
26589371c9d4SSatish Balay         cone[0] = 35;
26599371c9d4SSatish Balay         cone[1] = 38;
26609371c9d4SSatish Balay         cone[2] = 34;
26619371c9d4SSatish Balay         cone[3] = 31;
26629371c9d4SSatish Balay         cone[4] = 30;
26639371c9d4SSatish Balay         cone[5] = 19;
26649371c9d4SSatish Balay         cone[6] = 20;
26659371c9d4SSatish Balay         cone[7] = 28;
26669566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 8, cone));
26679371c9d4SSatish Balay         cone[0] = 35;
26689371c9d4SSatish Balay         cone[1] = 31;
26699371c9d4SSatish Balay         cone[2] = 32;
26709371c9d4SSatish Balay         cone[3] = 36;
26719371c9d4SSatish Balay         cone[4] = 30;
26729371c9d4SSatish Balay         cone[5] = 25;
26739371c9d4SSatish Balay         cone[6] = 22;
26749371c9d4SSatish Balay         cone[7] = 19;
26759566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 9, cone));
2676ae8bcbbbSMatthew G. Knepley 
26779371c9d4SSatish Balay         cone[0] = 19;
26789371c9d4SSatish Balay         cone[1] = 20;
26799371c9d4SSatish Balay         cone[2] = 21;
26809371c9d4SSatish Balay         cone[3] = 22;
26819371c9d4SSatish Balay         cone[4] = 15;
26829371c9d4SSatish Balay         cone[5] = 16;
26839371c9d4SSatish Balay         cone[6] = 17;
26849371c9d4SSatish Balay         cone[7] = 18;
26859566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 10, cone));
26869371c9d4SSatish Balay         cone[0] = 22;
26879371c9d4SSatish Balay         cone[1] = 21;
26889371c9d4SSatish Balay         cone[2] = 26;
26899371c9d4SSatish Balay         cone[3] = 25;
26909371c9d4SSatish Balay         cone[4] = 16;
26919371c9d4SSatish Balay         cone[5] = 23;
26929371c9d4SSatish Balay         cone[6] = 24;
26939371c9d4SSatish Balay         cone[7] = 17;
26949566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 11, cone));
26959371c9d4SSatish Balay         cone[0] = 20;
26969371c9d4SSatish Balay         cone[1] = 28;
26979371c9d4SSatish Balay         cone[2] = 26;
26989371c9d4SSatish Balay         cone[3] = 21;
26999371c9d4SSatish Balay         cone[4] = 18;
27009371c9d4SSatish Balay         cone[5] = 17;
27019371c9d4SSatish Balay         cone[6] = 24;
27029371c9d4SSatish Balay         cone[7] = 27;
27039566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 12, cone));
27049371c9d4SSatish Balay         cone[0] = 30;
27059371c9d4SSatish Balay         cone[1] = 28;
27069371c9d4SSatish Balay         cone[2] = 20;
27079371c9d4SSatish Balay         cone[3] = 19;
27089371c9d4SSatish Balay         cone[4] = 29;
27099371c9d4SSatish Balay         cone[5] = 15;
27109371c9d4SSatish Balay         cone[6] = 18;
27119371c9d4SSatish Balay         cone[7] = 27;
27129566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 13, cone));
27139371c9d4SSatish Balay         cone[0] = 30;
27149371c9d4SSatish Balay         cone[1] = 19;
27159371c9d4SSatish Balay         cone[2] = 22;
27169371c9d4SSatish Balay         cone[3] = 25;
27179371c9d4SSatish Balay         cone[4] = 29;
27189371c9d4SSatish Balay         cone[5] = 23;
27199371c9d4SSatish Balay         cone[6] = 16;
27209371c9d4SSatish Balay         cone[7] = 15;
27219566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
2722006a8963SMatthew G. Knepley       } else {
27239371c9d4SSatish Balay         cone[0] = 5;
27249371c9d4SSatish Balay         cone[1] = 8;
27259371c9d4SSatish Balay         cone[2] = 7;
27269371c9d4SSatish Balay         cone[3] = 6;
27279371c9d4SSatish Balay         cone[4] = 9;
27289371c9d4SSatish Balay         cone[5] = 12;
27299371c9d4SSatish Balay         cone[6] = 11;
27309371c9d4SSatish Balay         cone[7] = 10;
27319566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
27329371c9d4SSatish Balay         cone[0] = 6;
27339371c9d4SSatish Balay         cone[1] = 7;
27349371c9d4SSatish Balay         cone[2] = 14;
27359371c9d4SSatish Balay         cone[3] = 13;
27369371c9d4SSatish Balay         cone[4] = 12;
27379371c9d4SSatish Balay         cone[5] = 15;
27389371c9d4SSatish Balay         cone[6] = 16;
27399371c9d4SSatish Balay         cone[7] = 11;
27409566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
27419371c9d4SSatish Balay         cone[0] = 8;
27429371c9d4SSatish Balay         cone[1] = 17;
27439371c9d4SSatish Balay         cone[2] = 14;
27449371c9d4SSatish Balay         cone[3] = 7;
27459371c9d4SSatish Balay         cone[4] = 10;
27469371c9d4SSatish Balay         cone[5] = 11;
27479371c9d4SSatish Balay         cone[6] = 16;
27489371c9d4SSatish Balay         cone[7] = 18;
27499566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
27509371c9d4SSatish Balay         cone[0] = 19;
27519371c9d4SSatish Balay         cone[1] = 17;
27529371c9d4SSatish Balay         cone[2] = 8;
27539371c9d4SSatish Balay         cone[3] = 5;
27549371c9d4SSatish Balay         cone[4] = 20;
27559371c9d4SSatish Balay         cone[5] = 9;
27569371c9d4SSatish Balay         cone[6] = 10;
27579371c9d4SSatish Balay         cone[7] = 18;
27589566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
27599371c9d4SSatish Balay         cone[0] = 19;
27609371c9d4SSatish Balay         cone[1] = 5;
27619371c9d4SSatish Balay         cone[2] = 6;
27629371c9d4SSatish Balay         cone[3] = 13;
27639371c9d4SSatish Balay         cone[4] = 20;
27649371c9d4SSatish Balay         cone[5] = 15;
27659371c9d4SSatish Balay         cone[6] = 12;
27669371c9d4SSatish Balay         cone[7] = 9;
27679566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
2768006a8963SMatthew G. Knepley       }
2769d8c47e87SMatthew G. Knepley     }
27709566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
27719566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
27720510c589SMatthew G. Knepley   }
2773dbc1dc17SMatthew G. Knepley   /* Create cube geometry */
27740510c589SMatthew G. Knepley   {
27750510c589SMatthew G. Knepley     Vec             coordinates;
27760510c589SMatthew G. Knepley     PetscSection    coordSection;
27770510c589SMatthew G. Knepley     PetscScalar    *coords;
27780510c589SMatthew G. Knepley     PetscInt        coordSize, v;
27790510c589SMatthew G. Knepley     const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
27800510c589SMatthew G. Knepley     const PetscReal ds2 = dis / 2.0;
27810510c589SMatthew G. Knepley 
27820510c589SMatthew G. Knepley     /* Build coordinates */
27839566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
27849566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
27859566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
27869566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
27870510c589SMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
27889566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
27899566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
27900510c589SMatthew G. Knepley     }
27919566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
27929566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
27939566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
27949566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
27959566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
27969566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
27979566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
27989566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
2799dd400576SPatrick Sanan     if (rank == 0) {
28009371c9d4SSatish Balay       coords[0 * dim + 0]  = -ds2;
28019371c9d4SSatish Balay       coords[0 * dim + 1]  = -ds2;
28029371c9d4SSatish Balay       coords[0 * dim + 2]  = 0.0;
28039371c9d4SSatish Balay       coords[1 * dim + 0]  = ds2;
28049371c9d4SSatish Balay       coords[1 * dim + 1]  = -ds2;
28059371c9d4SSatish Balay       coords[1 * dim + 2]  = 0.0;
28069371c9d4SSatish Balay       coords[2 * dim + 0]  = ds2;
28079371c9d4SSatish Balay       coords[2 * dim + 1]  = ds2;
28089371c9d4SSatish Balay       coords[2 * dim + 2]  = 0.0;
28099371c9d4SSatish Balay       coords[3 * dim + 0]  = -ds2;
28109371c9d4SSatish Balay       coords[3 * dim + 1]  = ds2;
28119371c9d4SSatish Balay       coords[3 * dim + 2]  = 0.0;
28129371c9d4SSatish Balay       coords[4 * dim + 0]  = -ds2;
28139371c9d4SSatish Balay       coords[4 * dim + 1]  = -ds2;
28149371c9d4SSatish Balay       coords[4 * dim + 2]  = 1.0;
28159371c9d4SSatish Balay       coords[5 * dim + 0]  = -ds2;
28169371c9d4SSatish Balay       coords[5 * dim + 1]  = ds2;
28179371c9d4SSatish Balay       coords[5 * dim + 2]  = 1.0;
28189371c9d4SSatish Balay       coords[6 * dim + 0]  = ds2;
28199371c9d4SSatish Balay       coords[6 * dim + 1]  = ds2;
28209371c9d4SSatish Balay       coords[6 * dim + 2]  = 1.0;
28219371c9d4SSatish Balay       coords[7 * dim + 0]  = ds2;
28229371c9d4SSatish Balay       coords[7 * dim + 1]  = -ds2;
28239371c9d4SSatish Balay       coords[7 * dim + 2]  = 1.0;
28249371c9d4SSatish Balay       coords[8 * dim + 0]  = dis;
28259371c9d4SSatish Balay       coords[8 * dim + 1]  = -dis;
28269371c9d4SSatish Balay       coords[8 * dim + 2]  = 0.0;
28279371c9d4SSatish Balay       coords[9 * dim + 0]  = dis;
28289371c9d4SSatish Balay       coords[9 * dim + 1]  = dis;
28299371c9d4SSatish Balay       coords[9 * dim + 2]  = 0.0;
28309371c9d4SSatish Balay       coords[10 * dim + 0] = dis;
28319371c9d4SSatish Balay       coords[10 * dim + 1] = -dis;
28329371c9d4SSatish Balay       coords[10 * dim + 2] = 1.0;
28339371c9d4SSatish Balay       coords[11 * dim + 0] = dis;
28349371c9d4SSatish Balay       coords[11 * dim + 1] = dis;
28359371c9d4SSatish Balay       coords[11 * dim + 2] = 1.0;
28369371c9d4SSatish Balay       coords[12 * dim + 0] = -dis;
28379371c9d4SSatish Balay       coords[12 * dim + 1] = dis;
28389371c9d4SSatish Balay       coords[12 * dim + 2] = 0.0;
28399371c9d4SSatish Balay       coords[13 * dim + 0] = -dis;
28409371c9d4SSatish Balay       coords[13 * dim + 1] = dis;
28419371c9d4SSatish Balay       coords[13 * dim + 2] = 1.0;
28429371c9d4SSatish Balay       coords[14 * dim + 0] = -dis;
28439371c9d4SSatish Balay       coords[14 * dim + 1] = -dis;
28449371c9d4SSatish Balay       coords[14 * dim + 2] = 0.0;
28459371c9d4SSatish Balay       coords[15 * dim + 0] = -dis;
28469371c9d4SSatish Balay       coords[15 * dim + 1] = -dis;
28479371c9d4SSatish Balay       coords[15 * dim + 2] = 1.0;
2848ae8bcbbbSMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
28499371c9d4SSatish Balay         /* 15 31 19 */ coords[16 * dim + 0] = -ds2;
28509371c9d4SSatish Balay         coords[16 * dim + 1]                = -ds2;
28519371c9d4SSatish Balay         coords[16 * dim + 2]                = 0.5;
28529371c9d4SSatish Balay         /* 16 32 22 */ coords[17 * dim + 0] = ds2;
28539371c9d4SSatish Balay         coords[17 * dim + 1]                = -ds2;
28549371c9d4SSatish Balay         coords[17 * dim + 2]                = 0.5;
28559371c9d4SSatish Balay         /* 17 33 21 */ coords[18 * dim + 0] = ds2;
28569371c9d4SSatish Balay         coords[18 * dim + 1]                = ds2;
28579371c9d4SSatish Balay         coords[18 * dim + 2]                = 0.5;
28589371c9d4SSatish Balay         /* 18 34 20 */ coords[19 * dim + 0] = -ds2;
28599371c9d4SSatish Balay         coords[19 * dim + 1]                = ds2;
28609371c9d4SSatish Balay         coords[19 * dim + 2]                = 0.5;
28619371c9d4SSatish Balay         /* 29 35 30 */ coords[20 * dim + 0] = -dis;
28629371c9d4SSatish Balay         coords[20 * dim + 1]                = -dis;
28639371c9d4SSatish Balay         coords[20 * dim + 2]                = 0.5;
28649371c9d4SSatish Balay         /* 23 36 25 */ coords[21 * dim + 0] = dis;
28659371c9d4SSatish Balay         coords[21 * dim + 1]                = -dis;
28669371c9d4SSatish Balay         coords[21 * dim + 2]                = 0.5;
28679371c9d4SSatish Balay         /* 24 37 26 */ coords[22 * dim + 0] = dis;
28689371c9d4SSatish Balay         coords[22 * dim + 1]                = dis;
28699371c9d4SSatish Balay         coords[22 * dim + 2]                = 0.5;
28709371c9d4SSatish Balay         /* 27 38 28 */ coords[23 * dim + 0] = -dis;
28719371c9d4SSatish Balay         coords[23 * dim + 1]                = dis;
28729371c9d4SSatish Balay         coords[23 * dim + 2]                = 0.5;
2873ae8bcbbbSMatthew G. Knepley       }
2874d8c47e87SMatthew G. Knepley     }
28759566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
28769566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
28779566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
28780510c589SMatthew G. Knepley   }
2879006a8963SMatthew G. Knepley   /* Create periodicity */
2880006a8963SMatthew G. Knepley   if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) {
28816858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
28826858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
2883006a8963SMatthew G. Knepley     PetscReal lower[3]   = {0.0, 0.0, 0.0};
2884ae8bcbbbSMatthew G. Knepley     PetscReal upper[3]   = {1.0, 1.0, 1.5};
28856858538eSMatthew G. Knepley     PetscInt  numZCells  = 3;
2886006a8963SMatthew G. Knepley 
28876858538eSMatthew G. Knepley     L[2]       = upper[2] - lower[2];
28886858538eSMatthew G. Knepley     maxCell[2] = 1.1 * (L[2] / numZCells);
28894fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
2890006a8963SMatthew G. Knepley   }
2891dbc1dc17SMatthew G. Knepley   {
28929318fe57SMatthew G. Knepley     DM          cdm;
28939318fe57SMatthew G. Knepley     PetscDS     cds;
28949318fe57SMatthew G. Knepley     PetscScalar c[2] = {1.0, 1.0};
2895dbc1dc17SMatthew G. Knepley 
289649704ca5SMatthew G. Knepley     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL));
28979566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
28989566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
28999566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 2, c));
2900dbc1dc17SMatthew G. Knepley   }
290146139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
290246139095SJed Brown 
29039318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
29049566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(dm));
290549704ca5SMatthew G. Knepley 
290649704ca5SMatthew G. Knepley   char        oldprefix[PETSC_MAX_PATH_LEN];
290749704ca5SMatthew G. Knepley   const char *prefix;
290849704ca5SMatthew G. Knepley 
290949704ca5SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
291049704ca5SMatthew G. Knepley   PetscCall(PetscStrncpy(oldprefix, prefix, PETSC_MAX_PATH_LEN));
291149704ca5SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, "petsc_cyl_ref_"));
291249704ca5SMatthew G. Knepley   for (PetscInt r = 0; r < PetscMax(0, Nr); ++r) {
291349704ca5SMatthew G. Knepley     DM rdm;
291449704ca5SMatthew G. Knepley 
291549704ca5SMatthew G. Knepley     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
291649704ca5SMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &rdm));
291749704ca5SMatthew G. Knepley   }
291849704ca5SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldprefix));
291949704ca5SMatthew G. Knepley   PetscCall(DMPlexRemapGeometry(dm, 0.0, snapToCylinder));
292049704ca5SMatthew G. Knepley 
292149704ca5SMatthew G. Knepley   DMLabel         bdlabel, edgelabel;
292249704ca5SMatthew G. Knepley   IS              faceIS;
292349704ca5SMatthew G. Knepley   const PetscInt *faces;
292449704ca5SMatthew G. Knepley   PetscInt        Nf;
292549704ca5SMatthew G. Knepley 
292649704ca5SMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "marker"));
292749704ca5SMatthew G. Knepley   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
292849704ca5SMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "generatrix"));
292949704ca5SMatthew G. Knepley   PetscCall(DMGetLabel(dm, "generatrix", &edgelabel));
293049704ca5SMatthew G. Knepley   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
293149704ca5SMatthew G. Knepley   // Remove faces on top and bottom
293249704ca5SMatthew G. Knepley   PetscCall(DMLabelGetStratumIS(bdlabel, 1, &faceIS));
2933ba1b3593SJeremy L Thompson   if (faceIS) {
293449704ca5SMatthew G. Knepley     PetscCall(ISGetLocalSize(faceIS, &Nf));
293549704ca5SMatthew G. Knepley     PetscCall(ISGetIndices(faceIS, &faces));
293649704ca5SMatthew G. Knepley     for (PetscInt f = 0; f < Nf; ++f) {
293749704ca5SMatthew G. Knepley       PetscReal vol, normal[3];
293849704ca5SMatthew G. Knepley 
293949704ca5SMatthew G. Knepley       PetscCall(DMPlexComputeCellGeometryFVM(dm, faces[f], &vol, NULL, normal));
294049704ca5SMatthew G. Knepley       if (PetscAbsReal(normal[2]) < PETSC_SMALL) PetscCall(DMLabelSetValue(edgelabel, faces[f], 1));
294149704ca5SMatthew G. Knepley     }
294249704ca5SMatthew G. Knepley     PetscCall(ISRestoreIndices(faceIS, &faces));
294349704ca5SMatthew G. Knepley     PetscCall(ISDestroy(&faceIS));
2944ba1b3593SJeremy L Thompson   }
294549704ca5SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(dm, bdlabel));
294649704ca5SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(dm, edgelabel));
29473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
29480510c589SMatthew G. Knepley }
29490510c589SMatthew G. Knepley 
295024119c2aSMatthew G. Knepley /*@
29519318fe57SMatthew G. Knepley   DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra.
295224119c2aSMatthew G. Knepley 
2953d083f849SBarry Smith   Collective
295424119c2aSMatthew G. Knepley 
295524119c2aSMatthew G. Knepley   Input Parameters:
2956a1cb98faSBarry Smith + comm      - The communicator for the `DM` object
295749704ca5SMatthew G. Knepley . periodicZ - The boundary type for the Z direction
295849704ca5SMatthew G. Knepley - Nr        - The number of refinements to carry out
295924119c2aSMatthew G. Knepley 
296024119c2aSMatthew G. Knepley   Output Parameter:
296120f4b53cSBarry Smith . dm - The `DM` object
296224119c2aSMatthew G. Knepley 
296324119c2aSMatthew G. Knepley   Level: beginner
296424119c2aSMatthew G. Knepley 
2965a1cb98faSBarry Smith   Note:
2966a4e35b19SJacob Faibussowitsch   Here is the output numbering looking from the bottom of the cylinder\:
2967a1cb98faSBarry Smith .vb
2968a1cb98faSBarry Smith        17-----14
2969a1cb98faSBarry Smith         |     |
2970a1cb98faSBarry Smith         |  2  |
2971a1cb98faSBarry Smith         |     |
2972a1cb98faSBarry Smith  17-----8-----7-----14
2973a1cb98faSBarry Smith   |     |     |     |
2974a1cb98faSBarry Smith   |  3  |  0  |  1  |
2975a1cb98faSBarry Smith   |     |     |     |
2976a1cb98faSBarry Smith  19-----5-----6-----13
2977a1cb98faSBarry Smith         |     |
2978a1cb98faSBarry Smith         |  4  |
2979a1cb98faSBarry Smith         |     |
2980a1cb98faSBarry Smith        19-----13
2981a1cb98faSBarry Smith 
2982a1cb98faSBarry Smith  and up through the top
2983a1cb98faSBarry Smith 
2984a1cb98faSBarry Smith        18-----16
2985a1cb98faSBarry Smith         |     |
2986a1cb98faSBarry Smith         |  2  |
2987a1cb98faSBarry Smith         |     |
2988a1cb98faSBarry Smith  18----10----11-----16
2989a1cb98faSBarry Smith   |     |     |     |
2990a1cb98faSBarry Smith   |  3  |  0  |  1  |
2991a1cb98faSBarry Smith   |     |     |     |
2992a1cb98faSBarry Smith  20-----9----12-----15
2993a1cb98faSBarry Smith         |     |
2994a1cb98faSBarry Smith         |  4  |
2995a1cb98faSBarry Smith         |     |
2996a1cb98faSBarry Smith        20-----15
2997a1cb98faSBarry Smith .ve
2998a1cb98faSBarry Smith 
29991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
300024119c2aSMatthew G. Knepley @*/
300149704ca5SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, PetscInt Nr, DM *dm)
3002d71ae5a4SJacob Faibussowitsch {
30039318fe57SMatthew G. Knepley   PetscFunctionBegin;
300449704ca5SMatthew G. Knepley   PetscAssertPointer(dm, 4);
30059566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
30069566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
300749704ca5SMatthew G. Knepley   PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ, Nr));
30083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30099318fe57SMatthew G. Knepley }
30109318fe57SMatthew G. Knepley 
3011d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate)
3012d71ae5a4SJacob Faibussowitsch {
301324119c2aSMatthew G. Knepley   const PetscInt dim = 3;
3014412e9a14SMatthew G. Knepley   PetscInt       numCells, numVertices, v;
30159fe9f049SMatthew G. Knepley   PetscMPIInt    rank;
301624119c2aSMatthew G. Knepley 
301724119c2aSMatthew G. Knepley   PetscFunctionBegin;
301863a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n);
301946139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
30209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
30219566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
3022412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
30239566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
302424119c2aSMatthew G. Knepley   /* Create topology */
302524119c2aSMatthew G. Knepley   {
302624119c2aSMatthew G. Knepley     PetscInt cone[6], c;
302724119c2aSMatthew G. Knepley 
3028dd400576SPatrick Sanan     numCells    = rank == 0 ? n : 0;
3029dd400576SPatrick Sanan     numVertices = rank == 0 ? 2 * (n + 1) : 0;
30309566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
30319566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
30329566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
303324119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
30349371c9d4SSatish Balay       cone[0] = c + n * 1;
30359371c9d4SSatish Balay       cone[1] = (c + 1) % n + n * 1;
30369371c9d4SSatish Balay       cone[2] = 0 + 3 * n;
30379371c9d4SSatish Balay       cone[3] = c + n * 2;
30389371c9d4SSatish Balay       cone[4] = (c + 1) % n + n * 2;
30399371c9d4SSatish Balay       cone[5] = 1 + 3 * n;
30409566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(dm, c, cone));
30419566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR));
304224119c2aSMatthew G. Knepley     }
30439566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
30449566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
304524119c2aSMatthew G. Knepley   }
304648a46eb9SPierre Jolivet   for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT));
304724119c2aSMatthew G. Knepley   /* Create cylinder geometry */
304824119c2aSMatthew G. Knepley   {
304924119c2aSMatthew G. Knepley     Vec          coordinates;
305024119c2aSMatthew G. Knepley     PetscSection coordSection;
305124119c2aSMatthew G. Knepley     PetscScalar *coords;
3052412e9a14SMatthew G. Knepley     PetscInt     coordSize, c;
305324119c2aSMatthew G. Knepley 
305424119c2aSMatthew G. Knepley     /* Build coordinates */
30559566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
30569566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
30579566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
30589566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
305924119c2aSMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
30609566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
30619566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
306224119c2aSMatthew G. Knepley     }
30639566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
30649566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
30659566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
30669566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
30679566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
30689566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
30699566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
30709566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
307124119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
30729371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
30739371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
30749371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 2] = 1.0;
30759371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
30769371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
30779371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 2] = 0.0;
307824119c2aSMatthew G. Knepley     }
3079dd400576SPatrick Sanan     if (rank == 0) {
30809371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 0] = 0.0;
30819371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 1] = 0.0;
30829371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 2] = 1.0;
30839371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 0] = 0.0;
30849371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 1] = 0.0;
30859371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 2] = 0.0;
30869fe9f049SMatthew G. Knepley     }
30879566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
30889566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
30899566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
309024119c2aSMatthew G. Knepley   }
309146139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
30929318fe57SMatthew G. Knepley   /* Interpolate */
30939566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
30943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
30959318fe57SMatthew G. Knepley }
30969318fe57SMatthew G. Knepley 
30979318fe57SMatthew G. Knepley /*@
30989318fe57SMatthew G. Knepley   DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges.
30999318fe57SMatthew G. Knepley 
31009318fe57SMatthew G. Knepley   Collective
31019318fe57SMatthew G. Knepley 
31029318fe57SMatthew G. Knepley   Input Parameters:
3103a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
31049318fe57SMatthew G. Knepley . n           - The number of wedges around the origin
31059318fe57SMatthew G. Knepley - interpolate - Create edges and faces
31069318fe57SMatthew G. Knepley 
31079318fe57SMatthew G. Knepley   Output Parameter:
3108a1cb98faSBarry Smith . dm - The `DM` object
31099318fe57SMatthew G. Knepley 
31109318fe57SMatthew G. Knepley   Level: beginner
31119318fe57SMatthew G. Knepley 
31121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
31139318fe57SMatthew G. Knepley @*/
3114d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm)
3115d71ae5a4SJacob Faibussowitsch {
31169318fe57SMatthew G. Knepley   PetscFunctionBegin;
31174f572ea9SToby Isaac   PetscAssertPointer(dm, 4);
31189566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
31199566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
31209566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate));
31213ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
312224119c2aSMatthew G. Knepley }
312324119c2aSMatthew G. Knepley 
3124d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
3125d71ae5a4SJacob Faibussowitsch {
312665a81367SMatthew G. Knepley   PetscReal prod = 0.0;
312765a81367SMatthew G. Knepley   PetscInt  i;
312865a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]);
312965a81367SMatthew G. Knepley   return PetscSqrtReal(prod);
313065a81367SMatthew G. Knepley }
3131dd2b43ebSStefano Zampini 
3132d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
3133d71ae5a4SJacob Faibussowitsch {
313465a81367SMatthew G. Knepley   PetscReal prod = 0.0;
313565a81367SMatthew G. Knepley   PetscInt  i;
313665a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += x[i] * y[i];
313765a81367SMatthew G. Knepley   return prod;
313865a81367SMatthew G. Knepley }
313965a81367SMatthew G. Knepley 
314051a74b61SMatthew G. Knepley /* The first constant is the sphere radius */
3141d71ae5a4SJacob 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[])
3142d71ae5a4SJacob Faibussowitsch {
314351a74b61SMatthew G. Knepley   PetscReal r     = PetscRealPart(constants[0]);
314451a74b61SMatthew G. Knepley   PetscReal norm2 = 0.0, fac;
314551a74b61SMatthew G. Knepley   PetscInt  n     = uOff[1] - uOff[0], d;
314651a74b61SMatthew G. Knepley 
314751a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d]));
314851a74b61SMatthew G. Knepley   fac = r / PetscSqrtReal(norm2);
314951a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) f0[d] = u[d] * fac;
315051a74b61SMatthew G. Knepley }
315151a74b61SMatthew G. Knepley 
3152d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R)
3153d71ae5a4SJacob Faibussowitsch {
315465a81367SMatthew G. Knepley   const PetscInt embedDim = dim + 1;
315565a81367SMatthew G. Knepley   PetscSection   coordSection;
315665a81367SMatthew G. Knepley   Vec            coordinates;
315765a81367SMatthew G. Knepley   PetscScalar   *coords;
315865a81367SMatthew G. Knepley   PetscReal     *coordsIn;
315907c565c5SJose E. Roman   PetscInt       numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, e;
316065a81367SMatthew G. Knepley   PetscMPIInt    rank;
316165a81367SMatthew G. Knepley 
316265a81367SMatthew G. Knepley   PetscFunctionBegin;
31639318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, simplex, 3);
316446139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
31659566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
31669566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim + 1));
31679566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
316865a81367SMatthew G. Knepley   switch (dim) {
31695c344501SMatthew G. Knepley   case 1:
31705c344501SMatthew G. Knepley     numCells = 16;
31715c344501SMatthew G. Knepley     numVerts = numCells;
31725c344501SMatthew G. Knepley 
31735c344501SMatthew G. Knepley     // Build Topology
31745c344501SMatthew G. Knepley     PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
31755c344501SMatthew G. Knepley     for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
31765c344501SMatthew G. Knepley     PetscCall(DMSetUp(dm));
31775c344501SMatthew G. Knepley     for (PetscInt c = 0; c < numCells; ++c) {
31785c344501SMatthew G. Knepley       PetscInt cone[2];
31795c344501SMatthew G. Knepley 
31805c344501SMatthew G. Knepley       cone[0] = c + numCells;
31815c344501SMatthew G. Knepley       cone[1] = (c + 1) % numVerts + numCells;
31825c344501SMatthew G. Knepley       PetscCall(DMPlexSetCone(dm, c, cone));
31835c344501SMatthew G. Knepley     }
31845c344501SMatthew G. Knepley     PetscCall(DMPlexSymmetrize(dm));
31855c344501SMatthew G. Knepley     PetscCall(DMPlexStratify(dm));
31865c344501SMatthew G. Knepley     PetscCall(PetscMalloc1(numVerts * embedDim, &coordsIn));
31875c344501SMatthew G. Knepley     for (PetscInt v = 0; v < numVerts; ++v) {
31885c344501SMatthew G. Knepley       const PetscReal rad = 2. * PETSC_PI * v / numVerts;
31895c344501SMatthew G. Knepley 
31905c344501SMatthew G. Knepley       coordsIn[v * embedDim + 0] = PetscCosReal(rad);
31915c344501SMatthew G. Knepley       coordsIn[v * embedDim + 1] = PetscSinReal(rad);
31925c344501SMatthew G. Knepley     }
31935c344501SMatthew G. Knepley     break;
319465a81367SMatthew G. Knepley   case 2:
319565a81367SMatthew G. Knepley     if (simplex) {
319651a74b61SMatthew G. Knepley       const PetscReal radius    = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI);
319751a74b61SMatthew G. Knepley       const PetscReal edgeLen   = 2.0 / (1.0 + PETSC_PHI) * (R / radius);
319865a81367SMatthew G. Knepley       const PetscInt  degree    = 5;
319951a74b61SMatthew G. Knepley       PetscReal       vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)};
320065a81367SMatthew G. Knepley       PetscInt        s[3]      = {1, 1, 1};
320165a81367SMatthew G. Knepley       PetscInt        cone[3];
320207c565c5SJose E. Roman       PetscInt       *graph;
320365a81367SMatthew G. Knepley 
32049371c9d4SSatish Balay       vertex[0] *= R / radius;
32059371c9d4SSatish Balay       vertex[1] *= R / radius;
32069371c9d4SSatish Balay       vertex[2] *= R / radius;
3207dd400576SPatrick Sanan       numCells    = rank == 0 ? 20 : 0;
3208dd400576SPatrick Sanan       numVerts    = rank == 0 ? 12 : 0;
320965a81367SMatthew G. Knepley       firstVertex = numCells;
321051a74b61SMatthew G. Knepley       /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of
321165a81367SMatthew G. Knepley 
321265a81367SMatthew G. Knepley            (0, \pm 1/\phi+1, \pm \phi/\phi+1)
321365a81367SMatthew G. Knepley 
321465a81367SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
321551a74b61SMatthew G. Knepley          length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393.
321665a81367SMatthew G. Knepley       */
321765a81367SMatthew G. Knepley       /* Construct vertices */
32189566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3219dd400576SPatrick Sanan       if (rank == 0) {
322007c565c5SJose E. Roman         for (PetscInt p = 0, i = 0; p < embedDim; ++p) {
322165a81367SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
322265a81367SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
322365a81367SMatthew G. Knepley               for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim];
322465a81367SMatthew G. Knepley               ++i;
322565a81367SMatthew G. Knepley             }
322665a81367SMatthew G. Knepley           }
322765a81367SMatthew G. Knepley         }
322845da822fSValeria Barra       }
322965a81367SMatthew G. Knepley       /* Construct graph */
32309566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
323107c565c5SJose E. Roman       for (PetscInt i = 0; i < numVerts; ++i) {
323207c565c5SJose E. Roman         PetscInt k = 0;
323307c565c5SJose E. Roman         for (PetscInt j = 0; j < numVerts; ++j) {
32349371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
32359371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
32369371c9d4SSatish Balay             ++k;
32379371c9d4SSatish Balay           }
323865a81367SMatthew G. Knepley         }
323963a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
324065a81367SMatthew G. Knepley       }
324165a81367SMatthew G. Knepley       /* Build Topology */
32429566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
324307c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
32449566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
324565a81367SMatthew G. Knepley       /* Cells */
324607c565c5SJose E. Roman       for (PetscInt i = 0, c = 0; i < numVerts; ++i) {
324707c565c5SJose E. Roman         for (PetscInt j = 0; j < i; ++j) {
324807c565c5SJose E. Roman           for (PetscInt k = 0; k < j; ++k) {
324965a81367SMatthew G. Knepley             if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) {
32509371c9d4SSatish Balay               cone[0] = firstVertex + i;
32519371c9d4SSatish Balay               cone[1] = firstVertex + j;
32529371c9d4SSatish Balay               cone[2] = firstVertex + k;
325365a81367SMatthew G. Knepley               /* Check orientation */
325465a81367SMatthew G. Knepley               {
32559371c9d4SSatish Balay                 const PetscInt epsilon[3][3][3] = {
32569371c9d4SSatish Balay                   {{0, 0, 0},  {0, 0, 1},  {0, -1, 0}},
32579371c9d4SSatish Balay                   {{0, 0, -1}, {0, 0, 0},  {1, 0, 0} },
32589371c9d4SSatish Balay                   {{0, 1, 0},  {-1, 0, 0}, {0, 0, 0} }
32599371c9d4SSatish Balay                 };
326065a81367SMatthew G. Knepley                 PetscReal normal[3];
326165a81367SMatthew G. Knepley                 PetscInt  e, f;
326265a81367SMatthew G. Knepley 
326365a81367SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) {
326465a81367SMatthew G. Knepley                   normal[d] = 0.0;
326565a81367SMatthew G. Knepley                   for (e = 0; e < embedDim; ++e) {
3266ad540459SPierre 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]);
326765a81367SMatthew G. Knepley                   }
326865a81367SMatthew G. Knepley                 }
32699371c9d4SSatish Balay                 if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
32709371c9d4SSatish Balay                   PetscInt tmp = cone[1];
32719371c9d4SSatish Balay                   cone[1]      = cone[2];
32729371c9d4SSatish Balay                   cone[2]      = tmp;
327365a81367SMatthew G. Knepley                 }
327465a81367SMatthew G. Knepley               }
32759566063dSJacob Faibussowitsch               PetscCall(DMPlexSetCone(dm, c++, cone));
327665a81367SMatthew G. Knepley             }
327765a81367SMatthew G. Knepley           }
327865a81367SMatthew G. Knepley         }
327965a81367SMatthew G. Knepley       }
32809566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
32819566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
32829566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
328365a81367SMatthew G. Knepley     } else {
32842829fed8SMatthew G. Knepley       /*
32852829fed8SMatthew G. Knepley         12-21--13
32862829fed8SMatthew G. Knepley          |     |
32872829fed8SMatthew G. Knepley         25  4  24
32882829fed8SMatthew G. Knepley          |     |
32892829fed8SMatthew G. Knepley   12-25--9-16--8-24--13
32902829fed8SMatthew G. Knepley    |     |     |     |
32912829fed8SMatthew G. Knepley   23  5 17  0 15  3  22
32922829fed8SMatthew G. Knepley    |     |     |     |
32932829fed8SMatthew G. Knepley   10-20--6-14--7-19--11
32942829fed8SMatthew G. Knepley          |     |
32952829fed8SMatthew G. Knepley         20  1  19
32962829fed8SMatthew G. Knepley          |     |
32972829fed8SMatthew G. Knepley         10-18--11
32982829fed8SMatthew G. Knepley          |     |
32992829fed8SMatthew G. Knepley         23  2  22
33002829fed8SMatthew G. Knepley          |     |
33012829fed8SMatthew G. Knepley         12-21--13
33022829fed8SMatthew G. Knepley        */
33032829fed8SMatthew G. Knepley       PetscInt cone[4], ornt[4];
33042829fed8SMatthew G. Knepley 
3305dd400576SPatrick Sanan       numCells    = rank == 0 ? 6 : 0;
3306dd400576SPatrick Sanan       numEdges    = rank == 0 ? 12 : 0;
3307dd400576SPatrick Sanan       numVerts    = rank == 0 ? 8 : 0;
330865a81367SMatthew G. Knepley       firstVertex = numCells;
330965a81367SMatthew G. Knepley       firstEdge   = numCells + numVerts;
33102829fed8SMatthew G. Knepley       /* Build Topology */
33119566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts));
331207c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4));
331348a46eb9SPierre Jolivet       for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
33149566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3315dd400576SPatrick Sanan       if (rank == 0) {
33162829fed8SMatthew G. Knepley         /* Cell 0 */
33179371c9d4SSatish Balay         cone[0] = 14;
33189371c9d4SSatish Balay         cone[1] = 15;
33199371c9d4SSatish Balay         cone[2] = 16;
33209371c9d4SSatish Balay         cone[3] = 17;
33219566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
33229371c9d4SSatish Balay         ornt[0] = 0;
33239371c9d4SSatish Balay         ornt[1] = 0;
33249371c9d4SSatish Balay         ornt[2] = 0;
33259371c9d4SSatish Balay         ornt[3] = 0;
33269566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 0, ornt));
33272829fed8SMatthew G. Knepley         /* Cell 1 */
33289371c9d4SSatish Balay         cone[0] = 18;
33299371c9d4SSatish Balay         cone[1] = 19;
33309371c9d4SSatish Balay         cone[2] = 14;
33319371c9d4SSatish Balay         cone[3] = 20;
33329566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
33339371c9d4SSatish Balay         ornt[0] = 0;
33349371c9d4SSatish Balay         ornt[1] = 0;
33359371c9d4SSatish Balay         ornt[2] = -1;
33369371c9d4SSatish Balay         ornt[3] = 0;
33379566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 1, ornt));
33382829fed8SMatthew G. Knepley         /* Cell 2 */
33399371c9d4SSatish Balay         cone[0] = 21;
33409371c9d4SSatish Balay         cone[1] = 22;
33419371c9d4SSatish Balay         cone[2] = 18;
33429371c9d4SSatish Balay         cone[3] = 23;
33439566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
33449371c9d4SSatish Balay         ornt[0] = 0;
33459371c9d4SSatish Balay         ornt[1] = 0;
33469371c9d4SSatish Balay         ornt[2] = -1;
33479371c9d4SSatish Balay         ornt[3] = 0;
33489566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 2, ornt));
33492829fed8SMatthew G. Knepley         /* Cell 3 */
33509371c9d4SSatish Balay         cone[0] = 19;
33519371c9d4SSatish Balay         cone[1] = 22;
33529371c9d4SSatish Balay         cone[2] = 24;
33539371c9d4SSatish Balay         cone[3] = 15;
33549566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
33559371c9d4SSatish Balay         ornt[0] = -1;
33569371c9d4SSatish Balay         ornt[1] = -1;
33579371c9d4SSatish Balay         ornt[2] = 0;
33589371c9d4SSatish Balay         ornt[3] = -1;
33599566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 3, ornt));
33602829fed8SMatthew G. Knepley         /* Cell 4 */
33619371c9d4SSatish Balay         cone[0] = 16;
33629371c9d4SSatish Balay         cone[1] = 24;
33639371c9d4SSatish Balay         cone[2] = 21;
33649371c9d4SSatish Balay         cone[3] = 25;
33659566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
33669371c9d4SSatish Balay         ornt[0] = -1;
33679371c9d4SSatish Balay         ornt[1] = -1;
33689371c9d4SSatish Balay         ornt[2] = -1;
33699371c9d4SSatish Balay         ornt[3] = 0;
33709566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 4, ornt));
33712829fed8SMatthew G. Knepley         /* Cell 5 */
33729371c9d4SSatish Balay         cone[0] = 20;
33739371c9d4SSatish Balay         cone[1] = 17;
33749371c9d4SSatish Balay         cone[2] = 25;
33759371c9d4SSatish Balay         cone[3] = 23;
33769566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
33779371c9d4SSatish Balay         ornt[0] = -1;
33789371c9d4SSatish Balay         ornt[1] = -1;
33799371c9d4SSatish Balay         ornt[2] = -1;
33809371c9d4SSatish Balay         ornt[3] = -1;
33819566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 5, ornt));
33822829fed8SMatthew G. Knepley         /* Edges */
33839371c9d4SSatish Balay         cone[0] = 6;
33849371c9d4SSatish Balay         cone[1] = 7;
33859566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
33869371c9d4SSatish Balay         cone[0] = 7;
33879371c9d4SSatish Balay         cone[1] = 8;
33889566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 15, cone));
33899371c9d4SSatish Balay         cone[0] = 8;
33909371c9d4SSatish Balay         cone[1] = 9;
33919566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 16, cone));
33929371c9d4SSatish Balay         cone[0] = 9;
33939371c9d4SSatish Balay         cone[1] = 6;
33949566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 17, cone));
33959371c9d4SSatish Balay         cone[0] = 10;
33969371c9d4SSatish Balay         cone[1] = 11;
33979566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 18, cone));
33989371c9d4SSatish Balay         cone[0] = 11;
33999371c9d4SSatish Balay         cone[1] = 7;
34009566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 19, cone));
34019371c9d4SSatish Balay         cone[0] = 6;
34029371c9d4SSatish Balay         cone[1] = 10;
34039566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 20, cone));
34049371c9d4SSatish Balay         cone[0] = 12;
34059371c9d4SSatish Balay         cone[1] = 13;
34069566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 21, cone));
34079371c9d4SSatish Balay         cone[0] = 13;
34089371c9d4SSatish Balay         cone[1] = 11;
34099566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 22, cone));
34109371c9d4SSatish Balay         cone[0] = 10;
34119371c9d4SSatish Balay         cone[1] = 12;
34129566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 23, cone));
34139371c9d4SSatish Balay         cone[0] = 13;
34149371c9d4SSatish Balay         cone[1] = 8;
34159566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 24, cone));
34169371c9d4SSatish Balay         cone[0] = 12;
34179371c9d4SSatish Balay         cone[1] = 9;
34189566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 25, cone));
341945da822fSValeria Barra       }
34209566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
34219566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
34222829fed8SMatthew G. Knepley       /* Build coordinates */
34239566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3424dd400576SPatrick Sanan       if (rank == 0) {
34259371c9d4SSatish Balay         coordsIn[0 * embedDim + 0] = -R;
34269371c9d4SSatish Balay         coordsIn[0 * embedDim + 1] = R;
34279371c9d4SSatish Balay         coordsIn[0 * embedDim + 2] = -R;
34289371c9d4SSatish Balay         coordsIn[1 * embedDim + 0] = R;
34299371c9d4SSatish Balay         coordsIn[1 * embedDim + 1] = R;
34309371c9d4SSatish Balay         coordsIn[1 * embedDim + 2] = -R;
34319371c9d4SSatish Balay         coordsIn[2 * embedDim + 0] = R;
34329371c9d4SSatish Balay         coordsIn[2 * embedDim + 1] = -R;
34339371c9d4SSatish Balay         coordsIn[2 * embedDim + 2] = -R;
34349371c9d4SSatish Balay         coordsIn[3 * embedDim + 0] = -R;
34359371c9d4SSatish Balay         coordsIn[3 * embedDim + 1] = -R;
34369371c9d4SSatish Balay         coordsIn[3 * embedDim + 2] = -R;
34379371c9d4SSatish Balay         coordsIn[4 * embedDim + 0] = -R;
34389371c9d4SSatish Balay         coordsIn[4 * embedDim + 1] = R;
34399371c9d4SSatish Balay         coordsIn[4 * embedDim + 2] = R;
34409371c9d4SSatish Balay         coordsIn[5 * embedDim + 0] = R;
34419371c9d4SSatish Balay         coordsIn[5 * embedDim + 1] = R;
34429371c9d4SSatish Balay         coordsIn[5 * embedDim + 2] = R;
34439371c9d4SSatish Balay         coordsIn[6 * embedDim + 0] = -R;
34449371c9d4SSatish Balay         coordsIn[6 * embedDim + 1] = -R;
34459371c9d4SSatish Balay         coordsIn[6 * embedDim + 2] = R;
34469371c9d4SSatish Balay         coordsIn[7 * embedDim + 0] = R;
34479371c9d4SSatish Balay         coordsIn[7 * embedDim + 1] = -R;
34489371c9d4SSatish Balay         coordsIn[7 * embedDim + 2] = R;
344965a81367SMatthew G. Knepley       }
345045da822fSValeria Barra     }
345165a81367SMatthew G. Knepley     break;
345265a81367SMatthew G. Knepley   case 3:
3453116ded15SMatthew G. Knepley     if (simplex) {
3454116ded15SMatthew G. Knepley       const PetscReal edgeLen         = 1.0 / PETSC_PHI;
345551a74b61SMatthew G. Knepley       PetscReal       vertexA[4]      = {0.5, 0.5, 0.5, 0.5};
345651a74b61SMatthew G. Knepley       PetscReal       vertexB[4]      = {1.0, 0.0, 0.0, 0.0};
345751a74b61SMatthew G. Knepley       PetscReal       vertexC[4]      = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0};
3458116ded15SMatthew G. Knepley       const PetscInt  degree          = 12;
3459116ded15SMatthew G. Knepley       PetscInt        s[4]            = {1, 1, 1};
34609371c9d4SSatish Balay       PetscInt        evenPerm[12][4] = {
34619371c9d4SSatish Balay         {0, 1, 2, 3},
34629371c9d4SSatish Balay         {0, 2, 3, 1},
34639371c9d4SSatish Balay         {0, 3, 1, 2},
34649371c9d4SSatish Balay         {1, 0, 3, 2},
34659371c9d4SSatish Balay         {1, 2, 0, 3},
34669371c9d4SSatish Balay         {1, 3, 2, 0},
34679371c9d4SSatish Balay         {2, 0, 1, 3},
34689371c9d4SSatish Balay         {2, 1, 3, 0},
34699371c9d4SSatish Balay         {2, 3, 0, 1},
34709371c9d4SSatish Balay         {3, 0, 2, 1},
34719371c9d4SSatish Balay         {3, 1, 0, 2},
34729371c9d4SSatish Balay         {3, 2, 1, 0}
34739371c9d4SSatish Balay       };
3474116ded15SMatthew G. Knepley       PetscInt  cone[4];
3475116ded15SMatthew G. Knepley       PetscInt *graph, p, i, j, k, l;
3476116ded15SMatthew G. Knepley 
34779371c9d4SSatish Balay       vertexA[0] *= R;
34789371c9d4SSatish Balay       vertexA[1] *= R;
34799371c9d4SSatish Balay       vertexA[2] *= R;
34809371c9d4SSatish Balay       vertexA[3] *= R;
34819371c9d4SSatish Balay       vertexB[0] *= R;
34829371c9d4SSatish Balay       vertexB[1] *= R;
34839371c9d4SSatish Balay       vertexB[2] *= R;
34849371c9d4SSatish Balay       vertexB[3] *= R;
34859371c9d4SSatish Balay       vertexC[0] *= R;
34869371c9d4SSatish Balay       vertexC[1] *= R;
34879371c9d4SSatish Balay       vertexC[2] *= R;
34889371c9d4SSatish Balay       vertexC[3] *= R;
3489dd400576SPatrick Sanan       numCells    = rank == 0 ? 600 : 0;
3490dd400576SPatrick Sanan       numVerts    = rank == 0 ? 120 : 0;
3491116ded15SMatthew G. Knepley       firstVertex = numCells;
3492116ded15SMatthew G. Knepley       /* Use the 600-cell, which for a unit sphere has coordinates which are
3493116ded15SMatthew G. Knepley 
3494116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm 1,    \pm 1, \pm 1)                          16
3495116ded15SMatthew G. Knepley                (\pm 1,    0,       0,      0)  all cyclic permutations   8
3496116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm phi, \pm 1/phi, 0)  all even permutations    96
3497116ded15SMatthew G. Knepley 
3498116ded15SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
34996333ae4fSvaleriabarra          length is then given by 1/\phi = 0.61803.
3500116ded15SMatthew G. Knepley 
3501116ded15SMatthew G. Knepley          http://buzzard.pugetsound.edu/sage-practice/ch03s03.html
3502116ded15SMatthew G. Knepley          http://mathworld.wolfram.com/600-Cell.html
3503116ded15SMatthew G. Knepley       */
3504116ded15SMatthew G. Knepley       /* Construct vertices */
35059566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3506116ded15SMatthew G. Knepley       i = 0;
3507dd400576SPatrick Sanan       if (rank == 0) {
3508116ded15SMatthew G. Knepley         for (s[0] = -1; s[0] < 2; s[0] += 2) {
3509116ded15SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
3510116ded15SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
3511116ded15SMatthew G. Knepley               for (s[3] = -1; s[3] < 2; s[3] += 2) {
3512116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d];
3513116ded15SMatthew G. Knepley                 ++i;
3514116ded15SMatthew G. Knepley               }
3515116ded15SMatthew G. Knepley             }
3516116ded15SMatthew G. Knepley           }
3517116ded15SMatthew G. Knepley         }
3518116ded15SMatthew G. Knepley         for (p = 0; p < embedDim; ++p) {
3519116ded15SMatthew G. Knepley           s[1] = s[2] = s[3] = 1;
3520116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
3521116ded15SMatthew G. Knepley             for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim];
3522116ded15SMatthew G. Knepley             ++i;
3523116ded15SMatthew G. Knepley           }
3524116ded15SMatthew G. Knepley         }
3525116ded15SMatthew G. Knepley         for (p = 0; p < 12; ++p) {
3526116ded15SMatthew G. Knepley           s[3] = 1;
3527116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
3528116ded15SMatthew G. Knepley             for (s[1] = -1; s[1] < 2; s[1] += 2) {
3529116ded15SMatthew G. Knepley               for (s[2] = -1; s[2] < 2; s[2] += 2) {
3530116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]];
3531116ded15SMatthew G. Knepley                 ++i;
3532116ded15SMatthew G. Knepley               }
3533116ded15SMatthew G. Knepley             }
3534116ded15SMatthew G. Knepley           }
3535116ded15SMatthew G. Knepley         }
353645da822fSValeria Barra       }
353763a3b9bcSJacob Faibussowitsch       PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts);
3538116ded15SMatthew G. Knepley       /* Construct graph */
35399566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
3540116ded15SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
3541116ded15SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
35429371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
35439371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
35449371c9d4SSatish Balay             ++k;
35459371c9d4SSatish Balay           }
3546116ded15SMatthew G. Knepley         }
354763a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
3548116ded15SMatthew G. Knepley       }
3549116ded15SMatthew G. Knepley       /* Build Topology */
35509566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
355107c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
35529566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3553116ded15SMatthew G. Knepley       /* Cells */
3554dd400576SPatrick Sanan       if (rank == 0) {
355507c565c5SJose E. Roman         for (PetscInt i = 0, c = 0; i < numVerts; ++i) {
3556116ded15SMatthew G. Knepley           for (j = 0; j < i; ++j) {
3557116ded15SMatthew G. Knepley             for (k = 0; k < j; ++k) {
3558116ded15SMatthew G. Knepley               for (l = 0; l < k; ++l) {
35599371c9d4SSatish 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]) {
35609371c9d4SSatish Balay                   cone[0] = firstVertex + i;
35619371c9d4SSatish Balay                   cone[1] = firstVertex + j;
35629371c9d4SSatish Balay                   cone[2] = firstVertex + k;
35639371c9d4SSatish Balay                   cone[3] = firstVertex + l;
3564116ded15SMatthew G. Knepley                   /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */
3565116ded15SMatthew G. Knepley                   {
35669371c9d4SSatish Balay                     const PetscInt epsilon[4][4][4][4] = {
35679371c9d4SSatish 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}}},
3568116ded15SMatthew G. Knepley 
35699371c9d4SSatish 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}}},
3570116ded15SMatthew G. Knepley 
35719371c9d4SSatish 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}}},
3572116ded15SMatthew G. Knepley 
35739371c9d4SSatish 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}} }
35749371c9d4SSatish Balay                     };
3575116ded15SMatthew G. Knepley                     PetscReal normal[4];
3576116ded15SMatthew G. Knepley                     PetscInt  e, f, g;
3577116ded15SMatthew G. Knepley 
3578116ded15SMatthew G. Knepley                     for (d = 0; d < embedDim; ++d) {
3579116ded15SMatthew G. Knepley                       normal[d] = 0.0;
3580116ded15SMatthew G. Knepley                       for (e = 0; e < embedDim; ++e) {
3581116ded15SMatthew G. Knepley                         for (f = 0; f < embedDim; ++f) {
3582116ded15SMatthew G. Knepley                           for (g = 0; g < embedDim; ++g) {
3583116ded15SMatthew 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]);
3584116ded15SMatthew G. Knepley                           }
3585116ded15SMatthew G. Knepley                         }
3586116ded15SMatthew G. Knepley                       }
3587116ded15SMatthew G. Knepley                     }
35889371c9d4SSatish Balay                     if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
35899371c9d4SSatish Balay                       PetscInt tmp = cone[1];
35909371c9d4SSatish Balay                       cone[1]      = cone[2];
35919371c9d4SSatish Balay                       cone[2]      = tmp;
35929371c9d4SSatish Balay                     }
3593116ded15SMatthew G. Knepley                   }
35949566063dSJacob Faibussowitsch                   PetscCall(DMPlexSetCone(dm, c++, cone));
3595116ded15SMatthew G. Knepley                 }
3596116ded15SMatthew G. Knepley               }
3597116ded15SMatthew G. Knepley             }
3598116ded15SMatthew G. Knepley           }
3599116ded15SMatthew G. Knepley         }
360045da822fSValeria Barra       }
36019566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
36029566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
36039566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
3604116ded15SMatthew G. Knepley     }
3605f4d061e9SPierre Jolivet     break;
3606d71ae5a4SJacob Faibussowitsch   default:
3607d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim);
360865a81367SMatthew G. Knepley   }
360965a81367SMatthew G. Knepley   /* Create coordinates */
36109566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
36119566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
36129566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim));
36139566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts));
36142829fed8SMatthew G. Knepley   for (v = firstVertex; v < firstVertex + numVerts; ++v) {
36159566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, embedDim));
36169566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim));
36172829fed8SMatthew G. Knepley   }
36189566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
36199566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
36209566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
36219566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, embedDim));
36229566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
36239566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
36249566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
36259566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
36269371c9d4SSatish Balay   for (v = 0; v < numVerts; ++v)
3627ad540459SPierre Jolivet     for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d];
36289566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
36299566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
36309566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
36319566063dSJacob Faibussowitsch   PetscCall(PetscFree(coordsIn));
363251a74b61SMatthew G. Knepley   {
363351a74b61SMatthew G. Knepley     DM          cdm;
363451a74b61SMatthew G. Knepley     PetscDS     cds;
36359318fe57SMatthew G. Knepley     PetscScalar c = R;
363651a74b61SMatthew G. Knepley 
3637e44f6aebSMatthew G. Knepley     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, snapToSphere));
36389566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
36399566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
36409566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 1, &c));
364151a74b61SMatthew G. Knepley   }
364246139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
36439318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
36449566063dSJacob Faibussowitsch   if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
36453ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
36469318fe57SMatthew G. Knepley }
36479318fe57SMatthew G. Knepley 
3648b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]);
3649b7f5c055SJed Brown 
3650b7f5c055SJed Brown /*
3651b7f5c055SJed Brown  The Schwarz P implicit surface is
3652b7f5c055SJed Brown 
3653b7f5c055SJed Brown      f(x) = cos(x0) + cos(x1) + cos(x2) = 0
3654b7f5c055SJed Brown */
3655d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
3656d71ae5a4SJacob Faibussowitsch {
3657b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)};
3658b7f5c055SJed Brown   PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)};
3659b7f5c055SJed Brown   f[0]           = c[0] + c[1] + c[2];
3660b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
3661b7f5c055SJed Brown     grad[i] = PETSC_PI * g[i];
3662ad540459SPierre Jolivet     for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.;
3663b7f5c055SJed Brown   }
3664b7f5c055SJed Brown }
3665b7f5c055SJed Brown 
36664663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
3667d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
3668d71ae5a4SJacob Faibussowitsch {
3669ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI);
36703ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
36714663dae6SJed Brown }
36724663dae6SJed Brown 
3673b7f5c055SJed Brown /*
3674b7f5c055SJed Brown  The Gyroid implicit surface is
3675b7f5c055SJed Brown 
3676b7f5c055SJed 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)
3677b7f5c055SJed Brown 
3678b7f5c055SJed Brown */
3679d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
3680d71ae5a4SJacob Faibussowitsch {
3681b7f5c055SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))};
3682b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))};
3683b7f5c055SJed Brown   f[0]           = s[0] * c[1] + s[1] * c[2] + s[2] * c[0];
3684b7f5c055SJed Brown   grad[0]        = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
3685b7f5c055SJed Brown   grad[1]        = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
3686b7f5c055SJed Brown   grad[2]        = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
3687b7f5c055SJed Brown   hess[0][0]     = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]);
3688b7f5c055SJed Brown   hess[0][1]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
3689b7f5c055SJed Brown   hess[0][2]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
3690b7f5c055SJed Brown   hess[1][0]     = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]);
3691b7f5c055SJed Brown   hess[1][1]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
3692b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
3693b7f5c055SJed Brown   hess[2][0]     = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]);
3694b7f5c055SJed Brown   hess[2][1]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
3695b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
3696b7f5c055SJed Brown }
3697b7f5c055SJed Brown 
36984663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
3699d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
3700d71ae5a4SJacob Faibussowitsch {
37014663dae6SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))};
37024663dae6SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))};
37034663dae6SJed Brown   u[0]           = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
37044663dae6SJed Brown   u[1]           = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
37054663dae6SJed Brown   u[2]           = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
37063ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
37074663dae6SJed Brown }
37084663dae6SJed Brown 
3709b7f5c055SJed Brown /*
3710b7f5c055SJed Brown    We wish to solve
3711b7f5c055SJed Brown 
3712b7f5c055SJed Brown          min_y || y - x ||^2  subject to f(y) = 0
3713b7f5c055SJed Brown 
3714b7f5c055SJed Brown    Let g(y) = grad(f).  The minimization problem is equivalent to asking to satisfy
3715b7f5c055SJed 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
3716b7f5c055SJed Brown    tangent space and ask for both components in the tangent space to be zero.
3717b7f5c055SJed Brown 
3718b7f5c055SJed Brown    Take g to be a column vector and compute the "full QR" factorization Q R = g,
3719b7f5c055SJed Brown    where Q = I - 2 n n^T is a symmetric orthogonal matrix.
3720b7f5c055SJed Brown    The first column of Q is parallel to g so the remaining two columns span the null space.
3721b7f5c055SJed Brown    Let Qn = Q[:,1:] be those remaining columns.  Then Qn Qn^T is an orthogonal projector into the tangent space.
3722da81f932SPierre Jolivet    Since Q is symmetric, this is equivalent to multiplying by Q and taking the last two entries.
3723b7f5c055SJed Brown    In total, we have a system of 3 equations in 3 unknowns:
3724b7f5c055SJed Brown 
3725b7f5c055SJed Brown      f(y) = 0                       1 equation
3726b7f5c055SJed Brown      Qn^T (y - x) = 0               2 equations
3727b7f5c055SJed Brown 
3728b7f5c055SJed Brown    Here, we compute the residual and Jacobian of this system.
3729b7f5c055SJed Brown */
3730d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[])
3731d71ae5a4SJacob Faibussowitsch {
3732b7f5c055SJed Brown   PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])};
3733b7f5c055SJed Brown   PetscReal d[3]     = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])};
37342f0490c0SSatish Balay   PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign;
37359371c9d4SSatish Balay   PetscReal n_y[3][3] = {
37369371c9d4SSatish Balay     {0, 0, 0},
37379371c9d4SSatish Balay     {0, 0, 0},
37389371c9d4SSatish Balay     {0, 0, 0}
37399371c9d4SSatish Balay   };
3740b7f5c055SJed Brown 
3741b7f5c055SJed Brown   feval(yreal, &f, grad, n_y);
3742b7f5c055SJed Brown 
3743b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n[i] = grad[i];
3744b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
3745ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i];
3746b7f5c055SJed Brown 
3747b7f5c055SJed Brown   // Define the Householder reflector
3748b7f5c055SJed Brown   sign = n[0] >= 0 ? 1. : -1.;
3749b7f5c055SJed Brown   n[0] += norm * sign;
3750b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign;
3751b7f5c055SJed Brown 
3752b7f5c055SJed Brown   norm      = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
3753b7f5c055SJed Brown   norm_y[0] = 1. / norm * (n[0] * n_y[0][0]);
3754b7f5c055SJed Brown   norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]);
3755b7f5c055SJed Brown   norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]);
3756b7f5c055SJed Brown 
3757b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
3758b7f5c055SJed Brown     n[i] /= norm;
3759b7f5c055SJed Brown     for (PetscInt j = 0; j < 3; j++) {
3760b7f5c055SJed Brown       // note that n[i] is n_old[i]/norm when executing the code below
3761b7f5c055SJed Brown       n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j];
3762b7f5c055SJed Brown     }
3763b7f5c055SJed Brown   }
3764b7f5c055SJed Brown 
3765b7f5c055SJed Brown   nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2];
3766b7f5c055SJed 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];
3767b7f5c055SJed Brown 
3768b7f5c055SJed Brown   res[0] = f;
3769b7f5c055SJed Brown   res[1] = d[1] - 2 * n[1] * nd;
3770b7f5c055SJed Brown   res[2] = d[2] - 2 * n[2] * nd;
3771b7f5c055SJed Brown   // J[j][i] is J_{ij} (column major)
3772b7f5c055SJed Brown   for (PetscInt j = 0; j < 3; j++) {
3773b7f5c055SJed Brown     J[0 + j * 3] = grad[j];
3774b7f5c055SJed Brown     J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]);
3775b7f5c055SJed Brown     J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]);
3776b7f5c055SJed Brown   }
3777b7f5c055SJed Brown }
3778b7f5c055SJed Brown 
3779b7f5c055SJed Brown /*
3780b7f5c055SJed Brown    Project x to the nearest point on the implicit surface using Newton's method.
3781b7f5c055SJed Brown */
3782d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[])
3783d71ae5a4SJacob Faibussowitsch {
3784b7f5c055SJed Brown   PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess
3785b7f5c055SJed Brown 
3786b7f5c055SJed Brown   PetscFunctionBegin;
3787b7f5c055SJed Brown   for (PetscInt iter = 0; iter < 10; iter++) {
3788b7f5c055SJed Brown     PetscScalar res[3], J[9];
3789b7f5c055SJed Brown     PetscReal   resnorm;
3790b7f5c055SJed Brown     TPSNearestPointResJac(feval, x, y, res, J);
3791b7f5c055SJed Brown     resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2])));
3792b7f5c055SJed Brown     if (0) { // Turn on this monitor if you need to confirm quadratic convergence
379363a3b9bcSJacob 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])));
3794b7f5c055SJed Brown     }
3795b7f5c055SJed Brown     if (resnorm < PETSC_SMALL) break;
3796b7f5c055SJed Brown 
3797b7f5c055SJed Brown     // Take the Newton step
37989566063dSJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL));
3799b7f5c055SJed Brown     PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res);
3800b7f5c055SJed Brown   }
3801b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) x[i] = y[i];
38023ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3803b7f5c055SJed Brown }
3804b7f5c055SJed Brown 
3805b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL};
3806b7f5c055SJed Brown 
3807d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness)
3808d71ae5a4SJacob Faibussowitsch {
3809b7f5c055SJed Brown   PetscMPIInt rank;
3810b7f5c055SJed Brown   PetscInt    topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0;
3811b7f5c055SJed Brown   PetscInt (*edges)[2] = NULL, *edgeSets = NULL;
3812b7f5c055SJed Brown   PetscInt           *cells_flat = NULL;
3813b7f5c055SJed Brown   PetscReal          *vtxCoords  = NULL;
3814b7f5c055SJed Brown   TPSEvaluateFunc     evalFunc   = NULL;
38158434afd1SBarry Smith   PetscSimplePointFn *normalFunc = NULL;
3816b7f5c055SJed Brown   DMLabel             label;
3817b7f5c055SJed Brown 
3818b7f5c055SJed Brown   PetscFunctionBegin;
381946139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
38209566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
382163a3b9bcSJacob 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);
3822b7f5c055SJed Brown   switch (tpstype) {
3823b7f5c055SJed Brown   case DMPLEX_TPS_SCHWARZ_P:
3824b7f5c055SJed 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");
3825c5853193SPierre Jolivet     if (rank == 0) {
3826b7f5c055SJed Brown       PetscInt (*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn]
3827b7f5c055SJed Brown       PetscInt  Njunctions = 0, Ncuts = 0, Npipes[3], vcount;
3828b7f5c055SJed Brown       PetscReal L = 1;
3829b7f5c055SJed Brown 
3830b7f5c055SJed Brown       Npipes[0]   = (extent[0] + 1) * extent[1] * extent[2];
3831b7f5c055SJed Brown       Npipes[1]   = extent[0] * (extent[1] + 1) * extent[2];
3832b7f5c055SJed Brown       Npipes[2]   = extent[0] * extent[1] * (extent[2] + 1);
3833b7f5c055SJed Brown       Njunctions  = extent[0] * extent[1] * extent[2];
3834b7f5c055SJed Brown       Ncuts       = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]);
3835b7f5c055SJed Brown       numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions;
38369566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords));
38379566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Njunctions, &cells));
38389566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edges));
38399566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets));
3840b7f5c055SJed Brown       // x-normal pipes
3841b7f5c055SJed Brown       vcount = 0;
3842b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0] + 1; i++) {
3843b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3844b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3845b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3846b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * i - 1) * L;
3847b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3848b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3849b7f5c055SJed Brown             }
3850b7f5c055SJed Brown           }
3851b7f5c055SJed Brown         }
3852b7f5c055SJed Brown       }
3853b7f5c055SJed Brown       // y-normal pipes
3854b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3855b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1] + 1; j++) {
3856b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3857b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3858b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3859b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * j - 1) * L;
3860b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3861b7f5c055SJed Brown             }
3862b7f5c055SJed Brown           }
3863b7f5c055SJed Brown         }
3864b7f5c055SJed Brown       }
3865b7f5c055SJed Brown       // z-normal pipes
3866b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3867b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3868b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2] + 1; k++) {
3869b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3870b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3871b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3872b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * k - 1) * L;
3873b7f5c055SJed Brown             }
3874b7f5c055SJed Brown           }
3875b7f5c055SJed Brown         }
3876b7f5c055SJed Brown       }
3877b7f5c055SJed Brown       // junctions
3878b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3879b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3880b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3881b7f5c055SJed Brown             const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8;
3882b7f5c055SJed Brown             PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count");
3883b7f5c055SJed Brown             for (PetscInt ii = 0; ii < 2; ii++) {
3884b7f5c055SJed Brown               for (PetscInt jj = 0; jj < 2; jj++) {
3885b7f5c055SJed Brown                 for (PetscInt kk = 0; kk < 2; kk++) {
3886b7f5c055SJed Brown                   double Ls           = (1 - sqrt(2) / 4) * L;
3887b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls;
3888b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls;
3889b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls;
3890b7f5c055SJed Brown                 }
3891b7f5c055SJed Brown               }
3892b7f5c055SJed Brown             }
3893b7f5c055SJed Brown             const PetscInt jfaces[3][2][4] = {
3894b7f5c055SJed Brown               {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned
3895b7f5c055SJed Brown               {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned
3896b7f5c055SJed Brown               {{6, 2, 0, 4}, {7, 3, 1, 5}}  // z-aligned
3897b7f5c055SJed Brown             };
3898b7f5c055SJed Brown             const PetscInt pipe_lo[3] = {// vertex numbers of pipes
38999371c9d4SSatish 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};
3900b7f5c055SJed Brown             const PetscInt pipe_hi[3] = {// vertex numbers of pipes
39019371c9d4SSatish 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};
3902b7f5c055SJed Brown             for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z
3903b7f5c055SJed Brown               const PetscInt ijk[3] = {i, j, k};
3904b7f5c055SJed Brown               for (PetscInt l = 0; l < 4; l++) { // rotations
3905b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l;
3906b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l];
3907b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4];
3908b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4;
3909b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l];
3910b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l;
3911b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4;
3912b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4];
3913b7f5c055SJed Brown                 if (ijk[dir] == 0) {
3914b7f5c055SJed Brown                   edges[numEdges][0] = pipe_lo[dir] + l;
3915b7f5c055SJed Brown                   edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4;
3916b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 1;
3917b7f5c055SJed Brown                   numEdges++;
3918b7f5c055SJed Brown                 }
3919b7f5c055SJed Brown                 if (ijk[dir] + 1 == extent[dir]) {
3920b7f5c055SJed Brown                   edges[numEdges][0] = pipe_hi[dir] + l;
3921b7f5c055SJed Brown                   edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4;
3922b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 2;
3923b7f5c055SJed Brown                   numEdges++;
3924b7f5c055SJed Brown                 }
3925b7f5c055SJed Brown               }
3926b7f5c055SJed Brown             }
3927b7f5c055SJed Brown           }
3928b7f5c055SJed Brown         }
3929b7f5c055SJed Brown       }
393063a3b9bcSJacob Faibussowitsch       PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts);
3931b7f5c055SJed Brown       numFaces   = 24 * Njunctions;
3932b7f5c055SJed Brown       cells_flat = cells[0][0][0];
3933b7f5c055SJed Brown     }
3934b7f5c055SJed Brown     evalFunc   = TPSEvaluate_SchwarzP;
39354663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_SchwarzP;
3936b7f5c055SJed Brown     break;
3937b7f5c055SJed Brown   case DMPLEX_TPS_GYROID:
3938c5853193SPierre Jolivet     if (rank == 0) {
3939b7f5c055SJed Brown       // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set
3940b7f5c055SJed Brown       //
3941b7f5c055SJed 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)
3942b7f5c055SJed Brown       //
3943b7f5c055SJed Brown       // on the cell [0,2]^3.
3944b7f5c055SJed Brown       //
3945b7f5c055SJed Brown       // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2].
3946b7f5c055SJed Brown       // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins
3947b7f5c055SJed Brown       // like a boomerang:
3948b7f5c055SJed Brown       //
3949b7f5c055SJed Brown       //     z = 0          z = 1/4        z = 1/2        z = 3/4     //
3950b7f5c055SJed Brown       //     -----          -------        -------        -------     //
3951b7f5c055SJed Brown       //                                                              //
3952b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
3953b7f5c055SJed Brown       //      \                                   /            \      //
3954b7f5c055SJed Brown       //       \            `-_   _-'            /              }     //
3955b7f5c055SJed Brown       //        *-_            `-'            _-'              /      //
3956b7f5c055SJed Brown       //     +     `-+      +       +      +-'     +      +   /   +   //
3957b7f5c055SJed Brown       //                                                              //
3958b7f5c055SJed Brown       //                                                              //
3959b7f5c055SJed Brown       //     z = 1          z = 5/4        z = 3/2        z = 7/4     //
3960b7f5c055SJed Brown       //     -----          -------        -------        -------     //
3961b7f5c055SJed Brown       //                                                              //
3962b7f5c055SJed Brown       //     +-_     +      +       +      +     _-+      +   /   +   //
3963b7f5c055SJed Brown       //        `-_            _-_            _-`            /        //
3964b7f5c055SJed Brown       //           \        _-'   `-_        /              {         //
3965b7f5c055SJed Brown       //            \                       /                \        //
3966b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
3967b7f5c055SJed Brown       //
3968b7f5c055SJed Brown       //
3969b7f5c055SJed Brown       // This course mesh approximates each of these slices by two line segments,
3970b7f5c055SJed Brown       // and then connects the segments in consecutive layers with quadrilateral faces.
3971b7f5c055SJed Brown       // All of the end points of the segments are multiples of 1/4 except for the
3972b7f5c055SJed Brown       // point * in the picture for z = 0 above and the similar points in other layers.
3973b7f5c055SJed Brown       // That point is at (gamma, gamma, 0), where gamma is calculated below.
3974b7f5c055SJed Brown       //
3975b7f5c055SJed Brown       // The column  [1,2]x[1,2]x[0,2] looks the same as this column;
3976b7f5c055SJed Brown       // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images.
3977b7f5c055SJed Brown       //
3978b7f5c055SJed Brown       // As for how this method turned into the names given to the vertices:
3979b7f5c055SJed Brown       // that was not systematic, it was just the way it worked out in my handwritten notes.
3980b7f5c055SJed Brown 
3981b7f5c055SJed Brown       PetscInt facesPerBlock = 64;
3982b7f5c055SJed Brown       PetscInt vertsPerBlock = 56;
3983b7f5c055SJed Brown       PetscInt extentPlus[3];
3984b7f5c055SJed Brown       PetscInt numBlocks, numBlocksPlus;
39859371c9d4SSatish 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;
39869371c9d4SSatish Balay       const PetscInt pattern[64][4] = {
39879371c9d4SSatish Balay         /* face to vertex within the coarse discretization of a single gyroid block */
3988b7f5c055SJed Brown         /* layer 0 */
39899371c9d4SSatish Balay         {A,           C,           K,           G          },
39909371c9d4SSatish Balay         {C,           B,           II,          K          },
39919371c9d4SSatish Balay         {D,           A,           H,           L          },
39929371c9d4SSatish Balay         {B + 56 * 1,  D,           L,           J          },
39939371c9d4SSatish Balay         {E,           B + 56 * 1,  J,           N          },
39949371c9d4SSatish Balay         {A + 56 * 2,  E,           N,           H + 56 * 2 },
39959371c9d4SSatish Balay         {F,           A + 56 * 2,  G + 56 * 2,  M          },
39969371c9d4SSatish Balay         {B,           F,           M,           II         },
3997b7f5c055SJed Brown         /* layer 1 */
39989371c9d4SSatish Balay         {G,           K,           Q,           O          },
39999371c9d4SSatish Balay         {K,           II,          P,           Q          },
40009371c9d4SSatish Balay         {L,           H,           O + 56 * 1,  R          },
40019371c9d4SSatish Balay         {J,           L,           R,           P          },
40029371c9d4SSatish Balay         {N,           J,           P,           S          },
40039371c9d4SSatish Balay         {H + 56 * 2,  N,           S,           O + 56 * 3 },
40049371c9d4SSatish Balay         {M,           G + 56 * 2,  O + 56 * 2,  T          },
40059371c9d4SSatish Balay         {II,          M,           T,           P          },
4006b7f5c055SJed Brown         /* layer 2 */
40079371c9d4SSatish Balay         {O,           Q,           Y,           U          },
40089371c9d4SSatish Balay         {Q,           P,           W,           Y          },
40099371c9d4SSatish Balay         {R,           O + 56 * 1,  U + 56 * 1,  Ap         },
40109371c9d4SSatish Balay         {P,           R,           Ap,          W          },
40119371c9d4SSatish Balay         {S,           P,           X,           Bp         },
40129371c9d4SSatish Balay         {O + 56 * 3,  S,           Bp,          V + 56 * 1 },
40139371c9d4SSatish Balay         {T,           O + 56 * 2,  V,           Z          },
40149371c9d4SSatish Balay         {P,           T,           Z,           X          },
4015b7f5c055SJed Brown         /* layer 3 */
40169371c9d4SSatish Balay         {U,           Y,           Ep,          Dp         },
40179371c9d4SSatish Balay         {Y,           W,           Cp,          Ep         },
40189371c9d4SSatish Balay         {Ap,          U + 56 * 1,  Dp + 56 * 1, Gp         },
40199371c9d4SSatish Balay         {W,           Ap,          Gp,          Cp         },
40209371c9d4SSatish Balay         {Bp,          X,           Cp + 56 * 2, Fp         },
40219371c9d4SSatish Balay         {V + 56 * 1,  Bp,          Fp,          Dp + 56 * 1},
40229371c9d4SSatish Balay         {Z,           V,           Dp,          Hp         },
40239371c9d4SSatish Balay         {X,           Z,           Hp,          Cp + 56 * 2},
4024b7f5c055SJed Brown         /* layer 4 */
40259371c9d4SSatish Balay         {Dp,          Ep,          Mp,          Kp         },
40269371c9d4SSatish Balay         {Ep,          Cp,          Ip,          Mp         },
40279371c9d4SSatish Balay         {Gp,          Dp + 56 * 1, Lp,          Np         },
40289371c9d4SSatish Balay         {Cp,          Gp,          Np,          Jp         },
40299371c9d4SSatish Balay         {Fp,          Cp + 56 * 2, Jp + 56 * 2, Pp         },
40309371c9d4SSatish Balay         {Dp + 56 * 1, Fp,          Pp,          Lp         },
40319371c9d4SSatish Balay         {Hp,          Dp,          Kp,          Op         },
40329371c9d4SSatish Balay         {Cp + 56 * 2, Hp,          Op,          Ip + 56 * 2},
4033b7f5c055SJed Brown         /* layer 5 */
40349371c9d4SSatish Balay         {Kp,          Mp,          Sp,          Rp         },
40359371c9d4SSatish Balay         {Mp,          Ip,          Qp,          Sp         },
40369371c9d4SSatish Balay         {Np,          Lp,          Rp,          Tp         },
40379371c9d4SSatish Balay         {Jp,          Np,          Tp,          Qp + 56 * 1},
40389371c9d4SSatish Balay         {Pp,          Jp + 56 * 2, Qp + 56 * 3, Up         },
40399371c9d4SSatish Balay         {Lp,          Pp,          Up,          Rp         },
40409371c9d4SSatish Balay         {Op,          Kp,          Rp,          Vp         },
40419371c9d4SSatish Balay         {Ip + 56 * 2, Op,          Vp,          Qp + 56 * 2},
4042b7f5c055SJed Brown         /* layer 6 */
40439371c9d4SSatish Balay         {Rp,          Sp,          Aq,          Yp         },
40449371c9d4SSatish Balay         {Sp,          Qp,          Wp,          Aq         },
40459371c9d4SSatish Balay         {Tp,          Rp,          Yp,          Cq         },
40469371c9d4SSatish Balay         {Qp + 56 * 1, Tp,          Cq,          Wp + 56 * 1},
40479371c9d4SSatish Balay         {Up,          Qp + 56 * 3, Xp + 56 * 1, Dq         },
40489371c9d4SSatish Balay         {Rp,          Up,          Dq,          Zp         },
40499371c9d4SSatish Balay         {Vp,          Rp,          Zp,          Bq         },
40509371c9d4SSatish Balay         {Qp + 56 * 2, Vp,          Bq,          Xp         },
4051b7f5c055SJed Brown         /* layer 7 (the top is the periodic image of the bottom of layer 0) */
40529371c9d4SSatish Balay         {Yp,          Aq,          C + 56 * 4,  A + 56 * 4 },
40539371c9d4SSatish Balay         {Aq,          Wp,          B + 56 * 4,  C + 56 * 4 },
40549371c9d4SSatish Balay         {Cq,          Yp,          A + 56 * 4,  D + 56 * 4 },
40559371c9d4SSatish Balay         {Wp + 56 * 1, Cq,          D + 56 * 4,  B + 56 * 5 },
40569371c9d4SSatish Balay         {Dq,          Xp + 56 * 1, B + 56 * 5,  E + 56 * 4 },
40579371c9d4SSatish Balay         {Zp,          Dq,          E + 56 * 4,  A + 56 * 6 },
40589371c9d4SSatish Balay         {Bq,          Zp,          A + 56 * 6,  F + 56 * 4 },
40599371c9d4SSatish Balay         {Xp,          Bq,          F + 56 * 4,  B + 56 * 4 }
4060b7f5c055SJed Brown       };
4061b7f5c055SJed Brown       const PetscReal gamma                = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI;
40629371c9d4SSatish Balay       const PetscReal patternCoords[56][3] = {
4063bee3fc89SBarry Smith         {1.,        0.,        0.  }, /* A  */
4064bee3fc89SBarry Smith         {0.,        1.,        0.  }, /* B  */
4065bee3fc89SBarry Smith         {gamma,     gamma,     0.  }, /* C  */
4066bee3fc89SBarry Smith         {1 + gamma, 1 - gamma, 0.  }, /* D  */
4067bee3fc89SBarry Smith         {2 - gamma, 2 - gamma, 0.  }, /* E  */
4068bee3fc89SBarry Smith         {1 - gamma, 1 + gamma, 0.  }, /* F  */
4069b7f5c055SJed Brown 
4070bee3fc89SBarry Smith         {.5,        0,         .25 }, /* G  */
4071bee3fc89SBarry Smith         {1.5,       0.,        .25 }, /* H  */
4072bee3fc89SBarry Smith         {.5,        1.,        .25 }, /* II */
4073bee3fc89SBarry Smith         {1.5,       1.,        .25 }, /* J  */
4074bee3fc89SBarry Smith         {.25,       .5,        .25 }, /* K  */
4075bee3fc89SBarry Smith         {1.25,      .5,        .25 }, /* L  */
4076bee3fc89SBarry Smith         {.75,       1.5,       .25 }, /* M  */
4077bee3fc89SBarry Smith         {1.75,      1.5,       .25 }, /* N  */
4078b7f5c055SJed Brown 
4079bee3fc89SBarry Smith         {0.,        0.,        .5  }, /* O  */
4080bee3fc89SBarry Smith         {1.,        1.,        .5  }, /* P  */
4081bee3fc89SBarry Smith         {gamma,     1 - gamma, .5  }, /* Q  */
4082bee3fc89SBarry Smith         {1 + gamma, gamma,     .5  }, /* R  */
4083bee3fc89SBarry Smith         {2 - gamma, 1 + gamma, .5  }, /* S  */
4084bee3fc89SBarry Smith         {1 - gamma, 2 - gamma, .5  }, /* T  */
4085b7f5c055SJed Brown 
4086bee3fc89SBarry Smith         {0.,        .5,        .75 }, /* U  */
4087bee3fc89SBarry Smith         {0.,        1.5,       .75 }, /* V  */
4088bee3fc89SBarry Smith         {1.,        .5,        .75 }, /* W  */
4089bee3fc89SBarry Smith         {1.,        1.5,       .75 }, /* X  */
4090bee3fc89SBarry Smith         {.5,        .75,       .75 }, /* Y  */
4091bee3fc89SBarry Smith         {.5,        1.75,      .75 }, /* Z  */
4092bee3fc89SBarry Smith         {1.5,       .25,       .75 }, /* Ap */
4093bee3fc89SBarry Smith         {1.5,       1.25,      .75 }, /* Bp */
4094b7f5c055SJed Brown 
4095bee3fc89SBarry Smith         {1.,        0.,        1.  }, /* Cp */
4096bee3fc89SBarry Smith         {0.,        1.,        1.  }, /* Dp */
4097bee3fc89SBarry Smith         {1 - gamma, 1 - gamma, 1.  }, /* Ep */
4098bee3fc89SBarry Smith         {1 + gamma, 1 + gamma, 1.  }, /* Fp */
4099bee3fc89SBarry Smith         {2 - gamma, gamma,     1.  }, /* Gp */
4100bee3fc89SBarry Smith         {gamma,     2 - gamma, 1.  }, /* Hp */
4101b7f5c055SJed Brown 
4102bee3fc89SBarry Smith         {.5,        0.,        1.25}, /* Ip */
4103bee3fc89SBarry Smith         {1.5,       0.,        1.25}, /* Jp */
4104bee3fc89SBarry Smith         {.5,        1.,        1.25}, /* Kp */
4105bee3fc89SBarry Smith         {1.5,       1.,        1.25}, /* Lp */
4106bee3fc89SBarry Smith         {.75,       .5,        1.25}, /* Mp */
4107bee3fc89SBarry Smith         {1.75,      .5,        1.25}, /* Np */
4108bee3fc89SBarry Smith         {.25,       1.5,       1.25}, /* Op */
4109bee3fc89SBarry Smith         {1.25,      1.5,       1.25}, /* Pp */
4110b7f5c055SJed Brown 
4111bee3fc89SBarry Smith         {0.,        0.,        1.5 }, /* Qp */
4112bee3fc89SBarry Smith         {1.,        1.,        1.5 }, /* Rp */
4113bee3fc89SBarry Smith         {1 - gamma, gamma,     1.5 }, /* Sp */
4114bee3fc89SBarry Smith         {2 - gamma, 1 - gamma, 1.5 }, /* Tp */
4115bee3fc89SBarry Smith         {1 + gamma, 2 - gamma, 1.5 }, /* Up */
4116bee3fc89SBarry Smith         {gamma,     1 + gamma, 1.5 }, /* Vp */
4117b7f5c055SJed Brown 
4118bee3fc89SBarry Smith         {0.,        .5,        1.75}, /* Wp */
4119bee3fc89SBarry Smith         {0.,        1.5,       1.75}, /* Xp */
4120bee3fc89SBarry Smith         {1.,        .5,        1.75}, /* Yp */
4121bee3fc89SBarry Smith         {1.,        1.5,       1.75}, /* Zp */
4122bee3fc89SBarry Smith         {.5,        .25,       1.75}, /* Aq */
4123bee3fc89SBarry Smith         {.5,        1.25,      1.75}, /* Bq */
4124bee3fc89SBarry Smith         {1.5,       .75,       1.75}, /* Cq */
4125bee3fc89SBarry Smith         {1.5,       1.75,      1.75}, /* Dq */
4126b7f5c055SJed Brown       };
4127b7f5c055SJed Brown       PetscInt (*cells)[64][4] = NULL;
4128b7f5c055SJed Brown       PetscBool *seen;
4129b7f5c055SJed Brown       PetscInt  *vertToTrueVert;
4130b7f5c055SJed Brown       PetscInt   count;
4131b7f5c055SJed Brown 
4132b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1;
4133b7f5c055SJed Brown       numBlocks = 1;
4134b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i];
4135b7f5c055SJed Brown       numBlocksPlus = 1;
4136b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i];
4137b7f5c055SJed Brown       numFaces = numBlocks * facesPerBlock;
41389566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocks, &cells));
41399566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen));
4140b7f5c055SJed Brown       for (PetscInt k = 0; k < extent[2]; k++) {
4141b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
4142b7f5c055SJed Brown           for (PetscInt i = 0; i < extent[0]; i++) {
4143b7f5c055SJed Brown             for (PetscInt f = 0; f < facesPerBlock; f++) {
4144b7f5c055SJed Brown               for (PetscInt v = 0; v < 4; v++) {
4145b7f5c055SJed Brown                 PetscInt vertRaw     = pattern[f][v];
4146b7f5c055SJed Brown                 PetscInt blockidx    = vertRaw / 56;
4147b7f5c055SJed Brown                 PetscInt patternvert = vertRaw % 56;
4148b7f5c055SJed Brown                 PetscInt xplus       = (blockidx & 1);
4149b7f5c055SJed Brown                 PetscInt yplus       = (blockidx & 2) >> 1;
4150b7f5c055SJed Brown                 PetscInt zplus       = (blockidx & 4) >> 2;
4151b7f5c055SJed Brown                 PetscInt zcoord      = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus);
4152b7f5c055SJed Brown                 PetscInt ycoord      = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus);
4153b7f5c055SJed Brown                 PetscInt xcoord      = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus);
4154b7f5c055SJed Brown                 PetscInt vert        = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert;
4155b7f5c055SJed Brown 
4156b7f5c055SJed Brown                 cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert;
4157b7f5c055SJed Brown                 seen[vert]                                       = PETSC_TRUE;
4158b7f5c055SJed Brown               }
4159b7f5c055SJed Brown             }
4160b7f5c055SJed Brown           }
4161b7f5c055SJed Brown         }
4162b7f5c055SJed Brown       }
41639371c9d4SSatish Balay       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++)
41649371c9d4SSatish Balay         if (seen[i]) numVertices++;
4165b7f5c055SJed Brown       count = 0;
41669566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert));
41679566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords));
4168b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1;
4169b7f5c055SJed Brown       for (PetscInt k = 0; k < extentPlus[2]; k++) {
4170b7f5c055SJed Brown         for (PetscInt j = 0; j < extentPlus[1]; j++) {
4171b7f5c055SJed Brown           for (PetscInt i = 0; i < extentPlus[0]; i++) {
4172b7f5c055SJed Brown             for (PetscInt v = 0; v < vertsPerBlock; v++) {
4173b7f5c055SJed Brown               PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v;
4174b7f5c055SJed Brown 
4175b7f5c055SJed Brown               if (seen[vIdx]) {
4176b7f5c055SJed Brown                 PetscInt thisVert;
4177b7f5c055SJed Brown 
4178b7f5c055SJed Brown                 vertToTrueVert[vIdx] = thisVert = count++;
4179b7f5c055SJed Brown 
4180b7f5c055SJed Brown                 for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d];
4181b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 0] += i * 2;
4182b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 1] += j * 2;
4183b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 2] += k * 2;
4184b7f5c055SJed Brown               }
4185b7f5c055SJed Brown             }
4186b7f5c055SJed Brown           }
4187b7f5c055SJed Brown         }
4188b7f5c055SJed Brown       }
4189b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocks; i++) {
4190b7f5c055SJed Brown         for (PetscInt f = 0; f < facesPerBlock; f++) {
4191ad540459SPierre Jolivet           for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]];
4192b7f5c055SJed Brown         }
4193b7f5c055SJed Brown       }
41949566063dSJacob Faibussowitsch       PetscCall(PetscFree(vertToTrueVert));
41959566063dSJacob Faibussowitsch       PetscCall(PetscFree(seen));
4196b7f5c055SJed Brown       cells_flat = cells[0][0];
4197b7f5c055SJed Brown       numEdges   = 0;
4198b7f5c055SJed Brown       for (PetscInt i = 0; i < numFaces; i++) {
4199b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
4200b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
4201b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
4202b7f5c055SJed Brown 
4203b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
4204b7f5c055SJed Brown             if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) {
4205b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++;
4206b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++;
4207b7f5c055SJed Brown             }
4208b7f5c055SJed Brown           }
4209b7f5c055SJed Brown         }
4210b7f5c055SJed Brown       }
42119566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edges));
42129566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edgeSets));
4213b7f5c055SJed Brown       for (PetscInt edge = 0, i = 0; i < numFaces; i++) {
4214b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
4215b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
4216b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
4217b7f5c055SJed Brown 
4218b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
4219b7f5c055SJed Brown             if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) {
4220b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) {
4221b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
4222b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
4223b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d;
4224b7f5c055SJed Brown               }
4225b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) {
4226b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
4227b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
4228b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d + 1;
4229b7f5c055SJed Brown               }
4230b7f5c055SJed Brown             }
4231b7f5c055SJed Brown           }
4232b7f5c055SJed Brown         }
4233b7f5c055SJed Brown       }
4234b7f5c055SJed Brown     }
4235b7f5c055SJed Brown     evalFunc   = TPSEvaluate_Gyroid;
42364663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_Gyroid;
4237b7f5c055SJed Brown     break;
4238b7f5c055SJed Brown   }
4239b7f5c055SJed Brown 
42409566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, topoDim));
4241c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat));
42429566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL));
42439566063dSJacob Faibussowitsch   PetscCall(PetscFree(cells_flat));
4244b7f5c055SJed Brown   {
4245b7f5c055SJed Brown     DM idm;
42469566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
424769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &idm));
4248b7f5c055SJed Brown   }
4249c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords));
42509566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL));
42519566063dSJacob Faibussowitsch   PetscCall(PetscFree(vtxCoords));
4252b7f5c055SJed Brown 
42539566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
42549566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
4255b7f5c055SJed Brown   for (PetscInt e = 0; e < numEdges; e++) {
4256b7f5c055SJed Brown     PetscInt        njoin;
4257b7f5c055SJed Brown     const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]};
42589566063dSJacob Faibussowitsch     PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join));
425963a3b9bcSJacob 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]);
42609566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(label, join[0], edgeSets[e]));
42619566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join));
4262b7f5c055SJed Brown   }
42639566063dSJacob Faibussowitsch   PetscCall(PetscFree(edges));
42649566063dSJacob Faibussowitsch   PetscCall(PetscFree(edgeSets));
42651436d7faSJed Brown   if (tps_distribute) {
42661436d7faSJed Brown     DM               pdm = NULL;
42671436d7faSJed Brown     PetscPartitioner part;
42681436d7faSJed Brown 
42699566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
42709566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
42719566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm));
427248a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
42731436d7faSJed Brown     // Do not auto-distribute again
42749566063dSJacob Faibussowitsch     PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
42751436d7faSJed Brown   }
4276b7f5c055SJed Brown 
42779566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
4278b7f5c055SJed Brown   for (PetscInt refine = 0; refine < refinements; refine++) {
4279b7f5c055SJed Brown     PetscInt     m;
4280b7f5c055SJed Brown     DM           dmf;
4281b7f5c055SJed Brown     Vec          X;
4282b7f5c055SJed Brown     PetscScalar *x;
42839566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf));
428469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmf));
4285b7f5c055SJed Brown 
42869566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &X));
42879566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(X, &m));
42889566063dSJacob Faibussowitsch     PetscCall(VecGetArray(X, &x));
428948a46eb9SPierre Jolivet     for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i]));
42909566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(X, &x));
4291b7f5c055SJed Brown   }
4292b7f5c055SJed Brown 
4293b7f5c055SJed Brown   // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices.
42949566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
42959566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, label));
4296b7f5c055SJed Brown 
429746139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
429846139095SJed Brown 
4299b7f5c055SJed Brown   if (thickness > 0) {
43004663dae6SJed Brown     DM              edm, cdm, ecdm;
43014663dae6SJed Brown     DMPlexTransform tr;
43024663dae6SJed Brown     const char     *prefix;
43034663dae6SJed Brown     PetscOptions    options;
43044663dae6SJed Brown     // Code from DMPlexExtrude
43054663dae6SJed Brown     PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr));
43064663dae6SJed Brown     PetscCall(DMPlexTransformSetDM(tr, dm));
4307ce78bad3SBarry Smith     PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDETYPE));
43084663dae6SJed Brown     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
43094663dae6SJed Brown     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix));
43104663dae6SJed Brown     PetscCall(PetscObjectGetOptions((PetscObject)dm, &options));
43114663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, options));
43124663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers));
43134663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness));
43144663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE));
43154663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE));
43164663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc));
43174663dae6SJed Brown     PetscCall(DMPlexTransformSetFromOptions(tr));
43184663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL));
43194663dae6SJed Brown     PetscCall(DMPlexTransformSetUp(tr));
43204663dae6SJed Brown     PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view"));
43214663dae6SJed Brown     PetscCall(DMPlexTransformApply(tr, dm, &edm));
43224663dae6SJed Brown     PetscCall(DMCopyDisc(dm, edm));
43234663dae6SJed Brown     PetscCall(DMGetCoordinateDM(dm, &cdm));
43244663dae6SJed Brown     PetscCall(DMGetCoordinateDM(edm, &ecdm));
43254663dae6SJed Brown     PetscCall(DMCopyDisc(cdm, ecdm));
43264663dae6SJed Brown     PetscCall(DMPlexTransformCreateDiscLabels(tr, edm));
43274663dae6SJed Brown     PetscCall(DMPlexTransformDestroy(&tr));
4328a77a5016SMatthew G. Knepley     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, edm));
432969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
4330b7f5c055SJed Brown   }
43313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4332b7f5c055SJed Brown }
4333b7f5c055SJed Brown 
4334b7f5c055SJed Brown /*@
4335b7f5c055SJed Brown   DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface
4336b7f5c055SJed Brown 
4337b7f5c055SJed Brown   Collective
4338b7f5c055SJed Brown 
4339b7f5c055SJed Brown   Input Parameters:
4340a1cb98faSBarry Smith + comm           - The communicator for the `DM` object
4341b7f5c055SJed Brown . tpstype        - Type of triply-periodic surface
4342b7f5c055SJed Brown . extent         - Array of length 3 containing number of periods in each direction
434320f4b53cSBarry Smith . periodic       - array of length 3 with periodicity, or `NULL` for non-periodic
43441436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable)
4345817da375SSatish Balay . refinements    - Number of factor-of-2 refinements of 2D manifold mesh
43461436d7faSJed Brown . layers         - Number of cell layers extruded in normal direction
4347817da375SSatish Balay - thickness      - Thickness in normal direction
4348b7f5c055SJed Brown 
4349b7f5c055SJed Brown   Output Parameter:
4350a1cb98faSBarry Smith . dm - The `DM` object
4351a1cb98faSBarry Smith 
4352a1cb98faSBarry Smith   Level: beginner
4353b7f5c055SJed Brown 
4354b7f5c055SJed Brown   Notes:
435515229ffcSPierre Jolivet   This meshes the surface of the Schwarz P or Gyroid surfaces.  Schwarz P is the simplest member of the triply-periodic minimal surfaces.
43561d27aa22SBarry Smith   <https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22)> and can be cut with "clean" boundaries.
43571d27aa22SBarry 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.
4358b7f5c055SJed Brown   Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested.
4359b7f5c055SJed Brown   On each refinement, all vertices are projected to their nearest point on the surface.
4360b7f5c055SJed Brown   This projection could readily be extended to related surfaces.
4361b7f5c055SJed Brown 
43621d27aa22SBarry Smith   See {cite}`maskery2018insights`
43631d27aa22SBarry Smith 
43641d27aa22SBarry Smith   The face (edge) sets for the Schwarz P surface are numbered $1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z)$.
43651d27aa22SBarry Smith   When the mesh is refined, "Face Sets" contain the new vertices (created during refinement).
43661d27aa22SBarry Smith   Use `DMPlexLabelComplete()` to propagate to coarse-level vertices.
4367b7f5c055SJed Brown 
436860225df5SJacob Faibussowitsch   Developer Notes:
4369b7f5c055SJed Brown   The Gyroid mesh does not currently mark boundary sets.
4370b7f5c055SJed Brown 
43711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()`
4372b7f5c055SJed Brown @*/
4373d71ae5a4SJacob 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)
4374d71ae5a4SJacob Faibussowitsch {
4375b7f5c055SJed Brown   PetscFunctionBegin;
43769566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
43779566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
43789566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness));
43793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4380b7f5c055SJed Brown }
4381b7f5c055SJed Brown 
43829318fe57SMatthew G. Knepley /*@
43839318fe57SMatthew G. Knepley   DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d.
43849318fe57SMatthew G. Knepley 
43859318fe57SMatthew G. Knepley   Collective
43869318fe57SMatthew G. Knepley 
43879318fe57SMatthew G. Knepley   Input Parameters:
4388a1cb98faSBarry Smith + comm    - The communicator for the `DM` object
43899318fe57SMatthew G. Knepley . dim     - The dimension
43909318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells
43919318fe57SMatthew G. Knepley - R       - The radius
43929318fe57SMatthew G. Knepley 
43939318fe57SMatthew G. Knepley   Output Parameter:
4394a1cb98faSBarry Smith . dm - The `DM` object
43959318fe57SMatthew G. Knepley 
43969318fe57SMatthew G. Knepley   Level: beginner
43979318fe57SMatthew G. Knepley 
43981cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
43999318fe57SMatthew G. Knepley @*/
4400d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm)
4401d71ae5a4SJacob Faibussowitsch {
44029318fe57SMatthew G. Knepley   PetscFunctionBegin;
44034f572ea9SToby Isaac   PetscAssertPointer(dm, 5);
44049566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
44059566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
44069566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R));
44073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44089318fe57SMatthew G. Knepley }
44099318fe57SMatthew G. Knepley 
4410d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R)
4411d71ae5a4SJacob Faibussowitsch {
44129318fe57SMatthew G. Knepley   DM          sdm, vol;
44139318fe57SMatthew G. Knepley   DMLabel     bdlabel;
4414dd2b43ebSStefano Zampini   const char *prefix;
44159318fe57SMatthew G. Knepley 
44169318fe57SMatthew G. Knepley   PetscFunctionBegin;
44179566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm));
44189566063dSJacob Faibussowitsch   PetscCall(DMSetType(sdm, DMPLEX));
4419dd2b43ebSStefano Zampini   PetscCall(DMGetOptionsPrefix(dm, &prefix));
4420dd2b43ebSStefano Zampini   PetscCall(DMSetOptionsPrefix(sdm, prefix));
4421dd2b43ebSStefano Zampini   PetscCall(DMAppendOptionsPrefix(sdm, "bd_"));
4422dd2b43ebSStefano Zampini   PetscCall(DMPlexDistributeSetDefault(sdm, PETSC_FALSE));
44239566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R));
44249566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(sdm));
44259566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view"));
44269566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol));
44279566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&sdm));
442869d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
44299566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
44309566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
44319566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
44329566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, bdlabel));
44333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
443451a74b61SMatthew G. Knepley }
443551a74b61SMatthew G. Knepley 
443651a74b61SMatthew G. Knepley /*@
443751a74b61SMatthew G. Knepley   DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d.
443851a74b61SMatthew G. Knepley 
443951a74b61SMatthew G. Knepley   Collective
444051a74b61SMatthew G. Knepley 
444151a74b61SMatthew G. Knepley   Input Parameters:
4442a1cb98faSBarry Smith + comm - The communicator for the `DM` object
444351a74b61SMatthew G. Knepley . dim  - The dimension
444451a74b61SMatthew G. Knepley - R    - The radius
444551a74b61SMatthew G. Knepley 
444651a74b61SMatthew G. Knepley   Output Parameter:
4447a1cb98faSBarry Smith . dm - The `DM` object
444851a74b61SMatthew G. Knepley 
4449a1cb98faSBarry Smith   Options Database Key:
445060225df5SJacob Faibussowitsch . bd_dm_refine - This will refine the surface mesh preserving the sphere geometry
445151a74b61SMatthew G. Knepley 
445251a74b61SMatthew G. Knepley   Level: beginner
445351a74b61SMatthew G. Knepley 
44541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
445551a74b61SMatthew G. Knepley @*/
4456d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm)
4457d71ae5a4SJacob Faibussowitsch {
445851a74b61SMatthew G. Knepley   PetscFunctionBegin;
44599566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
44609566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
44619566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R));
44623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44632829fed8SMatthew G. Knepley }
44642829fed8SMatthew G. Knepley 
4465d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct)
4466d71ae5a4SJacob Faibussowitsch {
44670a6ba040SMatthew G. Knepley   PetscFunctionBegin;
44689318fe57SMatthew G. Knepley   switch (ct) {
44699371c9d4SSatish Balay   case DM_POLYTOPE_POINT: {
44709318fe57SMatthew G. Knepley     PetscInt    numPoints[1]        = {1};
44719318fe57SMatthew G. Knepley     PetscInt    coneSize[1]         = {0};
44729318fe57SMatthew G. Knepley     PetscInt    cones[1]            = {0};
44739318fe57SMatthew G. Knepley     PetscInt    coneOrientations[1] = {0};
44749318fe57SMatthew G. Knepley     PetscScalar vertexCoords[1]     = {0.0};
44759318fe57SMatthew G. Knepley 
44769566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 0));
44779566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords));
44789371c9d4SSatish Balay   } break;
44799371c9d4SSatish Balay   case DM_POLYTOPE_SEGMENT: {
44809318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
44819318fe57SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
44829318fe57SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
44839318fe57SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
44849318fe57SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
44859318fe57SMatthew G. Knepley 
44869566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
44879566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
44889371c9d4SSatish Balay   } break;
44899371c9d4SSatish Balay   case DM_POLYTOPE_POINT_PRISM_TENSOR: {
4490b5a892a1SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
4491b5a892a1SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
4492b5a892a1SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
4493b5a892a1SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
4494b5a892a1SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
4495b5a892a1SMatthew G. Knepley 
44969566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
44979566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
44989371c9d4SSatish Balay   } break;
44999371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
45009318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {3, 1};
45019318fe57SMatthew G. Knepley     PetscInt    coneSize[4]         = {3, 0, 0, 0};
45029318fe57SMatthew G. Knepley     PetscInt    cones[3]            = {1, 2, 3};
45039318fe57SMatthew G. Knepley     PetscInt    coneOrientations[3] = {0, 0, 0};
45049318fe57SMatthew G. Knepley     PetscScalar vertexCoords[6]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0};
45059318fe57SMatthew G. Knepley 
45069566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
45079566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45089371c9d4SSatish Balay   } break;
45099371c9d4SSatish Balay   case DM_POLYTOPE_QUADRILATERAL: {
45109318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
45119318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
45129318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
45139318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
45149318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0};
45159318fe57SMatthew G. Knepley 
45169566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
45179566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45189371c9d4SSatish Balay   } break;
45199371c9d4SSatish Balay   case DM_POLYTOPE_SEG_PRISM_TENSOR: {
45209318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
45219318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
45229318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
45239318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
45249318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0};
45259318fe57SMatthew G. Knepley 
45269566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
45279566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45289371c9d4SSatish Balay   } break;
45299371c9d4SSatish Balay   case DM_POLYTOPE_TETRAHEDRON: {
45309318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
45319318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
4532f0edb160SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
45339318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
4534f0edb160SMatthew 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};
45359318fe57SMatthew G. Knepley 
45369566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
45379566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45389371c9d4SSatish Balay   } break;
45399371c9d4SSatish Balay   case DM_POLYTOPE_HEXAHEDRON: {
45409318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
45419318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
4542f0edb160SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
45439318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
45449371c9d4SSatish 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};
45459318fe57SMatthew G. Knepley 
45469566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
45479566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45489371c9d4SSatish Balay   } break;
45499371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM: {
45509318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
45519318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
4552f0edb160SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
45539318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
45549371c9d4SSatish 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};
45559318fe57SMatthew G. Knepley 
45569566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
45579566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45589371c9d4SSatish Balay   } break;
45599371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM_TENSOR: {
45609318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
45619318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
45629318fe57SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
45639318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
45649371c9d4SSatish 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};
45659318fe57SMatthew G. Knepley 
45669566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
45679566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45689371c9d4SSatish Balay   } break;
45699371c9d4SSatish Balay   case DM_POLYTOPE_QUAD_PRISM_TENSOR: {
45709318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
45719318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
45729318fe57SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
45739318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
45749371c9d4SSatish 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};
45759318fe57SMatthew G. Knepley 
45769566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
45779566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45789371c9d4SSatish Balay   } break;
45799371c9d4SSatish Balay   case DM_POLYTOPE_PYRAMID: {
45809318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {5, 1};
45819318fe57SMatthew G. Knepley     PetscInt    coneSize[6]         = {5, 0, 0, 0, 0, 0};
4582f0edb160SMatthew G. Knepley     PetscInt    cones[5]            = {1, 2, 3, 4, 5};
45839318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
45849371c9d4SSatish 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};
45859318fe57SMatthew G. Knepley 
45869566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
45879566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
45889371c9d4SSatish Balay   } break;
4589d71ae5a4SJacob Faibussowitsch   default:
4590d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]);
45919318fe57SMatthew G. Knepley   }
45929318fe57SMatthew G. Knepley   {
45939318fe57SMatthew G. Knepley     PetscInt Nv, v;
45949318fe57SMatthew G. Knepley 
45959318fe57SMatthew G. Knepley     /* Must create the celltype label here so that we do not automatically try to compute the types */
45969566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(rdm, "celltype"));
45979566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(rdm, 0, ct));
45989566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(rdm, NULL, &Nv));
45999566063dSJacob Faibussowitsch     for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT));
46009318fe57SMatthew G. Knepley   }
46019566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(rdm));
46029566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct]));
46033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46040a6ba040SMatthew G. Knepley }
46050a6ba040SMatthew G. Knepley 
46069318fe57SMatthew G. Knepley /*@
4607a1cb98faSBarry Smith   DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell
46089318fe57SMatthew G. Knepley 
46099318fe57SMatthew G. Knepley   Collective
46109318fe57SMatthew G. Knepley 
46119318fe57SMatthew G. Knepley   Input Parameters:
46129318fe57SMatthew G. Knepley + comm - The communicator
46139318fe57SMatthew G. Knepley - ct   - The cell type of the reference cell
46149318fe57SMatthew G. Knepley 
46159318fe57SMatthew G. Knepley   Output Parameter:
46169318fe57SMatthew G. Knepley . refdm - The reference cell
46179318fe57SMatthew G. Knepley 
46189318fe57SMatthew G. Knepley   Level: intermediate
46199318fe57SMatthew G. Knepley 
462042747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`
46219318fe57SMatthew G. Knepley @*/
4622d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm)
4623d71ae5a4SJacob Faibussowitsch {
46240a6ba040SMatthew G. Knepley   PetscFunctionBegin;
46259566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, refdm));
46269566063dSJacob Faibussowitsch   PetscCall(DMSetType(*refdm, DMPLEX));
46279566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct));
46283ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46299318fe57SMatthew G. Knepley }
463079a015ccSMatthew G. Knepley 
4631d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[])
4632d71ae5a4SJacob Faibussowitsch {
46339318fe57SMatthew G. Knepley   DM        plex;
46349318fe57SMatthew G. Knepley   DMLabel   label;
46359318fe57SMatthew G. Knepley   PetscBool hasLabel;
46360a6ba040SMatthew G. Knepley 
4637c22d3578SMatthew G. Knepley   PetscFunctionBegin;
46389566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &hasLabel));
46393ba16761SJacob Faibussowitsch   if (hasLabel) PetscFunctionReturn(PETSC_SUCCESS);
46409566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, name));
46419566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
46429566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
46439566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label));
46441c8afea9SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(plex, label));
46459566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
46463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
46479318fe57SMatthew G. Knepley }
4648acdc6f61SToby Isaac 
4649669647acSMatthew G. Knepley /*
4650669647acSMatthew 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.
4651669647acSMatthew G. Knepley 
4652669647acSMatthew G. Knepley     (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0]))
4653669647acSMatthew G. Knepley */
4654d71ae5a4SJacob 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[])
4655d71ae5a4SJacob Faibussowitsch {
4656669647acSMatthew G. Knepley   const PetscReal low = PetscRealPart(constants[0]);
4657669647acSMatthew G. Knepley   const PetscReal upp = PetscRealPart(constants[1]);
4658669647acSMatthew G. Knepley   const PetscReal r   = PetscRealPart(u[1]);
4659669647acSMatthew G. Knepley   const PetscReal th  = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low);
4660669647acSMatthew G. Knepley 
4661669647acSMatthew G. Knepley   f0[0] = r * PetscCosReal(th);
4662669647acSMatthew G. Knepley   f0[1] = r * PetscSinReal(th);
4663669647acSMatthew G. Knepley }
4664669647acSMatthew G. Knepley 
46655390be7dSMatthew G. Knepley // Insert vertices and their joins, marked by depth
46665390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Vertices(DM dm, DMLabel label, DMLabel vlabel, PetscInt val, PetscInt n, const PetscInt vertices[])
46675390be7dSMatthew G. Knepley {
46685390be7dSMatthew G. Knepley   PetscFunctionBegin;
46695390be7dSMatthew G. Knepley   PetscCall(DMPlexMarkSubmesh_Interpolated(dm, vlabel, val, PETSC_FALSE, PETSC_FALSE, label, NULL));
46705390be7dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
46715390be7dSMatthew G. Knepley }
46725390be7dSMatthew G. Knepley 
46735390be7dSMatthew G. Knepley // Insert faces and their closures, marked by depth
46745390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Faces(DM dm, DMLabel label, PetscInt n, const PetscInt faces[])
46755390be7dSMatthew G. Knepley {
46765390be7dSMatthew G. Knepley   PetscFunctionBegin;
46775390be7dSMatthew G. Knepley   for (PetscInt p = 0; p < n; ++p) {
46785390be7dSMatthew G. Knepley     const PetscInt point   = faces[p];
46795390be7dSMatthew G. Knepley     PetscInt      *closure = NULL;
46805390be7dSMatthew G. Knepley     PetscInt       clSize, pdepth;
46815390be7dSMatthew G. Knepley 
46825390be7dSMatthew G. Knepley     PetscCall(DMPlexGetPointDepth(dm, point, &pdepth));
46835390be7dSMatthew G. Knepley     PetscCall(DMLabelSetValue(label, point, pdepth));
46845390be7dSMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure));
46855390be7dSMatthew G. Knepley     for (PetscInt cl = 0; cl < clSize * 2; cl += 2) {
46865390be7dSMatthew G. Knepley       PetscCall(DMPlexGetPointDepth(dm, closure[cl], &pdepth));
46875390be7dSMatthew G. Knepley       PetscCall(DMLabelSetValue(label, closure[cl], pdepth));
46885390be7dSMatthew G. Knepley     }
46895390be7dSMatthew G. Knepley     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure));
46905390be7dSMatthew G. Knepley   }
46915390be7dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
46925390be7dSMatthew G. Knepley }
46935390be7dSMatthew G. Knepley 
46944e22dd4cSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *flg);
46954e22dd4cSMatthew G. Knepley 
46965dca41c3SJed Brown const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "zbox", "unknown", "DMPlexShape", "DM_SHAPE_", NULL};
46979318fe57SMatthew G. Knepley 
4698ce78bad3SBarry Smith static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems PetscOptionsObject, PetscBool *useCoordSpace, DM dm)
4699d71ae5a4SJacob Faibussowitsch {
47009318fe57SMatthew G. Knepley   DMPlexShape    shape   = DM_SHAPE_BOX;
47019318fe57SMatthew G. Knepley   DMPolytopeType cell    = DM_POLYTOPE_TRIANGLE;
47029318fe57SMatthew G. Knepley   PetscInt       dim     = 2;
4703b9da1bb3SMatthew G. Knepley   PetscBool      simplex = PETSC_TRUE, interpolate = PETSC_TRUE, orient = PETSC_FALSE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE;
4704d0812dedSMatthew G. Knepley   PetscBool      flg, flg2, fflg, strflg, bdfflg, nameflg;
47059318fe57SMatthew G. Knepley   MPI_Comm       comm;
4706ed5e4e85SVaclav Hapla   char           filename[PETSC_MAX_PATH_LEN]   = "<unspecified>";
4707ed5e4e85SVaclav Hapla   char           bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>";
4708ed5e4e85SVaclav Hapla   char           plexname[PETSC_MAX_PATH_LEN]   = "";
47094e22dd4cSMatthew G. Knepley   const char    *option;
47109318fe57SMatthew G. Knepley 
47119318fe57SMatthew G. Knepley   PetscFunctionBegin;
4712708be2fdSJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromOptions, dm, 0, 0, 0));
47139566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
47149318fe57SMatthew G. Knepley   /* TODO Turn this into a registration interface */
47159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg));
4716d0812dedSMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_plex_file_contents", "Contents of a file format in a string", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &strflg));
47179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg));
47189566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg));
47199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL));
47209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL));
47219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg));
47229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0));
47239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg));
47249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg));
4725b9da1bb3SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_orient", "Orient the constructed mesh", "DMPlexOrient", orient, &orient, &flg));
47269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg));
47279566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2));
47289566063dSJacob Faibussowitsch   if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure));
47293f3e541fSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_adj", "Debug output level all adjacency computations", "", 0, &((DM_Plex *)dm->data)->printAdj, NULL, 0));
47309318fe57SMatthew G. Knepley 
473161a622f3SMatthew G. Knepley   switch (cell) {
473261a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT:
473361a622f3SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
473461a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
473561a622f3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
473661a622f3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
473761a622f3SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
4738d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_HEXAHEDRON:
4739d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_TRUE;
4740d71ae5a4SJacob Faibussowitsch     break;
4741d71ae5a4SJacob Faibussowitsch   default:
4742d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_FALSE;
4743d71ae5a4SJacob Faibussowitsch     break;
474461a622f3SMatthew G. Knepley   }
474561a622f3SMatthew G. Knepley 
47469318fe57SMatthew G. Knepley   if (fflg) {
47479318fe57SMatthew G. Knepley     DM          dmnew;
47481e4a82c4SMatthew G. Knepley     const char *name;
47499318fe57SMatthew G. Knepley 
47501e4a82c4SMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
47511e4a82c4SMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, nameflg ? plexname : name, interpolate, &dmnew));
47525de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
475369d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
47549318fe57SMatthew G. Knepley   } else if (refDomain) {
47559566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell));
47569318fe57SMatthew G. Knepley   } else if (bdfflg) {
47579318fe57SMatthew G. Knepley     DM          bdm, dmnew;
47581e4a82c4SMatthew G. Knepley     const char *name;
47599318fe57SMatthew G. Knepley 
47601e4a82c4SMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
47611e4a82c4SMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, nameflg ? plexname : name, interpolate, &bdm));
47629566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_"));
47639566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(bdm));
47649566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew));
47659566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&bdm));
47665de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
476769d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
4768d0812dedSMatthew G. Knepley   } else if (strflg) {
4769d0812dedSMatthew G. Knepley     DM          dmnew;
4770d0812dedSMatthew G. Knepley     PetscViewer viewer;
4771d0812dedSMatthew G. Knepley     const char *contents;
4772d0812dedSMatthew G. Knepley     char       *strname;
4773d0812dedSMatthew G. Knepley     char        tmpdir[PETSC_MAX_PATH_LEN];
4774d0812dedSMatthew G. Knepley     char        tmpfilename[PETSC_MAX_PATH_LEN];
4775d0812dedSMatthew G. Knepley     char        name[PETSC_MAX_PATH_LEN];
4776d0812dedSMatthew G. Knepley     MPI_Comm    comm;
4777d0812dedSMatthew G. Knepley     PetscMPIInt rank;
4778d0812dedSMatthew G. Knepley 
4779d0812dedSMatthew G. Knepley     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4780d0812dedSMatthew G. Knepley     PetscCallMPI(MPI_Comm_rank(comm, &rank));
4781d0812dedSMatthew G. Knepley     PetscCall(PetscStrchr(filename, ':', &strname));
4782d0812dedSMatthew G. Knepley     PetscCheck(strname, comm, PETSC_ERR_ARG_WRONG, "File contents must have the form \"ext:string_name\", not %s", filename);
4783d0812dedSMatthew G. Knepley     strname[0] = '\0';
4784d0812dedSMatthew G. Knepley     ++strname;
4785d0812dedSMatthew G. Knepley     PetscCall(PetscDLSym(NULL, strname, (void **)&contents));
4786d0812dedSMatthew G. Knepley     PetscCheck(contents, comm, PETSC_ERR_ARG_WRONG, "Could not locate mesh string %s", strname);
4787d0812dedSMatthew G. Knepley     PetscCall(PetscGetTmp(comm, tmpdir, PETSC_MAX_PATH_LEN));
4788ed32af8cSMatthew G. Knepley     PetscCall(PetscStrlcat(tmpdir, "/meshXXXXXX", PETSC_MAX_PATH_LEN));
4789ed32af8cSMatthew G. Knepley     PetscCall(PetscMkdtemp(tmpdir));
4790ed32af8cSMatthew G. Knepley     PetscCall(PetscSNPrintf(tmpfilename, PETSC_MAX_PATH_LEN, "%s/mesh.%s", tmpdir, filename));
4791d0812dedSMatthew G. Knepley     PetscCall(PetscViewerASCIIOpen(comm, tmpfilename, &viewer));
4792d0812dedSMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", contents));
4793d0812dedSMatthew G. Knepley     PetscCall(PetscViewerDestroy(&viewer));
4794d0812dedSMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), tmpfilename, plexname, interpolate, &dmnew));
4795ed32af8cSMatthew G. Knepley     PetscCall(PetscRMTree(tmpdir));
4796d0812dedSMatthew G. Knepley     PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%s Mesh", strname));
4797d0812dedSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, name));
4798d0812dedSMatthew G. Knepley     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
4799d0812dedSMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
48009318fe57SMatthew G. Knepley   } else {
48019566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape]));
48029318fe57SMatthew G. Knepley     switch (shape) {
4803669647acSMatthew G. Knepley     case DM_SHAPE_BOX:
48045dca41c3SJed Brown     case DM_SHAPE_ZBOX:
4805669647acSMatthew G. Knepley     case DM_SHAPE_ANNULUS: {
48069318fe57SMatthew G. Knepley       PetscInt       faces[3]  = {0, 0, 0};
48079318fe57SMatthew G. Knepley       PetscReal      lower[3]  = {0, 0, 0};
48089318fe57SMatthew G. Knepley       PetscReal      upper[3]  = {1, 1, 1};
48099318fe57SMatthew G. Knepley       DMBoundaryType bdt[3]    = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
4810669647acSMatthew G. Knepley       PetscBool      isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE;
48119318fe57SMatthew G. Knepley       PetscInt       i, n;
48129318fe57SMatthew G. Knepley 
48139318fe57SMatthew G. Knepley       n = dim;
48149318fe57SMatthew G. Knepley       for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim);
48159566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
48169318fe57SMatthew G. Knepley       n = 3;
48179566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
481863a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
48199318fe57SMatthew G. Knepley       n = 3;
48209566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
482163a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
48229318fe57SMatthew G. Knepley       n = 3;
48239566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
482463a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
4825669647acSMatthew G. Knepley 
4826669647acSMatthew G. Knepley       PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented");
4827669647acSMatthew G. Knepley       if (isAnnular)
4828669647acSMatthew G. Knepley         for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC;
4829669647acSMatthew G. Knepley 
48309318fe57SMatthew G. Knepley       switch (cell) {
483161a622f3SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
48329566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt));
4833d410b0cfSMatthew G. Knepley         if (!interpolate) {
4834d410b0cfSMatthew G. Knepley           DM udm;
4835d410b0cfSMatthew G. Knepley 
48369566063dSJacob Faibussowitsch           PetscCall(DMPlexUninterpolate(dm, &udm));
483769d8a87bSksagiyam           PetscCall(DMPlexReplace_Internal(dm, &udm));
4838d410b0cfSMatthew G. Knepley         }
48399318fe57SMatthew G. Knepley         break;
4840d71ae5a4SJacob Faibussowitsch       default:
48415dca41c3SJed Brown         PetscCall(DMPlexCreateBoxMesh_Internal(dm, shape, dim, simplex, faces, lower, upper, bdt, interpolate));
4842d71ae5a4SJacob Faibussowitsch         break;
48439318fe57SMatthew G. Knepley       }
4844669647acSMatthew G. Knepley       if (isAnnular) {
4845669647acSMatthew G. Knepley         DM          cdm;
4846669647acSMatthew G. Knepley         PetscDS     cds;
4847669647acSMatthew G. Knepley         PetscScalar bounds[2] = {lower[0], upper[0]};
4848669647acSMatthew G. Knepley 
4849669647acSMatthew G. Knepley         // Fix coordinates for annular region
4850669647acSMatthew G. Knepley         PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL));
4851669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinatesLocal(dm, NULL));
4852669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinates(dm, NULL));
4853e44f6aebSMatthew G. Knepley         PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL));
4854669647acSMatthew G. Knepley         PetscCall(DMGetCoordinateDM(dm, &cdm));
4855669647acSMatthew G. Knepley         PetscCall(DMGetDS(cdm, &cds));
4856669647acSMatthew G. Knepley         PetscCall(PetscDSSetConstants(cds, 2, bounds));
4857669647acSMatthew G. Knepley         PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus));
4858669647acSMatthew G. Knepley       }
48599371c9d4SSatish Balay     } break;
48609371c9d4SSatish Balay     case DM_SHAPE_BOX_SURFACE: {
48619318fe57SMatthew G. Knepley       PetscInt  faces[3] = {0, 0, 0};
48629318fe57SMatthew G. Knepley       PetscReal lower[3] = {0, 0, 0};
48639318fe57SMatthew G. Knepley       PetscReal upper[3] = {1, 1, 1};
48649318fe57SMatthew G. Knepley       PetscInt  i, n;
48659318fe57SMatthew G. Knepley 
48669318fe57SMatthew G. Knepley       n = dim + 1;
48679318fe57SMatthew G. Knepley       for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1));
48689566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
48699318fe57SMatthew G. Knepley       n = 3;
48709566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
487163a3b9bcSJacob 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);
48729318fe57SMatthew G. Knepley       n = 3;
48739566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
487463a3b9bcSJacob 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);
48759566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate));
48769371c9d4SSatish Balay     } break;
48779371c9d4SSatish Balay     case DM_SHAPE_SPHERE: {
48789318fe57SMatthew G. Knepley       PetscReal R = 1.0;
48799318fe57SMatthew G. Knepley 
48809566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg));
48819566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R));
48829371c9d4SSatish Balay     } break;
48839371c9d4SSatish Balay     case DM_SHAPE_BALL: {
48849318fe57SMatthew G. Knepley       PetscReal R = 1.0;
48859318fe57SMatthew G. Knepley 
48869566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg));
48879566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R));
48889371c9d4SSatish Balay     } break;
48899371c9d4SSatish Balay     case DM_SHAPE_CYLINDER: {
48909318fe57SMatthew G. Knepley       DMBoundaryType bdt = DM_BOUNDARY_NONE;
48919318fe57SMatthew G. Knepley       PetscInt       Nw  = 6;
489249704ca5SMatthew G. Knepley       PetscInt       Nr  = 0;
48939318fe57SMatthew G. Knepley 
48949566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL));
48959566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL));
489649704ca5SMatthew G. Knepley       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_refine", "Number of refinements before projection", "", Nr, &Nr, NULL));
48979318fe57SMatthew G. Knepley       switch (cell) {
4898d71ae5a4SJacob Faibussowitsch       case DM_POLYTOPE_TRI_PRISM_TENSOR:
4899d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate));
4900d71ae5a4SJacob Faibussowitsch         break;
4901d71ae5a4SJacob Faibussowitsch       default:
490249704ca5SMatthew G. Knepley         PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt, Nr));
4903d71ae5a4SJacob Faibussowitsch         break;
49049318fe57SMatthew G. Knepley       }
49059371c9d4SSatish Balay     } break;
4906b7f5c055SJed Brown     case DM_SHAPE_SCHWARZ_P: // fallthrough
49079371c9d4SSatish Balay     case DM_SHAPE_GYROID: {
4908b7f5c055SJed Brown       PetscInt       extent[3] = {1, 1, 1}, refine = 0, layers = 0, three;
4909b7f5c055SJed Brown       PetscReal      thickness   = 0.;
4910b7f5c055SJed Brown       DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
4911b7f5c055SJed Brown       DMPlexTPSType  tps_type    = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID;
49121436d7faSJed Brown       PetscBool      tps_distribute;
49139566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL));
49149566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL));
49159566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL));
49169566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL));
49179566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL));
49189566063dSJacob Faibussowitsch       PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute));
49199566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL));
49209566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness));
49219371c9d4SSatish Balay     } break;
49229371c9d4SSatish Balay     case DM_SHAPE_DOUBLET: {
492305bd46c0SStefano Zampini       DM        dmnew;
492405bd46c0SStefano Zampini       PetscReal rl = 0.0;
492505bd46c0SStefano Zampini 
492605bd46c0SStefano Zampini       PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL));
492705bd46c0SStefano Zampini       PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew));
49285de52c6dSVaclav Hapla       PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
492969d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &dmnew));
49309371c9d4SSatish Balay     } break;
4931cfb853baSMatthew G. Knepley     case DM_SHAPE_HYPERCUBIC: {
49328d2ec52aSSatish Balay       PetscInt       *edges, overlap = 1;
4933cfb853baSMatthew G. Knepley       PetscReal      *lower, *upper;
4934cfb853baSMatthew G. Knepley       DMBoundaryType *bdt;
4935cfb853baSMatthew G. Knepley       PetscInt        n, d;
4936cfb853baSMatthew G. Knepley 
4937cfb853baSMatthew G. Knepley       *useCoordSpace = PETSC_FALSE;
4938cfb853baSMatthew G. Knepley       PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt));
4939cfb853baSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
4940cfb853baSMatthew G. Knepley         edges[d] = 1;
4941cfb853baSMatthew G. Knepley         lower[d] = 0.;
4942cfb853baSMatthew G. Knepley         upper[d] = 1.;
4943cfb853baSMatthew G. Knepley         bdt[d]   = DM_BOUNDARY_PERIODIC;
4944cfb853baSMatthew G. Knepley       }
4945cfb853baSMatthew G. Knepley       n = dim;
4946cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg));
4947cfb853baSMatthew G. Knepley       n = dim;
4948cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
4949cfb853baSMatthew 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);
4950cfb853baSMatthew G. Knepley       n = dim;
4951cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
4952cfb853baSMatthew 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);
4953cfb853baSMatthew G. Knepley       n = dim;
4954cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
4955cfb853baSMatthew 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);
49568d2ec52aSSatish Balay       PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", overlap, &overlap, NULL, 0));
49578d2ec52aSSatish Balay       PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, overlap, bdt));
4958cfb853baSMatthew G. Knepley       PetscCall(PetscFree4(edges, lower, upper, bdt));
4959cfb853baSMatthew G. Knepley     } break;
4960d71ae5a4SJacob Faibussowitsch     default:
4961d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]);
49629318fe57SMatthew G. Knepley     }
49639318fe57SMatthew G. Knepley   }
49649566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
496548a46eb9SPierre Jolivet   if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname));
4966b9da1bb3SMatthew G. Knepley   if (orient) PetscCall(DMPlexOrient(dm));
49674e22dd4cSMatthew G. Knepley   // Allow label creation
49684e22dd4cSMatthew G. Knepley   PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_label_", &option, NULL, &flg));
49694e22dd4cSMatthew G. Knepley   if (flg) {
49704e22dd4cSMatthew G. Knepley     DMLabel     label;
49714e22dd4cSMatthew G. Knepley     PetscInt    points[1024], n = 1024;
49724e22dd4cSMatthew G. Knepley     char        fulloption[PETSC_MAX_PATH_LEN];
49734e22dd4cSMatthew G. Knepley     const char *name = &option[14];
49744e22dd4cSMatthew G. Knepley 
49754e22dd4cSMatthew G. Knepley     PetscCall(DMCreateLabel(dm, name));
49764e22dd4cSMatthew G. Knepley     PetscCall(DMGetLabel(dm, name, &label));
49774e22dd4cSMatthew G. Knepley     fulloption[0] = '-';
49784e22dd4cSMatthew G. Knepley     fulloption[1] = 0;
49794e22dd4cSMatthew G. Knepley     PetscCall(PetscStrlcat(fulloption, option, PETSC_MAX_PATH_LEN));
49804e22dd4cSMatthew G. Knepley     PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, NULL));
49814e22dd4cSMatthew G. Knepley     for (PetscInt p = 0; p < n; ++p) PetscCall(DMLabelSetValue(label, points[p], 1));
49824e22dd4cSMatthew G. Knepley   }
4983dd0eeac9SMatthew G. Knepley   // Allow cohesive label creation
4984dd0eeac9SMatthew G. Knepley   //   Faces are input, completed, and all points are marked with their depth
4985dd0eeac9SMatthew G. Knepley   PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_cohesive_label_", &option, NULL, &flg));
4986dd0eeac9SMatthew G. Knepley   if (flg) {
4987dd0eeac9SMatthew G. Knepley     DMLabel   label;
4988dd0eeac9SMatthew G. Knepley     PetscInt  points[1024], n, pStart, pEnd, Nl = 1;
49895390be7dSMatthew G. Knepley     PetscBool noCreate = PETSC_FALSE;
4990dd0eeac9SMatthew G. Knepley     char      fulloption[PETSC_MAX_PATH_LEN];
4991dd0eeac9SMatthew G. Knepley     char      name[PETSC_MAX_PATH_LEN];
4992dd0eeac9SMatthew G. Knepley     size_t    len;
4993dd0eeac9SMatthew G. Knepley 
4994dd0eeac9SMatthew G. Knepley     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4995dd0eeac9SMatthew G. Knepley     PetscCall(PetscStrncpy(name, &option[23], PETSC_MAX_PATH_LEN));
4996dd0eeac9SMatthew G. Knepley     PetscCall(PetscStrlen(name, &len));
4997dd0eeac9SMatthew G. Knepley     if (name[len - 1] == '0') Nl = 10;
4998dd0eeac9SMatthew G. Knepley     for (PetscInt l = 0; l < Nl; ++l) {
49996497c311SBarry Smith       if (l > 0) name[len - 1] = (char)('0' + l);
5000dd0eeac9SMatthew G. Knepley       fulloption[0] = 0;
5001dd0eeac9SMatthew G. Knepley       PetscCall(PetscStrlcat(fulloption, "-dm_plex_cohesive_label_", 32));
5002dd0eeac9SMatthew G. Knepley       PetscCall(PetscStrlcat(fulloption, name, PETSC_MAX_PATH_LEN - 32));
5003dd0eeac9SMatthew G. Knepley       n = 1024;
5004dd0eeac9SMatthew G. Knepley       PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, &flg));
5005dd0eeac9SMatthew G. Knepley       if (!flg) break;
50065390be7dSMatthew G. Knepley       PetscCall(DMHasLabel(dm, name, &noCreate));
50075390be7dSMatthew G. Knepley       if (noCreate) {
50085390be7dSMatthew G. Knepley         DMLabel         inlabel;
50095390be7dSMatthew G. Knepley         IS              pointIS;
50105390be7dSMatthew G. Knepley         const PetscInt *lpoints;
50115390be7dSMatthew G. Knepley         PetscInt        pdep, ln, inval = points[0];
50125390be7dSMatthew G. Knepley         char            newname[PETSC_MAX_PATH_LEN];
50135390be7dSMatthew G. Knepley 
50145390be7dSMatthew G. Knepley         PetscCheck(n == 1, comm, PETSC_ERR_ARG_WRONG, "Must specify a label value with this option");
50155390be7dSMatthew G. Knepley         PetscCall(DMGetLabel(dm, name, &inlabel));
50165390be7dSMatthew G. Knepley         PetscCall(DMLabelGetStratumIS(inlabel, inval, &pointIS));
50175390be7dSMatthew G. Knepley         PetscCall(ISGetLocalSize(pointIS, &ln));
50185390be7dSMatthew G. Knepley         PetscCall(ISGetIndices(pointIS, &lpoints));
50195390be7dSMatthew G. Knepley         PetscCall(DMPlexGetPointDepth(dm, lpoints[0], &pdep));
50205390be7dSMatthew G. Knepley         PetscCall(PetscSNPrintf(newname, PETSC_MAX_PATH_LEN, "%s%" PetscInt_FMT, name, points[0]));
50215390be7dSMatthew G. Knepley         PetscCall(DMCreateLabel(dm, newname));
50225390be7dSMatthew G. Knepley         PetscCall(DMGetLabel(dm, newname, &label));
50235390be7dSMatthew G. Knepley         if (!pdep) PetscCall(ProcessCohesiveLabel_Vertices(dm, label, inlabel, inval, ln, lpoints));
50245390be7dSMatthew G. Knepley         else PetscCall(ProcessCohesiveLabel_Faces(dm, label, ln, lpoints));
50255390be7dSMatthew G. Knepley         PetscCall(ISRestoreIndices(pointIS, &lpoints));
50265390be7dSMatthew G. Knepley         PetscCall(ISDestroy(&pointIS));
50275390be7dSMatthew G. Knepley       } else {
5028dd0eeac9SMatthew G. Knepley         PetscCall(DMCreateLabel(dm, name));
5029dd0eeac9SMatthew G. Knepley         PetscCall(DMGetLabel(dm, name, &label));
5030dd0eeac9SMatthew G. Knepley         if (pStart >= pEnd) n = 0;
50315390be7dSMatthew G. Knepley         PetscCall(ProcessCohesiveLabel_Faces(dm, label, n, points));
5032dd0eeac9SMatthew G. Knepley       }
5033dd0eeac9SMatthew G. Knepley       PetscCall(DMPlexOrientLabel(dm, label));
50340542aa8cSMatthew G. Knepley       PetscCall(DMPlexLabelCohesiveComplete(dm, label, NULL, 1, PETSC_FALSE, PETSC_FALSE, NULL));
5035dd0eeac9SMatthew G. Knepley     }
5036dd0eeac9SMatthew G. Knepley   }
50375390be7dSMatthew G. Knepley   PetscCall(DMViewFromOptions(dm, NULL, "-created_dm_view"));
5038708be2fdSJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromOptions, dm, 0, 0, 0));
50393ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
50400a6ba040SMatthew G. Knepley }
50410a6ba040SMatthew G. Knepley 
5042ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems PetscOptionsObject)
5043d71ae5a4SJacob Faibussowitsch {
50440a6ba040SMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
50457f9d8d6cSVaclav Hapla   PetscBool flg, flg2;
50469318fe57SMatthew G. Knepley   char      bdLabel[PETSC_MAX_PATH_LEN];
5047adc21957SMatthew G. Knepley   char      method[PETSC_MAX_PATH_LEN];
50480a6ba040SMatthew G. Knepley 
50490a6ba040SMatthew G. Knepley   PetscFunctionBegin;
50500a6ba040SMatthew G. Knepley   /* Handle viewing */
50519566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL));
50525962854dSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level for all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0));
50535962854dSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fvm", "Debug output level for all fvm computations", "DMPlexSNESComputeResidualFVM", 0, &mesh->printFVM, NULL, 0));
50549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL));
50559566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0));
5056f5867de0SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0));
5057a77a5016SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_project", "Debug output level all projection computations", "DMPlexProject", 0, &mesh->printProject, NULL, 0));
50589566063dSJacob Faibussowitsch   PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg));
50599566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscLogDefaultBegin());
50605e2c5519SMatthew G. Knepley   // Interpolation
50615e2c5519SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_interpolate_prefer_tensor", "When different orderings exist, prefer the tensor order", "DMPlexSetInterpolationPreferTensor", mesh->interpolatePreferTensor, &mesh->interpolatePreferTensor, NULL));
50629318fe57SMatthew G. Knepley   /* Labeling */
50639566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg));
50649566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel));
5065953fc75cSMatthew G. Knepley   /* Point Location */
50669566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL));
50670848f4b5SMatthew G. Knepley   /* Partitioning and distribution */
50689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL));
5069d02c7345SMatthew G. Knepley   /* Reordering */
5070adc21957SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_reorder_section", "Compute point permutation for local section", "DMReorderSectionSetDefault", PETSC_FALSE, &flg2, &flg));
5071adc21957SMatthew G. Knepley   if (flg) PetscCall(DMReorderSectionSetDefault(dm, flg2 ? DM_REORDER_DEFAULT_TRUE : DM_REORDER_DEFAULT_FALSE));
5072adc21957SMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_reorder_section_type", "Reordering method for local section", "DMReorderSectionSetType", method, method, PETSC_MAX_PATH_LEN, &flg));
5073adc21957SMatthew G. Knepley   if (flg) PetscCall(DMReorderSectionSetType(dm, method));
50742e62ab5aSMatthew G. Knepley   /* Generation and remeshing */
50759566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL));
5076b29cfa1cSToby Isaac   /* Projection behavior */
5077d5b43468SJose E. Roman   PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0));
50789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL));
5079f12cf164SMatthew G. Knepley   /* Checking structure */
5080f12cf164SMatthew G. Knepley   {
50817f9d8d6cSVaclav Hapla     PetscBool all = PETSC_FALSE;
5082f12cf164SMatthew G. Knepley 
50837f9d8d6cSVaclav Hapla     PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL));
50847f9d8d6cSVaclav Hapla     if (all) {
50857f9d8d6cSVaclav Hapla       PetscCall(DMPlexCheck(dm));
50867f9d8d6cSVaclav Hapla     } else {
50879566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2));
50887f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm));
50899566063dSJacob 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));
50907f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0));
50919566063dSJacob 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));
50927f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0));
50939566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2));
50947f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm));
50959566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2));
5096d7d32a9aSMatthew G. Knepley       if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
50979566063dSJacob 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));
50987f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm));
50997f9d8d6cSVaclav Hapla     }
51009566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2));
51019566063dSJacob Faibussowitsch     if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE));
5102f12cf164SMatthew G. Knepley   }
51039318fe57SMatthew G. Knepley   {
51049318fe57SMatthew G. Knepley     PetscReal scale = 1.0;
51054f3833eaSMatthew G. Knepley 
51069566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg));
51079318fe57SMatthew G. Knepley     if (flg) {
51089318fe57SMatthew G. Knepley       Vec coordinates, coordinatesLocal;
51099318fe57SMatthew G. Knepley 
51109566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinates(dm, &coordinates));
51119566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
51129566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinates, scale));
51139566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinatesLocal, scale));
51149318fe57SMatthew G. Knepley     }
51159318fe57SMatthew G. Knepley   }
51169566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner));
51173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
511868d4fef7SMatthew G. Knepley }
511968d4fef7SMatthew G. Knepley 
5120ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems PetscOptionsObject, PetscInt *overlap)
5121d71ae5a4SJacob Faibussowitsch {
5122c506a872SMatthew G. Knepley   PetscInt  numOvLabels = 16, numOvExLabels = 16;
5123c506a872SMatthew G. Knepley   char     *ovLabelNames[16], *ovExLabelNames[16];
5124c506a872SMatthew G. Knepley   PetscInt  numOvValues = 16, numOvExValues = 16, l;
5125c506a872SMatthew G. Knepley   PetscBool flg;
5126c506a872SMatthew G. Knepley 
5127c506a872SMatthew G. Knepley   PetscFunctionBegin;
5128c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0));
5129c506a872SMatthew G. Knepley   PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg));
5130c506a872SMatthew G. Knepley   if (!flg) numOvLabels = 0;
5131c506a872SMatthew G. Knepley   if (numOvLabels) {
5132c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvLabels = numOvLabels;
5133c506a872SMatthew G. Knepley     for (l = 0; l < numOvLabels; ++l) {
5134c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l]));
5135c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]);
5136c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovLabelNames[l]));
5137c506a872SMatthew G. Knepley     }
5138c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg));
5139c506a872SMatthew G. Knepley     if (!flg) numOvValues = 0;
5140c506a872SMatthew 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);
5141c506a872SMatthew G. Knepley 
5142c506a872SMatthew G. Knepley     PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg));
5143c506a872SMatthew G. Knepley     if (!flg) numOvExLabels = 0;
5144c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels;
5145c506a872SMatthew G. Knepley     for (l = 0; l < numOvExLabels; ++l) {
5146c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l]));
5147c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]);
5148c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovExLabelNames[l]));
5149c506a872SMatthew G. Knepley     }
5150c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg));
5151c506a872SMatthew G. Knepley     if (!flg) numOvExValues = 0;
5152c506a872SMatthew 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);
5153c506a872SMatthew G. Knepley   }
51543ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5155c506a872SMatthew G. Knepley }
5156c506a872SMatthew G. Knepley 
5157ce78bad3SBarry Smith static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems PetscOptionsObject)
5158d71ae5a4SJacob Faibussowitsch {
5159bdf63967SMatthew G. Knepley   PetscFunctionList    ordlist;
5160bdf63967SMatthew G. Knepley   char                 oname[256];
51614e22dd4cSMatthew G. Knepley   char                 sublabelname[PETSC_MAX_PATH_LEN] = "";
5162adc21957SMatthew G. Knepley   DMReorderDefaultFlag reorder;
5163d410b0cfSMatthew G. Knepley   PetscReal            volume    = -1.0;
51649318fe57SMatthew G. Knepley   PetscInt             prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim;
51651b742f01SMatthew G. Knepley   PetscBool            uniformOrig = PETSC_FALSE, created = PETSC_FALSE, uniform = PETSC_TRUE, distribute, saveSF = PETSC_FALSE, interpolate = PETSC_TRUE, coordSpace = PETSC_TRUE, remap = PETSC_TRUE, ghostCells = PETSC_FALSE, isHierarchy, flg;
516668d4fef7SMatthew G. Knepley 
516768d4fef7SMatthew G. Knepley   PetscFunctionBegin;
5168d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options");
5169dd4c3f67SMatthew G. Knepley   if (dm->cloneOpts) goto non_refine;
51709318fe57SMatthew G. Knepley   /* Handle automatic creation */
51719566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
51726bc1bd01Sksagiyam   if (dim < 0) {
51736bc1bd01Sksagiyam     PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));
51746bc1bd01Sksagiyam     created = PETSC_TRUE;
51756bc1bd01Sksagiyam   }
51766bc1bd01Sksagiyam   PetscCall(DMGetDimension(dm, &dim));
5177d89e6e46SMatthew G. Knepley   /* Handle interpolation before distribution */
51789566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg));
5179d89e6e46SMatthew G. Knepley   if (flg) {
5180d89e6e46SMatthew G. Knepley     DMPlexInterpolatedFlag interpolated;
5181d89e6e46SMatthew G. Knepley 
51829566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpolated));
5183d89e6e46SMatthew G. Knepley     if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) {
5184d89e6e46SMatthew G. Knepley       DM udm;
5185d89e6e46SMatthew G. Knepley 
51869566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(dm, &udm));
518769d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &udm));
5188d89e6e46SMatthew G. Knepley     } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) {
5189d89e6e46SMatthew G. Knepley       DM idm;
5190d89e6e46SMatthew G. Knepley 
51919566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(dm, &idm));
519269d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &idm));
5193d89e6e46SMatthew G. Knepley     }
5194d89e6e46SMatthew G. Knepley   }
51954e22dd4cSMatthew G. Knepley   // Handle submesh selection before distribution
51964e22dd4cSMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_plex_submesh", "Label to use for submesh selection", "", sublabelname, sublabelname, PETSC_MAX_PATH_LEN, &flg));
51974e22dd4cSMatthew G. Knepley   if (flg) {
51984e22dd4cSMatthew G. Knepley     DM              subdm;
51994e22dd4cSMatthew G. Knepley     DMLabel         label;
52004e22dd4cSMatthew G. Knepley     IS              valueIS, pointIS;
52014e22dd4cSMatthew G. Knepley     const PetscInt *values, *points;
52024e22dd4cSMatthew G. Knepley     PetscBool       markedFaces = PETSC_FALSE;
52034e22dd4cSMatthew G. Knepley     PetscInt        Nv, value, Np;
52044e22dd4cSMatthew G. Knepley 
52054e22dd4cSMatthew G. Knepley     PetscCall(DMGetLabel(dm, sublabelname, &label));
52064e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetNumValues(label, &Nv));
52074e22dd4cSMatthew 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);
52084e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetValueIS(label, &valueIS));
52094e22dd4cSMatthew G. Knepley     PetscCall(ISGetIndices(valueIS, &values));
52104e22dd4cSMatthew G. Knepley     value = values[0];
52114e22dd4cSMatthew G. Knepley     PetscCall(ISRestoreIndices(valueIS, &values));
52124e22dd4cSMatthew G. Knepley     PetscCall(ISDestroy(&valueIS));
52134e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetStratumSize(label, value, &Np));
52144e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetStratumIS(label, value, &pointIS));
52154e22dd4cSMatthew G. Knepley     PetscCall(ISGetIndices(pointIS, &points));
52164e22dd4cSMatthew G. Knepley     for (PetscInt p = 0; p < Np; ++p) {
52174e22dd4cSMatthew G. Knepley       PetscInt pdepth;
52184e22dd4cSMatthew G. Knepley 
52194e22dd4cSMatthew G. Knepley       PetscCall(DMPlexGetPointDepth(dm, points[p], &pdepth));
52204e22dd4cSMatthew G. Knepley       if (pdepth) {
52214e22dd4cSMatthew G. Knepley         markedFaces = PETSC_TRUE;
52224e22dd4cSMatthew G. Knepley         break;
52234e22dd4cSMatthew G. Knepley       }
52244e22dd4cSMatthew G. Knepley     }
52254e22dd4cSMatthew G. Knepley     PetscCall(ISRestoreIndices(pointIS, &points));
52264e22dd4cSMatthew G. Knepley     PetscCall(ISDestroy(&pointIS));
52274e22dd4cSMatthew G. Knepley     PetscCall(DMPlexCreateSubmesh(dm, label, value, markedFaces, &subdm));
52284e22dd4cSMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &subdm));
52294e22dd4cSMatthew G. Knepley     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
52304e22dd4cSMatthew G. Knepley   }
52319b44eab4SMatthew G. Knepley   /* Handle DMPlex refinement before distribution */
52329566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig));
52339566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0));
52349566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
52359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg));
52369566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform));
52379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg));
52389318fe57SMatthew G. Knepley   if (flg) {
52399566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE));
52409566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(dm, volume));
52419318fe57SMatthew G. Knepley     prerefine = PetscMax(prerefine, 1);
52429318fe57SMatthew G. Knepley   }
5243b23db253SStefano Zampini   if (prerefine) PetscCall(DMLocalizeCoordinates(dm));
52449b44eab4SMatthew G. Knepley   for (r = 0; r < prerefine; ++r) {
52459b44eab4SMatthew G. Knepley     DM             rdm;
52469b44eab4SMatthew G. Knepley     PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
52479b44eab4SMatthew G. Knepley 
5248dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
52499566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
525069d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &rdm));
5251dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
525261a622f3SMatthew G. Knepley     if (coordFunc && remap) {
52539566063dSJacob Faibussowitsch       PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
52549b44eab4SMatthew G. Knepley       ((DM_Plex *)dm->data)->coordFunc = coordFunc;
52559b44eab4SMatthew G. Knepley     }
52569b44eab4SMatthew G. Knepley   }
52579566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig));
52589318fe57SMatthew G. Knepley   /* Handle DMPlex extrusion before distribution */
52599566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0));
52609318fe57SMatthew G. Knepley   if (extLayers) {
52619318fe57SMatthew G. Knepley     DM edm;
52629318fe57SMatthew G. Knepley 
52639566063dSJacob Faibussowitsch     PetscCall(DMExtrude(dm, extLayers, &edm));
526469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
526548d16a33SMatthew G. Knepley     ((DM_Plex *)dm->data)->coordFunc = NULL;
5266dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
5267d410b0cfSMatthew G. Knepley     extLayers = 0;
52685e17fc22SAidan Hamilton     PetscCall(DMGetDimension(dm, &dim));
52699318fe57SMatthew G. Knepley   }
5270bdf63967SMatthew G. Knepley   /* Handle DMPlex reordering before distribution */
52716bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dm, &reorder));
52729566063dSJacob Faibussowitsch   PetscCall(MatGetOrderingList(&ordlist));
52736bc1bd01Sksagiyam   PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname)));
52749566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg));
5275adc21957SMatthew G. Knepley   if (reorder == DM_REORDER_DEFAULT_TRUE || flg) {
5276bdf63967SMatthew G. Knepley     DM pdm;
5277bdf63967SMatthew G. Knepley     IS perm;
5278bdf63967SMatthew G. Knepley 
52799566063dSJacob Faibussowitsch     PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm));
52809566063dSJacob Faibussowitsch     PetscCall(DMPlexPermute(dm, perm, &pdm));
52819566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&perm));
528269d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &pdm));
5283dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
5284bdf63967SMatthew G. Knepley   }
52859b44eab4SMatthew G. Knepley   /* Handle DMPlex distribution */
52869566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dm, &distribute));
5287c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL));
5288a286e215SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute_save_sf", "Flag to save the migration SF", "DMPlexSetMigrationSF", saveSF, &saveSF, NULL));
5289dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap));
52909b44eab4SMatthew G. Knepley   if (distribute) {
52919b44eab4SMatthew G. Knepley     DM               pdm = NULL;
52929b44eab4SMatthew G. Knepley     PetscPartitioner part;
5293a286e215SMatthew G. Knepley     PetscSF          sfMigration;
52949b44eab4SMatthew G. Knepley 
52959566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
52969566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
5297a286e215SMatthew G. Knepley     PetscCall(DMPlexDistribute(dm, overlap, &sfMigration, &pdm));
52985d2873a6SJames Wright     if (pdm) {
52995d2873a6SJames Wright       // Delete the local section to force the existing one to be rebuilt with the distributed DM
53005d2873a6SJames Wright       PetscCall(DMSetLocalSection(dm, pdm->localSection));
53015d2873a6SJames Wright       PetscCall(DMPlexReplace_Internal(dm, &pdm));
53025d2873a6SJames Wright     }
5303a286e215SMatthew G. Knepley     if (saveSF) PetscCall(DMPlexSetMigrationSF(dm, sfMigration));
5304a286e215SMatthew G. Knepley     PetscCall(PetscSFDestroy(&sfMigration));
53059b44eab4SMatthew G. Knepley   }
53064054ae39SJames Wright 
53074054ae39SJames Wright   {
53084054ae39SJames Wright     PetscBool useBoxLabel = PETSC_FALSE;
53094054ae39SJames Wright     PetscCall(PetscOptionsBool("-dm_plex_box_label", "Create 'Face Sets' assuming boundary faces align with cartesian directions", "DMCreate", useBoxLabel, &useBoxLabel, NULL));
5310d7d2d1d2SJames Wright     if (useBoxLabel) {
5311d7d2d1d2SJames Wright       PetscInt       n      = 3;
5312d7d2d1d2SJames Wright       DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
5313d7d2d1d2SJames Wright 
5314d7d2d1d2SJames Wright       PetscCall(PetscOptionsEnumArray("-dm_plex_box_label_bd", "Boundary type for each dimension when using -dm_plex_box_label", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
5315d7d2d1d2SJames 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);
5316d7d2d1d2SJames Wright       PetscCall(DMPlexSetBoxLabel_Internal(dm, bdt));
5317d7d2d1d2SJames Wright     }
53184054ae39SJames Wright   }
5319d2b2dc1eSMatthew G. Knepley   /* Must check CEED options before creating function space for coordinates */
5320d2b2dc1eSMatthew G. Knepley   {
5321d2b2dc1eSMatthew G. Knepley     PetscBool useCeed = PETSC_FALSE, flg;
5322d2b2dc1eSMatthew G. Knepley 
5323d2b2dc1eSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_plex_use_ceed", "Use LibCEED as the FEM backend", "DMPlexSetUseCeed", useCeed, &useCeed, &flg));
5324d2b2dc1eSMatthew G. Knepley     if (flg) PetscCall(DMPlexSetUseCeed(dm, useCeed));
5325d2b2dc1eSMatthew G. Knepley   }
53269318fe57SMatthew G. Knepley   /* Create coordinate space */
53279318fe57SMatthew G. Knepley   if (created) {
532861a622f3SMatthew G. Knepley     DM_Plex  *mesh   = (DM_Plex *)dm->data;
5329e44f6aebSMatthew G. Knepley     PetscInt  degree = 1, deg;
53305515ebd3SMatthew G. Knepley     PetscInt  height = 0;
53315515ebd3SMatthew G. Knepley     DM        cdm;
5332c3db174cSMatthew G. Knepley     PetscBool flg, localize = PETSC_TRUE, sparseLocalize = PETSC_TRUE;
53339318fe57SMatthew G. Knepley 
53349566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg));
53359566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, &degree, NULL));
5336e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDegree_Internal(dm, &deg));
5337e44f6aebSMatthew G. Knepley     if (coordSpace && deg <= 1) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_TRUE, mesh->coordFunc));
53385515ebd3SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
533961a622f3SMatthew G. Knepley     if (flg && !coordSpace) {
534061a622f3SMatthew G. Knepley       PetscDS      cds;
534161a622f3SMatthew G. Knepley       PetscObject  obj;
534261a622f3SMatthew G. Knepley       PetscClassId id;
534361a622f3SMatthew G. Knepley 
53449566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdm, &cds));
53459566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
53469566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
534761a622f3SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
534861a622f3SMatthew G. Knepley         PetscContainer dummy;
534961a622f3SMatthew G. Knepley 
53509566063dSJacob Faibussowitsch         PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy));
53519566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates"));
53529566063dSJacob Faibussowitsch         PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy));
53539566063dSJacob Faibussowitsch         PetscCall(PetscContainerDestroy(&dummy));
53549566063dSJacob Faibussowitsch         PetscCall(DMClearDS(cdm));
535561a622f3SMatthew G. Knepley       }
535661a622f3SMatthew G. Knepley       mesh->coordFunc = NULL;
535761a622f3SMatthew G. Knepley     }
5358c3db174cSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_localize", "Localize mesh coordinates", "", localize, &localize, NULL));
5359c3db174cSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "DMSetSparseLocalize", sparseLocalize, &sparseLocalize, &flg));
5360c3db174cSMatthew G. Knepley     if (flg) PetscCall(DMSetSparseLocalize(dm, sparseLocalize));
53615515ebd3SMatthew G. Knepley     PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg));
53625515ebd3SMatthew G. Knepley     if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height));
5363c3db174cSMatthew G. Knepley     if (localize) PetscCall(DMLocalizeCoordinates(dm));
53649318fe57SMatthew G. Knepley   }
536568d4fef7SMatthew G. Knepley   /* Handle DMPlex refinement */
536661a622f3SMatthew G. Knepley   remap = PETSC_TRUE;
53679566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0));
53689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
53699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0));
53709566063dSJacob Faibussowitsch   if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
537168d4fef7SMatthew G. Knepley   if (refine && isHierarchy) {
5372acdc6f61SToby Isaac     DM *dms, coarseDM;
537368d4fef7SMatthew G. Knepley 
53749566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &coarseDM));
53759566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarseDM));
53769566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(refine, &dms));
53779566063dSJacob Faibussowitsch     PetscCall(DMRefineHierarchy(dm, refine, dms));
537868d4fef7SMatthew G. Knepley     /* Total hack since we do not pass in a pointer */
53799566063dSJacob Faibussowitsch     PetscCall(DMPlexSwap_Static(dm, dms[refine - 1]));
538068d4fef7SMatthew G. Knepley     if (refine == 1) {
53819566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[0]));
53829566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
538368d4fef7SMatthew G. Knepley     } else {
53849566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[refine - 2]));
53859566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
53869566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1]));
53879566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE));
538868d4fef7SMatthew G. Knepley     }
53899566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM));
53909566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coarseDM));
539168d4fef7SMatthew G. Knepley     /* Free DMs */
539268d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
5393dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
53949566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
539568d4fef7SMatthew G. Knepley     }
53969566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
539768d4fef7SMatthew G. Knepley   } else {
539868d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
53999318fe57SMatthew G. Knepley       DM             rdm;
540051a74b61SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
540168d4fef7SMatthew G. Knepley 
5402dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
54039566063dSJacob Faibussowitsch       PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
540468d4fef7SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
540569d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
5406dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
540761a622f3SMatthew G. Knepley       if (coordFunc && remap) {
54089566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
540951a74b61SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
541051a74b61SMatthew G. Knepley       }
541168d4fef7SMatthew G. Knepley     }
541268d4fef7SMatthew G. Knepley   }
54133cf6fe12SMatthew G. Knepley   /* Handle DMPlex coarsening */
54149566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0));
54159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0));
5416b653a561SMatthew G. Knepley   if (coarsen && isHierarchy) {
5417b653a561SMatthew G. Knepley     DM *dms;
5418b653a561SMatthew G. Knepley 
54199566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coarsen, &dms));
54209566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHierarchy(dm, coarsen, dms));
5421b653a561SMatthew G. Knepley     /* Free DMs */
5422b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
5423dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
54249566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
5425b653a561SMatthew G. Knepley     }
54269566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
5427b653a561SMatthew G. Knepley   } else {
5428b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
54299318fe57SMatthew G. Knepley       DM             cdm;
54309318fe57SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
54313cf6fe12SMatthew G. Knepley 
5432dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
54339566063dSJacob Faibussowitsch       PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm));
54343cf6fe12SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
543569d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &cdm));
5436dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
54379318fe57SMatthew G. Knepley       if (coordFunc) {
54389566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
54399318fe57SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
54409318fe57SMatthew G. Knepley       }
54413cf6fe12SMatthew G. Knepley     }
5442b653a561SMatthew G. Knepley   }
5443be664eb1SMatthew G. Knepley   // Handle coordinate remapping
5444be664eb1SMatthew G. Knepley   remap = PETSC_FALSE;
5445be664eb1SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_coord_remap", "Flag to control coordinate remapping", "", remap, &remap, NULL));
5446be664eb1SMatthew G. Knepley   if (remap) {
5447be664eb1SMatthew G. Knepley     DMPlexCoordMap map     = DM_COORD_MAP_NONE;
5448be664eb1SMatthew G. Knepley     PetscPointFunc mapFunc = NULL;
5449be664eb1SMatthew G. Knepley     PetscScalar    params[16];
5450f45b553cSPierre Jolivet     PetscInt       Np = PETSC_STATIC_ARRAY_LENGTH(params), cdim;
5451be664eb1SMatthew G. Knepley     MPI_Comm       comm;
5452be664eb1SMatthew G. Knepley 
5453be664eb1SMatthew G. Knepley     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5454be664eb1SMatthew G. Knepley     PetscCall(DMGetCoordinateDim(dm, &cdim));
5455be664eb1SMatthew G. Knepley     PetscCall(PetscOptionsScalarArray("-dm_coord_map_params", "Parameters for the coordinate remapping", "", params, &Np, &flg));
5456be664eb1SMatthew G. Knepley     if (!flg) Np = 0;
5457be664eb1SMatthew G. Knepley     // TODO Allow user to pass a map function by name
5458be664eb1SMatthew G. Knepley     PetscCall(PetscOptionsEnum("-dm_coord_map", "Coordinate mapping for built-in mesh", "", DMPlexCoordMaps, (PetscEnum)map, (PetscEnum *)&map, &flg));
5459be664eb1SMatthew G. Knepley     if (flg) {
5460be664eb1SMatthew G. Knepley       switch (map) {
5461be664eb1SMatthew G. Knepley       case DM_COORD_MAP_NONE:
5462be664eb1SMatthew G. Knepley         mapFunc = coordMap_identity;
5463be664eb1SMatthew G. Knepley         break;
5464be664eb1SMatthew G. Knepley       case DM_COORD_MAP_SHEAR:
5465be664eb1SMatthew G. Knepley         mapFunc = coordMap_shear;
5466be664eb1SMatthew G. Knepley         if (!Np) {
5467be664eb1SMatthew G. Knepley           Np        = cdim + 1;
5468be664eb1SMatthew G. Knepley           params[0] = 0;
5469be664eb1SMatthew G. Knepley           for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0;
5470be664eb1SMatthew G. Knepley         }
5471be664eb1SMatthew 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);
5472be664eb1SMatthew G. Knepley         break;
5473be664eb1SMatthew G. Knepley       case DM_COORD_MAP_FLARE:
5474be664eb1SMatthew G. Knepley         mapFunc = coordMap_flare;
5475be664eb1SMatthew G. Knepley         if (!Np) {
5476be664eb1SMatthew G. Knepley           Np        = cdim + 1;
5477be664eb1SMatthew G. Knepley           params[0] = 0;
5478be664eb1SMatthew G. Knepley           for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0;
5479be664eb1SMatthew G. Knepley         }
5480be664eb1SMatthew 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);
5481be664eb1SMatthew G. Knepley         break;
5482be664eb1SMatthew G. Knepley       case DM_COORD_MAP_ANNULUS:
5483be664eb1SMatthew G. Knepley         mapFunc = coordMap_annulus;
5484be664eb1SMatthew G. Knepley         if (!Np) {
5485be664eb1SMatthew G. Knepley           Np        = 2;
5486be664eb1SMatthew G. Knepley           params[0] = 1.;
5487be664eb1SMatthew G. Knepley           params[1] = 2.;
5488be664eb1SMatthew G. Knepley         }
5489be664eb1SMatthew G. Knepley         PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The annulus coordinate map must have 2 parameters, not %" PetscInt_FMT, Np);
5490be664eb1SMatthew G. Knepley         break;
5491be664eb1SMatthew G. Knepley       case DM_COORD_MAP_SHELL:
5492be664eb1SMatthew G. Knepley         mapFunc = coordMap_shell;
5493be664eb1SMatthew G. Knepley         if (!Np) {
5494be664eb1SMatthew G. Knepley           Np        = 2;
5495be664eb1SMatthew G. Knepley           params[0] = 1.;
5496be664eb1SMatthew G. Knepley           params[1] = 2.;
5497be664eb1SMatthew G. Knepley         }
5498be664eb1SMatthew G. Knepley         PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The spherical shell coordinate map must have 2 parameters, not %" PetscInt_FMT, Np);
5499be664eb1SMatthew G. Knepley         break;
5500be664eb1SMatthew G. Knepley       default:
5501be664eb1SMatthew G. Knepley         mapFunc = coordMap_identity;
5502be664eb1SMatthew G. Knepley       }
5503be664eb1SMatthew G. Knepley     }
5504be664eb1SMatthew G. Knepley     if (Np) {
5505be664eb1SMatthew G. Knepley       DM      cdm;
5506be664eb1SMatthew G. Knepley       PetscDS cds;
5507be664eb1SMatthew G. Knepley 
5508be664eb1SMatthew G. Knepley       PetscCall(DMGetCoordinateDM(dm, &cdm));
5509be664eb1SMatthew G. Knepley       PetscCall(DMGetDS(cdm, &cds));
5510be664eb1SMatthew G. Knepley       PetscCall(PetscDSSetConstants(cds, Np, params));
5511be664eb1SMatthew G. Knepley     }
5512be664eb1SMatthew G. Knepley     PetscCall(DMPlexRemapGeometry(dm, 0.0, mapFunc));
5513be664eb1SMatthew G. Knepley   }
5514909dfd52SMatthew G. Knepley   /* Handle ghost cells */
55159566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL));
5516909dfd52SMatthew G. Knepley   if (ghostCells) {
5517909dfd52SMatthew G. Knepley     DM   gdm;
5518909dfd52SMatthew G. Knepley     char lname[PETSC_MAX_PATH_LEN];
5519909dfd52SMatthew G. Knepley 
5520909dfd52SMatthew G. Knepley     lname[0] = '\0';
55219566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg));
55229566063dSJacob Faibussowitsch     PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm));
552369d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &gdm));
5524909dfd52SMatthew G. Knepley   }
55256913077dSMatthew G. Knepley   /* Handle 1D order */
5526adc21957SMatthew G. Knepley   if (reorder != DM_REORDER_DEFAULT_FALSE && dim == 1) {
55276913077dSMatthew G. Knepley     DM           cdm, rdm;
55286913077dSMatthew G. Knepley     PetscDS      cds;
55296913077dSMatthew G. Knepley     PetscObject  obj;
55306913077dSMatthew G. Knepley     PetscClassId id = PETSC_OBJECT_CLASSID;
55316913077dSMatthew G. Knepley     IS           perm;
55326bc1bd01Sksagiyam     PetscInt     Nf;
55336913077dSMatthew G. Knepley     PetscBool    distributed;
55346913077dSMatthew G. Knepley 
55359566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(dm, &distributed));
55369566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
55379566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
55389566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(cds, &Nf));
55396913077dSMatthew G. Knepley     if (Nf) {
55409566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
55419566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
55426913077dSMatthew G. Knepley     }
55436bc1bd01Sksagiyam     if (!distributed && id != PETSCFE_CLASSID) {
55449566063dSJacob Faibussowitsch       PetscCall(DMPlexGetOrdering1D(dm, &perm));
55459566063dSJacob Faibussowitsch       PetscCall(DMPlexPermute(dm, perm, &rdm));
554669d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
55479566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&perm));
55486913077dSMatthew G. Knepley     }
55496913077dSMatthew G. Knepley   }
55503cf6fe12SMatthew G. Knepley /* Handle */
5551dd4c3f67SMatthew G. Knepley non_refine:
5552dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
555322d6dc08SStefano Zampini   char    *phases[16];
555422d6dc08SStefano Zampini   PetscInt Nphases = 16;
555522d6dc08SStefano Zampini   PetscCall(PetscOptionsStringArray("-dm_plex_option_phases", "Option phase prefixes", "DMSetFromOptions", phases, &Nphases, &flg));
5556d0609cedSBarry Smith   PetscOptionsHeadEnd();
555722d6dc08SStefano Zampini 
555822d6dc08SStefano Zampini   // Phases
555922d6dc08SStefano Zampini   if (flg) {
556022d6dc08SStefano Zampini     const char *oldPrefix;
556122d6dc08SStefano Zampini 
556222d6dc08SStefano Zampini     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &oldPrefix));
556322d6dc08SStefano Zampini     for (PetscInt ph = 0; ph < Nphases; ++ph) {
556422d6dc08SStefano Zampini       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, phases[ph]));
556522d6dc08SStefano Zampini       PetscCall(PetscInfo(dm, "Options phase %s for DM %s\n", phases[ph], dm->hdr.name));
556622d6dc08SStefano Zampini       PetscCall(DMSetFromOptions(dm));
556722d6dc08SStefano Zampini       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix));
556822d6dc08SStefano Zampini       PetscCall(PetscFree(phases[ph]));
556922d6dc08SStefano Zampini     }
557022d6dc08SStefano Zampini   }
55713ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
55720a6ba040SMatthew G. Knepley }
55730a6ba040SMatthew G. Knepley 
5574d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec)
5575d71ae5a4SJacob Faibussowitsch {
5576552f7358SJed Brown   PetscFunctionBegin;
55779566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector_Section_Private(dm, vec));
55789566063dSJacob Faibussowitsch   /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
55799566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex));
55809566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native));
55819566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex));
55829566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native));
55833ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5584552f7358SJed Brown }
5585552f7358SJed Brown 
5586d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec)
5587d71ae5a4SJacob Faibussowitsch {
5588552f7358SJed Brown   PetscFunctionBegin;
55899566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector_Section_Private(dm, vec));
55909566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local));
55919566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local));
55923ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5593552f7358SJed Brown }
5594552f7358SJed Brown 
5595d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
5596d71ae5a4SJacob Faibussowitsch {
5597793f3fe5SMatthew G. Knepley   PetscInt depth, d;
5598793f3fe5SMatthew G. Knepley 
5599793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
56009566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
5601793f3fe5SMatthew G. Knepley   if (depth == 1) {
56029566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &d));
56039566063dSJacob Faibussowitsch     if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
56049566063dSJacob Faibussowitsch     else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd));
56059371c9d4SSatish Balay     else {
56069371c9d4SSatish Balay       *pStart = 0;
56079371c9d4SSatish Balay       *pEnd   = 0;
56089371c9d4SSatish Balay     }
5609793f3fe5SMatthew G. Knepley   } else {
56109566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
5611793f3fe5SMatthew G. Knepley   }
56123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5613793f3fe5SMatthew G. Knepley }
5614793f3fe5SMatthew G. Knepley 
5615d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
5616d71ae5a4SJacob Faibussowitsch {
5617502a2867SDave May   PetscSF            sf;
56186497c311SBarry Smith   PetscMPIInt        niranks, njranks;
56196497c311SBarry Smith   PetscInt           n;
56200a19bb7dSprj-   const PetscMPIInt *iranks, *jranks;
56210a19bb7dSprj-   DM_Plex           *data = (DM_Plex *)dm->data;
5622502a2867SDave May 
56232f356facSMatthew G. Knepley   PetscFunctionBegin;
56249566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
56250a19bb7dSprj-   if (!data->neighbors) {
56269566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sf));
56279566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL));
56289566063dSJacob Faibussowitsch     PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL));
56299566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors));
56309566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks));
56319566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks));
56320a19bb7dSprj-     n = njranks + niranks;
56339566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1));
56340a19bb7dSprj-     /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */
56359566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(n, data->neighbors));
56360a19bb7dSprj-   }
56370a19bb7dSprj-   if (nranks) *nranks = data->neighbors[0];
56380a19bb7dSprj-   if (ranks) {
56390a19bb7dSprj-     if (data->neighbors[0]) *ranks = data->neighbors + 1;
56400a19bb7dSprj-     else *ranks = NULL;
56410a19bb7dSprj-   }
56423ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5643502a2867SDave May }
5644502a2867SDave May 
56451eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec);
56461eb70e55SToby Isaac 
5647d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm)
5648d71ae5a4SJacob Faibussowitsch {
5649552f7358SJed Brown   PetscFunctionBegin;
5650552f7358SJed Brown   dm->ops->view                      = DMView_Plex;
56512c40f234SMatthew G. Knepley   dm->ops->load                      = DMLoad_Plex;
5652552f7358SJed Brown   dm->ops->setfromoptions            = DMSetFromOptions_Plex;
565338221697SMatthew G. Knepley   dm->ops->clone                     = DMClone_Plex;
5654552f7358SJed Brown   dm->ops->setup                     = DMSetUp_Plex;
56551bb6d2a8SBarry Smith   dm->ops->createlocalsection        = DMCreateLocalSection_Plex;
5656adc21957SMatthew G. Knepley   dm->ops->createsectionpermutation  = DMCreateSectionPermutation_Plex;
565766ad2231SToby Isaac   dm->ops->createdefaultconstraints  = DMCreateDefaultConstraints_Plex;
5658552f7358SJed Brown   dm->ops->createglobalvector        = DMCreateGlobalVector_Plex;
5659552f7358SJed Brown   dm->ops->createlocalvector         = DMCreateLocalVector_Plex;
5660184d77edSJed Brown   dm->ops->getlocaltoglobalmapping   = NULL;
56610298fd71SBarry Smith   dm->ops->createfieldis             = NULL;
5662552f7358SJed Brown   dm->ops->createcoordinatedm        = DMCreateCoordinateDM_Plex;
5663f19dbd58SToby Isaac   dm->ops->createcoordinatefield     = DMCreateCoordinateField_Plex;
56640a6ba040SMatthew G. Knepley   dm->ops->getcoloring               = NULL;
5665552f7358SJed Brown   dm->ops->creatematrix              = DMCreateMatrix_Plex;
5666bceba477SMatthew G. Knepley   dm->ops->createinterpolation       = DMCreateInterpolation_Plex;
5667bd041c0cSMatthew G. Knepley   dm->ops->createmassmatrix          = DMCreateMassMatrix_Plex;
5668b4937a87SMatthew G. Knepley   dm->ops->createmassmatrixlumped    = DMCreateMassMatrixLumped_Plex;
56695a84ad33SLisandro Dalcin   dm->ops->createinjection           = DMCreateInjection_Plex;
5670552f7358SJed Brown   dm->ops->refine                    = DMRefine_Plex;
56710a6ba040SMatthew G. Knepley   dm->ops->coarsen                   = DMCoarsen_Plex;
56720a6ba040SMatthew G. Knepley   dm->ops->refinehierarchy           = DMRefineHierarchy_Plex;
5673b653a561SMatthew G. Knepley   dm->ops->coarsenhierarchy          = DMCoarsenHierarchy_Plex;
5674d410b0cfSMatthew G. Knepley   dm->ops->extrude                   = DMExtrude_Plex;
56750298fd71SBarry Smith   dm->ops->globaltolocalbegin        = NULL;
56760298fd71SBarry Smith   dm->ops->globaltolocalend          = NULL;
56770298fd71SBarry Smith   dm->ops->localtoglobalbegin        = NULL;
56780298fd71SBarry Smith   dm->ops->localtoglobalend          = NULL;
5679552f7358SJed Brown   dm->ops->destroy                   = DMDestroy_Plex;
5680552f7358SJed Brown   dm->ops->createsubdm               = DMCreateSubDM_Plex;
56812adcc780SMatthew G. Knepley   dm->ops->createsuperdm             = DMCreateSuperDM_Plex;
5682793f3fe5SMatthew G. Knepley   dm->ops->getdimpoints              = DMGetDimPoints_Plex;
5683552f7358SJed Brown   dm->ops->locatepoints              = DMLocatePoints_Plex;
56840709b2feSToby Isaac   dm->ops->projectfunctionlocal      = DMProjectFunctionLocal_Plex;
56850709b2feSToby Isaac   dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex;
5686bfc4295aSToby Isaac   dm->ops->projectfieldlocal         = DMProjectFieldLocal_Plex;
56878c6c5593SMatthew G. Knepley   dm->ops->projectfieldlabellocal    = DMProjectFieldLabelLocal_Plex;
5688ece3a9fcSMatthew G. Knepley   dm->ops->projectbdfieldlabellocal  = DMProjectBdFieldLabelLocal_Plex;
56890709b2feSToby Isaac   dm->ops->computel2diff             = DMComputeL2Diff_Plex;
5690b698f381SToby Isaac   dm->ops->computel2gradientdiff     = DMComputeL2GradientDiff_Plex;
56912a16baeaSToby Isaac   dm->ops->computel2fielddiff        = DMComputeL2FieldDiff_Plex;
569228d58a37SPierre Jolivet   dm->ops->getneighbors              = DMGetNeighbors_Plex;
56936c6a6b79SMatthew G. Knepley   dm->ops->getlocalboundingbox       = DMGetLocalBoundingBox_Coordinates;
5694907a3e9cSStefano Zampini   dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_Plex;
5695907a3e9cSStefano Zampini   dm->ops->createddscatters          = DMCreateDomainDecompositionScatters_Plex;
56969566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex));
56976c51210dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex));
56989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex));
56999566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex));
57009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex));
57019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex));
57026bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex));
57036bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex));
5704adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", DMReorderSectionGetDefault_Plex));
5705adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", DMReorderSectionSetDefault_Plex));
5706adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", DMReorderSectionGetType_Plex));
5707adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", DMReorderSectionSetType_Plex));
57089566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex));
5709c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
5710c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex));
5711d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", DMPlexGetUseCeed_Plex));
5712d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", DMPlexSetUseCeed_Plex));
57133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5714552f7358SJed Brown }
5715552f7358SJed Brown 
5716d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm)
5717d71ae5a4SJacob Faibussowitsch {
571863a16f15SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex *)dm->data;
57191fca310dSJames Wright   const PetscSF *face_sfs;
57201fca310dSJames Wright   PetscInt       num_face_sfs;
572163a16f15SMatthew G. Knepley 
572263a16f15SMatthew G. Knepley   PetscFunctionBegin;
572363a16f15SMatthew G. Knepley   mesh->refct++;
572463a16f15SMatthew G. Knepley   (*newdm)->data = mesh;
57251fca310dSJames Wright   PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &face_sfs));
57261fca310dSJames Wright   PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, num_face_sfs, (PetscSF *)face_sfs));
57279566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX));
57289566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(*newdm));
57293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
573063a16f15SMatthew G. Knepley }
573163a16f15SMatthew G. Knepley 
57328818961aSMatthew G Knepley /*MC
57330b4b7b1cSBarry Smith   DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh (or grid), or CW Complex {cite}`cwcomplex`,
57340b4b7b1cSBarry Smith            which can be expressed using a Hasse Diagram {cite}`hassediagram`.
573520f4b53cSBarry Smith            In the local representation, `Vec`s contain all unknowns in the interior and shared boundary. This is
57360b4b7b1cSBarry Smith            specified by a `PetscSection` object. Ownership in the global representation is determined by
5737a1cb98faSBarry Smith            ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object.
57388818961aSMatthew G Knepley 
5739e5893cccSMatthew G. Knepley   Options Database Keys:
5740250712c9SMatthew G. Knepley + -dm_refine_pre                     - Refine mesh before distribution
5741250712c9SMatthew G. Knepley + -dm_refine_uniform_pre             - Choose uniform or generator-based refinement
5742250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre        - Cell volume limit after pre-refinement using generator
5743250712c9SMatthew G. Knepley . -dm_distribute                     - Distribute mesh across processes
5744250712c9SMatthew G. Knepley . -dm_distribute_overlap             - Number of cells to overlap for distribution
5745250712c9SMatthew G. Knepley . -dm_refine                         - Refine mesh after distribution
5746c3db174cSMatthew G. Knepley . -dm_localize <bool>                - Whether to localize coordinates for periodic meshes
5747c3db174cSMatthew G. Knepley . -dm_sparse_localize <bool>         - Whether to only localize cells on the periodic boundary
5748250712c9SMatthew G. Knepley . -dm_plex_hash_location             - Use grid hashing for point location
5749ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p>    - The number of divisions in each direction of the grid hash
5750f12cf164SMatthew G. Knepley . -dm_plex_partition_balance         - Attempt to evenly divide points on partition boundary between processes
5751f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd                 - Allow changes to the boundary on remeshing
5752d5b43468SJose E. Roman . -dm_plex_max_projection_height     - Maximum mesh point height used to project locally
5753f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement        - Use special nested projection algorithm for regular refinement
5754d02c7345SMatthew G. Knepley . -dm_plex_reorder_section           - Use specialized blocking if available
5755aaa8cc7dSPierre Jolivet . -dm_plex_check_all                 - Perform all checks below
5756f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry            - Check that the adjacency information in the mesh is symmetric
5757f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices
5758f12cf164SMatthew 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
5759f12cf164SMatthew G. Knepley . -dm_plex_check_geometry            - Check that cells have positive volume
5760f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex     - View the mesh in LaTeX/TikZ
5761e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num>          - Scale the TikZ
57625962854dSMatthew G. Knepley . -dm_plex_print_fem <num>           - View FEM assembly information, such as element vectors and matrices
57635962854dSMatthew G. Knepley - -dm_plex_print_fvm <num>           - View FVM assembly information, such as flux updates
5764e5893cccSMatthew G. Knepley 
57658818961aSMatthew G Knepley   Level: intermediate
57668818961aSMatthew G Knepley 
57671cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection`
57688818961aSMatthew G Knepley M*/
57698818961aSMatthew G Knepley 
5770d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
5771d71ae5a4SJacob Faibussowitsch {
5772552f7358SJed Brown   DM_Plex *mesh;
5773412e9a14SMatthew G. Knepley   PetscInt unit;
5774552f7358SJed Brown 
5775552f7358SJed Brown   PetscFunctionBegin;
5776f39ec787SMatthew G. Knepley   PetscCall(PetscCitationsRegister(PlexCitation, &Plexcite));
5777552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
57784dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&mesh));
5779adc21957SMatthew G. Knepley   dm->reorderSection = DM_REORDER_DEFAULT_NOTSET;
5780552f7358SJed Brown   dm->data           = mesh;
5781552f7358SJed Brown 
5782552f7358SJed Brown   mesh->refct = 1;
57839566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection));
57849566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection));
5785552f7358SJed Brown   mesh->refinementUniform       = PETSC_TRUE;
5786552f7358SJed Brown   mesh->refinementLimit         = -1.0;
5787e600fa54SMatthew G. Knepley   mesh->distDefault             = PETSC_TRUE;
5788adc21957SMatthew G. Knepley   mesh->reorderDefault          = DM_REORDER_DEFAULT_NOTSET;
57891d1f2f2aSksagiyam   mesh->distributionName        = NULL;
57907d0f5628SVaclav Hapla   mesh->interpolated            = DMPLEX_INTERPOLATED_INVALID;
57917d0f5628SVaclav Hapla   mesh->interpolatedCollective  = DMPLEX_INTERPOLATED_INVALID;
57925e2c5519SMatthew G. Knepley   mesh->interpolatePreferTensor = PETSC_TRUE;
5793552f7358SJed Brown 
57949566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner));
57952e62ab5aSMatthew G. Knepley   mesh->remeshBd = PETSC_FALSE;
5796d9deefdfSMatthew G. Knepley 
57978865f1eaSKarl Rupp   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
5798552f7358SJed Brown 
5799df0420ecSMatthew G. Knepley   mesh->depthState    = -1;
5800ba2698f1SMatthew G. Knepley   mesh->celltypeState = -1;
58016113b454SMatthew G. Knepley   mesh->printTol      = 1.0e-10;
5802c29ce622SStefano Zampini   mesh->nonempty_comm = MPI_COMM_SELF;
5803552f7358SJed Brown 
58049566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
58053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5806552f7358SJed Brown }
5807552f7358SJed Brown 
5808552f7358SJed Brown /*@
5809a1cb98faSBarry Smith   DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
5810552f7358SJed Brown 
5811d083f849SBarry Smith   Collective
5812552f7358SJed Brown 
5813552f7358SJed Brown   Input Parameter:
5814a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object
5815552f7358SJed Brown 
5816552f7358SJed Brown   Output Parameter:
5817a1cb98faSBarry Smith . mesh - The `DMPLEX` object
5818552f7358SJed Brown 
5819552f7358SJed Brown   Level: beginner
5820552f7358SJed Brown 
582142747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMCreate()`, `DMSetType()`
5822552f7358SJed Brown @*/
5823d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
5824d71ae5a4SJacob Faibussowitsch {
5825552f7358SJed Brown   PetscFunctionBegin;
58264f572ea9SToby Isaac   PetscAssertPointer(mesh, 2);
58279566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, mesh));
58289566063dSJacob Faibussowitsch   PetscCall(DMSetType(*mesh, DMPLEX));
58293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5830552f7358SJed Brown }
5831552f7358SJed Brown 
5832b09969d6SVaclav Hapla /*@C
5833b0fe842aSMatthew 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
5834a1cb98faSBarry Smith 
583520f4b53cSBarry Smith   Collective; No Fortran Support
5836b09969d6SVaclav Hapla 
5837b09969d6SVaclav Hapla   Input Parameters:
5838a1cb98faSBarry Smith + dm          - The `DM`
5839b09969d6SVaclav Hapla . numCells    - The number of cells owned by this process
5840a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
5841a1cb98faSBarry Smith . NVertices   - The global number of vertices, or `PETSC_DETERMINE`
5842b09969d6SVaclav Hapla . numCorners  - The number of vertices for each cell
58435e488331SVaclav Hapla - cells       - An array of numCells*numCorners numbers, the global vertex numbers for each cell
5844b09969d6SVaclav Hapla 
5845be8c289dSNicolas Barral   Output Parameters:
5846a1cb98faSBarry Smith + vertexSF         - (Optional) `PetscSF` describing complete vertex ownership
5847be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
5848b09969d6SVaclav Hapla 
5849b09969d6SVaclav Hapla   Level: advanced
5850b09969d6SVaclav Hapla 
5851a1cb98faSBarry Smith   Notes:
5852a1cb98faSBarry Smith   Two triangles sharing a face
5853a1cb98faSBarry Smith .vb
5854a1cb98faSBarry Smith 
5855a1cb98faSBarry Smith         2
5856a1cb98faSBarry Smith       / | \
5857a1cb98faSBarry Smith      /  |  \
5858a1cb98faSBarry Smith     /   |   \
5859a1cb98faSBarry Smith    0  0 | 1  3
5860a1cb98faSBarry Smith     \   |   /
5861a1cb98faSBarry Smith      \  |  /
5862a1cb98faSBarry Smith       \ | /
5863a1cb98faSBarry Smith         1
5864a1cb98faSBarry Smith .ve
5865a1cb98faSBarry Smith   would have input
5866a1cb98faSBarry Smith .vb
5867a1cb98faSBarry Smith   numCells = 2, numVertices = 4
5868a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
5869a1cb98faSBarry Smith .ve
5870a1cb98faSBarry Smith   which would result in the `DMPLEX`
5871a1cb98faSBarry Smith .vb
5872a1cb98faSBarry Smith 
5873a1cb98faSBarry Smith         4
5874a1cb98faSBarry Smith       / | \
5875a1cb98faSBarry Smith      /  |  \
5876a1cb98faSBarry Smith     /   |   \
5877a1cb98faSBarry Smith    2  0 | 1  5
5878a1cb98faSBarry Smith     \   |   /
5879a1cb98faSBarry Smith      \  |  /
5880a1cb98faSBarry Smith       \ | /
5881a1cb98faSBarry Smith         3
5882a1cb98faSBarry Smith .ve
5883a1cb98faSBarry Smith 
5884a1cb98faSBarry Smith   Vertices are implicitly numbered consecutively 0,...,NVertices.
5885a1cb98faSBarry Smith   Each rank owns a chunk of numVertices consecutive vertices.
5886a1cb98faSBarry Smith   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
5887a1cb98faSBarry Smith   If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
5888a1cb98faSBarry Smith   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
5889a1cb98faSBarry Smith 
5890a1cb98faSBarry Smith   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
5891a1cb98faSBarry Smith 
58921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
5893a1cb98faSBarry Smith           `PetscSF`
5894b09969d6SVaclav Hapla @*/
5895ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[])
5896d71ae5a4SJacob Faibussowitsch {
58972464107aSksagiyam   PetscSF     sfPoint;
58982464107aSksagiyam   PetscLayout layout;
589982fb893eSVaclav Hapla   PetscInt    numVerticesAdj, *verticesAdj, *cones, c, p;
5900a47d0d45SMatthew G. Knepley 
5901a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
590225b6865aSVaclav Hapla   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
59039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
590425b6865aSVaclav Hapla   /* Get/check global number of vertices */
590525b6865aSVaclav Hapla   {
590625b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
590725b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
590825b6865aSVaclav Hapla 
590925b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
59101690c2aeSBarry Smith     NVerticesInCells = PETSC_INT_MIN;
59119371c9d4SSatish Balay     for (i = 0; i < len; i++)
59129371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
591325b6865aSVaclav Hapla     ++NVerticesInCells;
5914462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
591525b6865aSVaclav Hapla 
591625b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
59179371c9d4SSatish Balay     else
59189371c9d4SSatish 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);
591925b6865aSVaclav Hapla   }
59209079aca8SVaclav Hapla   /* Count locally unique vertices */
59219079aca8SVaclav Hapla   {
59229079aca8SVaclav Hapla     PetscHSetI vhash;
59239079aca8SVaclav Hapla     PetscInt   off = 0;
59249079aca8SVaclav Hapla 
59259566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&vhash));
5926a47d0d45SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
592748a46eb9SPierre Jolivet       for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p]));
5928a47d0d45SMatthew G. Knepley     }
59299566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
59309566063dSJacob Faibussowitsch     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
5931ad540459SPierre Jolivet     else verticesAdj = *verticesAdjSaved;
59329566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
59339566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&vhash));
593463a3b9bcSJacob Faibussowitsch     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
5935a47d0d45SMatthew G. Knepley   }
59369566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
5937a47d0d45SMatthew G. Knepley   /* Create cones */
59389566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
59399566063dSJacob Faibussowitsch   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
59409566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
59419566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
5942a47d0d45SMatthew G. Knepley   for (c = 0; c < numCells; ++c) {
5943a47d0d45SMatthew G. Knepley     for (p = 0; p < numCorners; ++p) {
5944a47d0d45SMatthew G. Knepley       const PetscInt gv = cells[c * numCorners + p];
5945a47d0d45SMatthew G. Knepley       PetscInt       lv;
5946a47d0d45SMatthew G. Knepley 
59479079aca8SVaclav Hapla       /* Positions within verticesAdj form 0-based local vertex numbering;
59489079aca8SVaclav Hapla          we need to shift it by numCells to get correct DAG points (cells go first) */
59499566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
595063a3b9bcSJacob Faibussowitsch       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
5951961cfab0SVaclav Hapla       cones[c * numCorners + p] = lv + numCells;
5952a47d0d45SMatthew G. Knepley     }
5953a47d0d45SMatthew G. Knepley   }
59542464107aSksagiyam   /* Build point sf */
59559566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
59569566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(layout, NVertices));
59579566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
59589566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
59599566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
59609566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
59619566063dSJacob Faibussowitsch   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
59629566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
59632464107aSksagiyam   if (dm->sf) {
59642464107aSksagiyam     const char *prefix;
59652464107aSksagiyam 
59669566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
59679566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
59682464107aSksagiyam   }
59699566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sfPoint));
59709566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfPoint));
5971f4f49eeaSPierre Jolivet   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF"));
5972a47d0d45SMatthew G. Knepley   /* Fill in the rest of the topology structure */
59739566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
59749566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
59759566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
59763ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5977a47d0d45SMatthew G. Knepley }
5978a47d0d45SMatthew G. Knepley 
5979b0fe842aSMatthew G. Knepley /*@C
5980b0fe842aSMatthew G. Knepley   DMPlexBuildFromCellSectionParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) allowing multiple celltypes
5981b0fe842aSMatthew G. Knepley 
5982b0fe842aSMatthew G. Knepley   Collective; No Fortran Support
5983b0fe842aSMatthew G. Knepley 
5984b0fe842aSMatthew G. Knepley   Input Parameters:
5985b0fe842aSMatthew G. Knepley + dm          - The `DM`
5986b0fe842aSMatthew G. Knepley . numCells    - The number of cells owned by this process
5987b0fe842aSMatthew G. Knepley . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
5988b0fe842aSMatthew G. Knepley . NVertices   - The global number of vertices, or `PETSC_DETERMINE`
5989b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells)
5990b0fe842aSMatthew G. Knepley - cells       - An array of the global vertex numbers for each cell
5991b0fe842aSMatthew G. Knepley 
5992b0fe842aSMatthew G. Knepley   Output Parameters:
5993b0fe842aSMatthew G. Knepley + vertexSF         - (Optional) `PetscSF` describing complete vertex ownership
5994b0fe842aSMatthew G. Knepley - verticesAdjSaved - (Optional) vertex adjacency array
5995b0fe842aSMatthew G. Knepley 
5996b0fe842aSMatthew G. Knepley   Level: advanced
5997b0fe842aSMatthew G. Knepley 
5998b0fe842aSMatthew G. Knepley   Notes:
5999b0fe842aSMatthew G. Knepley   A triangle and quadrilateral sharing a face
6000b0fe842aSMatthew G. Knepley .vb
6001b0fe842aSMatthew G. Knepley         2----------3
6002b0fe842aSMatthew G. Knepley       / |          |
6003b0fe842aSMatthew G. Knepley      /  |          |
6004b0fe842aSMatthew G. Knepley     /   |          |
6005b0fe842aSMatthew G. Knepley    0  0 |     1    |
6006b0fe842aSMatthew G. Knepley     \   |          |
6007b0fe842aSMatthew G. Knepley      \  |          |
6008b0fe842aSMatthew G. Knepley       \ |          |
6009b0fe842aSMatthew G. Knepley         1----------4
6010b0fe842aSMatthew G. Knepley .ve
6011b0fe842aSMatthew G. Knepley   would have input
6012b0fe842aSMatthew G. Knepley .vb
6013b0fe842aSMatthew G. Knepley   numCells = 2, numVertices = 5
6014b0fe842aSMatthew G. Knepley   cells = [0 1 2  1 4 3 2]
6015b0fe842aSMatthew G. Knepley .ve
6016b0fe842aSMatthew G. Knepley   which would result in the `DMPLEX`
6017b0fe842aSMatthew G. Knepley .vb
6018b0fe842aSMatthew G. Knepley         4----------5
6019b0fe842aSMatthew G. Knepley       / |          |
6020b0fe842aSMatthew G. Knepley      /  |          |
6021b0fe842aSMatthew G. Knepley     /   |          |
6022b0fe842aSMatthew G. Knepley    2  0 |     1    |
6023b0fe842aSMatthew G. Knepley     \   |          |
6024b0fe842aSMatthew G. Knepley      \  |          |
6025b0fe842aSMatthew G. Knepley       \ |          |
6026b0fe842aSMatthew G. Knepley         3----------6
6027b0fe842aSMatthew G. Knepley .ve
6028b0fe842aSMatthew G. Knepley 
6029b0fe842aSMatthew G. Knepley   Vertices are implicitly numbered consecutively 0,...,NVertices.
6030b0fe842aSMatthew G. Knepley   Each rank owns a chunk of numVertices consecutive vertices.
6031b0fe842aSMatthew G. Knepley   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
6032b0fe842aSMatthew 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.
6033b0fe842aSMatthew G. Knepley   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
6034b0fe842aSMatthew G. Knepley 
6035b0fe842aSMatthew G. Knepley   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
6036b0fe842aSMatthew G. Knepley 
6037b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexCreateFromCellSectionParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
6038b0fe842aSMatthew G. Knepley           `PetscSF`
6039b0fe842aSMatthew G. Knepley @*/
6040ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellSectionParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[])
6041b0fe842aSMatthew G. Knepley {
6042b0fe842aSMatthew G. Knepley   PetscSF     sfPoint;
6043b0fe842aSMatthew G. Knepley   PetscLayout layout;
6044b0fe842aSMatthew G. Knepley   PetscInt    numVerticesAdj, *verticesAdj, *cones, cStart, cEnd, len;
6045b0fe842aSMatthew G. Knepley 
6046b0fe842aSMatthew G. Knepley   PetscFunctionBegin;
6047b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
6048b0fe842aSMatthew G. Knepley   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
6049b0fe842aSMatthew G. Knepley   PetscCall(PetscSectionGetChart(cellSection, &cStart, &cEnd));
6050b0fe842aSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(cellSection, &len));
6051b0fe842aSMatthew 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);
6052b0fe842aSMatthew G. Knepley   /* Get/check global number of vertices */
6053b0fe842aSMatthew G. Knepley   {
6054b0fe842aSMatthew G. Knepley     PetscInt NVerticesInCells;
6055b0fe842aSMatthew G. Knepley 
6056b0fe842aSMatthew G. Knepley     /* NVerticesInCells = max(cells) + 1 */
6057b0fe842aSMatthew G. Knepley     NVerticesInCells = PETSC_MIN_INT;
6058b0fe842aSMatthew G. Knepley     for (PetscInt i = 0; i < len; i++)
6059b0fe842aSMatthew G. Knepley       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
6060b0fe842aSMatthew G. Knepley     ++NVerticesInCells;
6061b0fe842aSMatthew G. Knepley     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
6062b0fe842aSMatthew G. Knepley 
6063b0fe842aSMatthew G. Knepley     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
6064b0fe842aSMatthew G. Knepley     else
6065b0fe842aSMatthew 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);
6066b0fe842aSMatthew G. Knepley   }
6067b0fe842aSMatthew G. Knepley   /* Count locally unique vertices */
6068b0fe842aSMatthew G. Knepley   {
6069b0fe842aSMatthew G. Knepley     PetscHSetI vhash;
6070b0fe842aSMatthew G. Knepley     PetscInt   off = 0;
6071b0fe842aSMatthew G. Knepley 
6072b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetICreate(&vhash));
6073b0fe842aSMatthew G. Knepley     for (PetscInt i = 0; i < len; i++) PetscCall(PetscHSetIAdd(vhash, cells[i]));
6074b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
6075b0fe842aSMatthew G. Knepley     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
6076b0fe842aSMatthew G. Knepley     else verticesAdj = *verticesAdjSaved;
6077b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
6078b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIDestroy(&vhash));
6079b0fe842aSMatthew 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);
6080b0fe842aSMatthew G. Knepley   }
6081b0fe842aSMatthew G. Knepley   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
6082b0fe842aSMatthew G. Knepley   /* Create cones */
6083b0fe842aSMatthew G. Knepley   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
6084b0fe842aSMatthew G. Knepley   for (PetscInt c = 0; c < numCells; ++c) {
6085b0fe842aSMatthew G. Knepley     PetscInt dof;
6086b0fe842aSMatthew G. Knepley 
6087b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetDof(cellSection, c, &dof));
6088b0fe842aSMatthew G. Knepley     PetscCall(DMPlexSetConeSize(dm, c, dof));
6089b0fe842aSMatthew G. Knepley   }
6090b0fe842aSMatthew G. Knepley   PetscCall(DMSetUp(dm));
6091b0fe842aSMatthew G. Knepley   PetscCall(DMPlexGetCones(dm, &cones));
6092b0fe842aSMatthew G. Knepley   for (PetscInt c = 0; c < numCells; ++c) {
6093b0fe842aSMatthew G. Knepley     PetscInt dof, off;
6094b0fe842aSMatthew G. Knepley 
6095b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetDof(cellSection, c, &dof));
6096b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetOffset(cellSection, c, &off));
6097b0fe842aSMatthew G. Knepley     for (PetscInt p = off; p < off + dof; ++p) {
6098b0fe842aSMatthew G. Knepley       const PetscInt gv = cells[p];
6099b0fe842aSMatthew G. Knepley       PetscInt       lv;
6100b0fe842aSMatthew G. Knepley 
6101b0fe842aSMatthew G. Knepley       /* Positions within verticesAdj form 0-based local vertex numbering;
6102b0fe842aSMatthew G. Knepley          we need to shift it by numCells to get correct DAG points (cells go first) */
6103b0fe842aSMatthew G. Knepley       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
6104b0fe842aSMatthew G. Knepley       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
6105b0fe842aSMatthew G. Knepley       cones[p] = lv + numCells;
6106b0fe842aSMatthew G. Knepley     }
6107b0fe842aSMatthew G. Knepley   }
6108b0fe842aSMatthew G. Knepley   /* Build point sf */
6109b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
6110b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetSize(layout, NVertices));
6111b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
6112b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetBlockSize(layout, 1));
6113b0fe842aSMatthew G. Knepley   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
6114b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutDestroy(&layout));
6115b0fe842aSMatthew G. Knepley   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
6116b0fe842aSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
6117b0fe842aSMatthew G. Knepley   if (dm->sf) {
6118b0fe842aSMatthew G. Knepley     const char *prefix;
6119b0fe842aSMatthew G. Knepley 
6120b0fe842aSMatthew G. Knepley     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
6121b0fe842aSMatthew G. Knepley     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
6122b0fe842aSMatthew G. Knepley   }
6123b0fe842aSMatthew G. Knepley   PetscCall(DMSetPointSF(dm, sfPoint));
6124b0fe842aSMatthew G. Knepley   PetscCall(PetscSFDestroy(&sfPoint));
6125b0fe842aSMatthew G. Knepley   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF"));
6126b0fe842aSMatthew G. Knepley   /* Fill in the rest of the topology structure */
6127b0fe842aSMatthew G. Knepley   PetscCall(DMPlexSymmetrize(dm));
6128b0fe842aSMatthew G. Knepley   PetscCall(DMPlexStratify(dm));
6129b0fe842aSMatthew G. Knepley   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
6130b0fe842aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
6131b0fe842aSMatthew G. Knepley }
6132b0fe842aSMatthew G. Knepley 
6133cc4c1da9SBarry Smith /*@
6134a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
6135a1cb98faSBarry Smith 
613620f4b53cSBarry Smith   Collective; No Fortran Support
6137b09969d6SVaclav Hapla 
6138b09969d6SVaclav Hapla   Input Parameters:
6139a1cb98faSBarry Smith + dm           - The `DM`
6140b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
6141a1cb98faSBarry Smith . sfVert       - `PetscSF` describing complete vertex ownership
6142b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6143b09969d6SVaclav Hapla 
6144b09969d6SVaclav Hapla   Level: advanced
6145b09969d6SVaclav Hapla 
61461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()`
6147b09969d6SVaclav Hapla @*/
6148d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[])
6149d71ae5a4SJacob Faibussowitsch {
6150a47d0d45SMatthew G. Knepley   PetscSection coordSection;
6151a47d0d45SMatthew G. Knepley   Vec          coordinates;
6152a47d0d45SMatthew G. Knepley   PetscScalar *coords;
61531edcf0b2SVaclav Hapla   PetscInt     numVertices, numVerticesAdj, coordSize, v, vStart, vEnd;
6154835f2295SStefano Zampini   PetscMPIInt  spaceDimi;
6155a47d0d45SMatthew G. Knepley 
6156a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
61579566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
61589566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
61591dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
61609566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
61619566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL));
61621dca8a05SBarry 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);
61639566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
61649566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
61659566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
61669566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
61671edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
61689566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
61699566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
6170a47d0d45SMatthew G. Knepley   }
61719566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
61729566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
61739566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
61749566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
61759566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
61769566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
61779566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
61789566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
6179a47d0d45SMatthew G. Knepley   {
6180a47d0d45SMatthew G. Knepley     MPI_Datatype coordtype;
6181a47d0d45SMatthew G. Knepley 
6182a47d0d45SMatthew G. Knepley     /* Need a temp buffer for coords if we have complex/single */
6183835f2295SStefano Zampini     PetscCall(PetscMPIIntCast(spaceDim, &spaceDimi));
6184835f2295SStefano Zampini     PetscCallMPI(MPI_Type_contiguous(spaceDimi, MPIU_SCALAR, &coordtype));
61859566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&coordtype));
618621016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX)
618721016a8bSBarry Smith     {
618821016a8bSBarry Smith       PetscScalar *svertexCoords;
618921016a8bSBarry Smith       PetscInt     i;
61909566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords));
61913612f820SVaclav Hapla       for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i];
61929566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
61939566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
61949566063dSJacob Faibussowitsch       PetscCall(PetscFree(svertexCoords));
619521016a8bSBarry Smith     }
619621016a8bSBarry Smith #else
61979566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
61989566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
619921016a8bSBarry Smith #endif
62009566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&coordtype));
6201a47d0d45SMatthew G. Knepley   }
62029566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
62039566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
62049566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
62059566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
62063ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6207a47d0d45SMatthew G. Knepley }
6208a47d0d45SMatthew G. Knepley 
6209c3edce3dSSatish Balay /*@
6210b0fe842aSMatthew 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
6211a1cb98faSBarry Smith 
6212a1cb98faSBarry Smith   Collective
6213a47d0d45SMatthew G. Knepley 
6214a47d0d45SMatthew G. Knepley   Input Parameters:
6215a47d0d45SMatthew G. Knepley + comm         - The communicator
6216a47d0d45SMatthew G. Knepley . dim          - The topological dimension of the mesh
6217a47d0d45SMatthew G. Knepley . numCells     - The number of cells owned by this process
6218a1cb98faSBarry Smith . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`
6219a1cb98faSBarry Smith . NVertices    - The global number of vertices, or `PETSC_DECIDE`
6220a47d0d45SMatthew G. Knepley . numCorners   - The number of vertices for each cell
6221a47d0d45SMatthew G. Knepley . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
6222a47d0d45SMatthew G. Knepley . cells        - An array of numCells*numCorners numbers, the global vertex numbers for each cell
6223a47d0d45SMatthew G. Knepley . spaceDim     - The spatial dimension used for coordinates
6224a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6225a47d0d45SMatthew G. Knepley 
6226d8d19677SJose E. Roman   Output Parameters:
6227a1cb98faSBarry Smith + dm          - The `DM`
6228a1cb98faSBarry Smith . vertexSF    - (Optional) `PetscSF` describing complete vertex ownership
622960225df5SJacob Faibussowitsch - verticesAdj - (Optional) vertex adjacency array
6230a47d0d45SMatthew G. Knepley 
6231b09969d6SVaclav Hapla   Level: intermediate
6232a47d0d45SMatthew G. Knepley 
6233a1cb98faSBarry Smith   Notes:
6234a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
6235a1cb98faSBarry Smith   `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
6236a1cb98faSBarry Smith 
6237a1cb98faSBarry Smith   See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters.
6238a1cb98faSBarry Smith 
6239a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
6240a1cb98faSBarry Smith 
62411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
6242a47d0d45SMatthew G. Knepley @*/
6243ce78bad3SBarry 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)
6244d71ae5a4SJacob Faibussowitsch {
6245a47d0d45SMatthew G. Knepley   PetscSF sfVert;
6246a47d0d45SMatthew G. Knepley 
6247a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
62489566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
62499566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
6250a47d0d45SMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
6251064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
62529566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
62539566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj));
6254a47d0d45SMatthew G. Knepley   if (interpolate) {
62555fd9971aSMatthew G. Knepley     DM idm;
6256a47d0d45SMatthew G. Knepley 
62579566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
62589566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
6259a47d0d45SMatthew G. Knepley     *dm = idm;
6260a47d0d45SMatthew G. Knepley   }
62619566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
626218d54ad4SMichael Lange   if (vertexSF) *vertexSF = sfVert;
62639566063dSJacob Faibussowitsch   else PetscCall(PetscSFDestroy(&sfVert));
62643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6265a47d0d45SMatthew G. Knepley }
6266a47d0d45SMatthew G. Knepley 
6267cc4c1da9SBarry Smith /*@
6268b0fe842aSMatthew G. Knepley   DMPlexCreateFromCellSectionParallel - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) and supports multiple celltypes
6269b0fe842aSMatthew G. Knepley 
6270b0fe842aSMatthew G. Knepley   Collective
6271b0fe842aSMatthew G. Knepley 
6272b0fe842aSMatthew G. Knepley   Input Parameters:
6273b0fe842aSMatthew G. Knepley + comm         - The communicator
6274b0fe842aSMatthew G. Knepley . dim          - The topological dimension of the mesh
6275b0fe842aSMatthew G. Knepley . numCells     - The number of cells owned by this process
6276b0fe842aSMatthew G. Knepley . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`
6277b0fe842aSMatthew G. Knepley . NVertices    - The global number of vertices, or `PETSC_DECIDE`
6278b0fe842aSMatthew G. Knepley . cellSection  - The `PetscSection` giving the number of vertices for each cell (layout of cells)
6279b0fe842aSMatthew G. Knepley . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
6280b0fe842aSMatthew G. Knepley . cells        - An array of the global vertex numbers for each cell
6281b0fe842aSMatthew G. Knepley . spaceDim     - The spatial dimension used for coordinates
6282b0fe842aSMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6283b0fe842aSMatthew G. Knepley 
6284b0fe842aSMatthew G. Knepley   Output Parameters:
6285b0fe842aSMatthew G. Knepley + dm          - The `DM`
6286b0fe842aSMatthew G. Knepley . vertexSF    - (Optional) `PetscSF` describing complete vertex ownership
6287b0fe842aSMatthew G. Knepley - verticesAdj - (Optional) vertex adjacency array
6288b0fe842aSMatthew G. Knepley 
6289b0fe842aSMatthew G. Knepley   Level: intermediate
6290b0fe842aSMatthew G. Knepley 
6291b0fe842aSMatthew G. Knepley   Notes:
6292b0fe842aSMatthew G. Knepley   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
6293b0fe842aSMatthew G. Knepley   `DMPlexBuildFromCellSectionParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
6294b0fe842aSMatthew G. Knepley 
6295b0fe842aSMatthew G. Knepley   See `DMPlexBuildFromCellSectionParallel()` for an example and details about the topology-related parameters.
6296b0fe842aSMatthew G. Knepley 
6297b0fe842aSMatthew G. Knepley   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
6298b0fe842aSMatthew G. Knepley 
6299b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
6300b0fe842aSMatthew G. Knepley @*/
6301ce78bad3SBarry 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)
6302b0fe842aSMatthew G. Knepley {
6303b0fe842aSMatthew G. Knepley   PetscSF sfVert;
6304b0fe842aSMatthew G. Knepley 
6305b0fe842aSMatthew G. Knepley   PetscFunctionBegin;
6306b0fe842aSMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
6307b0fe842aSMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
6308b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
6309b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
6310b0fe842aSMatthew G. Knepley   PetscCall(DMSetDimension(*dm, dim));
6311b0fe842aSMatthew G. Knepley   PetscCall(DMPlexBuildFromCellSectionParallel(*dm, numCells, numVertices, NVertices, cellSection, cells, &sfVert, verticesAdj));
6312b0fe842aSMatthew G. Knepley   if (interpolate) {
6313b0fe842aSMatthew G. Knepley     DM idm;
6314b0fe842aSMatthew G. Knepley 
6315b0fe842aSMatthew G. Knepley     PetscCall(DMPlexInterpolate(*dm, &idm));
6316b0fe842aSMatthew G. Knepley     PetscCall(DMDestroy(dm));
6317b0fe842aSMatthew G. Knepley     *dm = idm;
6318b0fe842aSMatthew G. Knepley   }
6319b0fe842aSMatthew G. Knepley   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
6320b0fe842aSMatthew G. Knepley   if (vertexSF) *vertexSF = sfVert;
6321b0fe842aSMatthew G. Knepley   else PetscCall(PetscSFDestroy(&sfVert));
6322b0fe842aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
6323b0fe842aSMatthew G. Knepley }
6324b0fe842aSMatthew G. Knepley 
6325b0fe842aSMatthew G. Knepley /*@
6326a1cb98faSBarry Smith   DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output)
6327a1cb98faSBarry Smith 
632820f4b53cSBarry Smith   Collective; No Fortran Support
63299298eaa6SMatthew G Knepley 
63309298eaa6SMatthew G Knepley   Input Parameters:
6331a1cb98faSBarry Smith + dm          - The `DM`
6332b09969d6SVaclav Hapla . numCells    - The number of cells owned by this process
6333a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE`
63349298eaa6SMatthew G Knepley . numCorners  - The number of vertices for each cell
6335a3b724e8SBarry Smith - cells       - An array of `numCells` x `numCorners` numbers, the global vertex numbers for each cell
63369298eaa6SMatthew G Knepley 
6337b09969d6SVaclav Hapla   Level: advanced
63389298eaa6SMatthew G Knepley 
6339b09969d6SVaclav Hapla   Notes:
6340b09969d6SVaclav Hapla   Two triangles sharing a face
6341a1cb98faSBarry Smith .vb
63429298eaa6SMatthew G Knepley 
6343a1cb98faSBarry Smith         2
6344a1cb98faSBarry Smith       / | \
6345a1cb98faSBarry Smith      /  |  \
6346a1cb98faSBarry Smith     /   |   \
6347a1cb98faSBarry Smith    0  0 | 1  3
6348a1cb98faSBarry Smith     \   |   /
6349a1cb98faSBarry Smith      \  |  /
6350a1cb98faSBarry Smith       \ | /
6351a1cb98faSBarry Smith         1
6352a1cb98faSBarry Smith .ve
6353a1cb98faSBarry Smith   would have input
6354a1cb98faSBarry Smith .vb
6355a1cb98faSBarry Smith   numCells = 2, numVertices = 4
6356a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
6357a1cb98faSBarry Smith .ve
6358a1cb98faSBarry Smith   which would result in the `DMPLEX`
6359a1cb98faSBarry Smith .vb
6360a1cb98faSBarry Smith 
6361a1cb98faSBarry Smith         4
6362a1cb98faSBarry Smith       / | \
6363a1cb98faSBarry Smith      /  |  \
6364a1cb98faSBarry Smith     /   |   \
6365a1cb98faSBarry Smith    2  0 | 1  5
6366a1cb98faSBarry Smith     \   |   /
6367a1cb98faSBarry Smith      \  |  /
6368a1cb98faSBarry Smith       \ | /
6369a1cb98faSBarry Smith         3
6370a1cb98faSBarry Smith .ve
6371a1cb98faSBarry Smith 
6372a1cb98faSBarry Smith   If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1.
637325b6865aSVaclav Hapla 
63741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()`
6375b09969d6SVaclav Hapla @*/
6376d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[])
6377d71ae5a4SJacob Faibussowitsch {
6378961cfab0SVaclav Hapla   PetscInt *cones, c, p, dim;
6379b09969d6SVaclav Hapla 
6380b09969d6SVaclav Hapla   PetscFunctionBegin;
63819566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
63829566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
638325b6865aSVaclav Hapla   /* Get/check global number of vertices */
638425b6865aSVaclav Hapla   {
638525b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
638625b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
638725b6865aSVaclav Hapla 
638825b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
63891690c2aeSBarry Smith     NVerticesInCells = PETSC_INT_MIN;
63909371c9d4SSatish Balay     for (i = 0; i < len; i++)
63919371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
639225b6865aSVaclav Hapla     ++NVerticesInCells;
639325b6865aSVaclav Hapla 
639425b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells;
63959371c9d4SSatish Balay     else
63969371c9d4SSatish 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);
639725b6865aSVaclav Hapla   }
63989566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
639948a46eb9SPierre Jolivet   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
64009566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
64019566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
6402b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
6403ad540459SPierre Jolivet     for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells;
6404b09969d6SVaclav Hapla   }
64059566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
64069566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
64079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
64083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6409b09969d6SVaclav Hapla }
6410b09969d6SVaclav Hapla 
6411cc4c1da9SBarry Smith /*@
6412a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
6413a1cb98faSBarry Smith 
6414cc4c1da9SBarry Smith   Collective
6415b09969d6SVaclav Hapla 
6416b09969d6SVaclav Hapla   Input Parameters:
6417a1cb98faSBarry Smith + dm           - The `DM`
6418b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
6419b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6420b09969d6SVaclav Hapla 
6421b09969d6SVaclav Hapla   Level: advanced
6422b09969d6SVaclav Hapla 
64231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()`
6424b09969d6SVaclav Hapla @*/
6425d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[])
6426d71ae5a4SJacob Faibussowitsch {
6427b09969d6SVaclav Hapla   PetscSection coordSection;
6428b09969d6SVaclav Hapla   Vec          coordinates;
6429b09969d6SVaclav Hapla   DM           cdm;
6430b09969d6SVaclav Hapla   PetscScalar *coords;
64311edcf0b2SVaclav Hapla   PetscInt     v, vStart, vEnd, d;
6432b09969d6SVaclav Hapla 
6433b09969d6SVaclav Hapla   PetscFunctionBegin;
64349566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
64359566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
64361dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
64379566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
64389566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
64399566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
64409566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
64419566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
64421edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
64439566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
64449566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
6445b09969d6SVaclav Hapla   }
64469566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
6447b09969d6SVaclav Hapla 
64489566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
64499566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(cdm, &coordinates));
64509566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
64519566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
64529566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(coordinates, &coords));
64531edcf0b2SVaclav Hapla   for (v = 0; v < vEnd - vStart; ++v) {
6454ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d];
6455b09969d6SVaclav Hapla   }
64569566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
64579566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
64589566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
64599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
64603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6461b09969d6SVaclav Hapla }
6462b09969d6SVaclav Hapla 
6463b09969d6SVaclav Hapla /*@
6464a1cb98faSBarry Smith   DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input
64653df08285SMatthew G. Knepley 
6466a1cb98faSBarry Smith   Collective
6467b09969d6SVaclav Hapla 
6468b09969d6SVaclav Hapla   Input Parameters:
6469b09969d6SVaclav Hapla + comm         - The communicator
6470b09969d6SVaclav Hapla . dim          - The topological dimension of the mesh
64713df08285SMatthew G. Knepley . numCells     - The number of cells, only on process 0
6472a1cb98faSBarry Smith . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0
64733df08285SMatthew G. Knepley . numCorners   - The number of vertices for each cell, only on process 0
6474b09969d6SVaclav Hapla . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
6475ce78bad3SBarry Smith . cells        - An array of $ numCells \times numCorners$ numbers, the vertices for each cell, only on process 0
6476b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
6477ce78bad3SBarry Smith - vertexCoords - An array of $ numVertices \times spaceDim$ numbers, the coordinates of each vertex, only on process 0
6478b09969d6SVaclav Hapla 
6479b09969d6SVaclav Hapla   Output Parameter:
6480a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0
648125b6865aSVaclav Hapla 
6482b09969d6SVaclav Hapla   Level: intermediate
6483b09969d6SVaclav Hapla 
6484a1cb98faSBarry Smith   Notes:
6485a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`,
6486a1cb98faSBarry Smith   `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()`
6487a1cb98faSBarry Smith 
6488a1cb98faSBarry Smith   See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters.
6489a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters.
6490a1cb98faSBarry Smith   See `DMPlexCreateFromCellListParallelPetsc()` for parallel input
6491a1cb98faSBarry Smith 
64921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
64939298eaa6SMatthew G Knepley @*/
6494d71ae5a4SJacob 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)
6495d71ae5a4SJacob Faibussowitsch {
64963df08285SMatthew G. Knepley   PetscMPIInt rank;
64979298eaa6SMatthew G Knepley 
64989298eaa6SMatthew G Knepley   PetscFunctionBegin;
649928b400f6SJacob 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.");
65009566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
65019566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
65029566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
65039566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
6504c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells));
65059566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL));
65069298eaa6SMatthew G Knepley   if (interpolate) {
65075fd9971aSMatthew G. Knepley     DM idm;
65089298eaa6SMatthew G Knepley 
65099566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
65109566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
65119298eaa6SMatthew G Knepley     *dm = idm;
65129298eaa6SMatthew G Knepley   }
6513c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords));
65149566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL));
65153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
65169298eaa6SMatthew G Knepley }
65179298eaa6SMatthew G Knepley 
6518939f6067SMatthew G. Knepley /*@
651920f4b53cSBarry Smith   DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a `DM`
6520939f6067SMatthew G. Knepley 
6521939f6067SMatthew G. Knepley   Input Parameters:
652220f4b53cSBarry Smith + dm               - The empty `DM` object, usually from `DMCreate()` and `DMSetDimension()`
6523939f6067SMatthew G. Knepley . depth            - The depth of the DAG
6524ce78bad3SBarry Smith . numPoints        - Array of size $ depth + 1 $ containing the number of points at each `depth`
6525939f6067SMatthew G. Knepley . coneSize         - The cone size of each point
6526939f6067SMatthew G. Knepley . cones            - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
6527939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point
6528ce78bad3SBarry Smith - vertexCoords     - An array of $ numPoints[0] \times spacedim $ numbers representing the coordinates of each vertex, with `spacedim` the value set via `DMSetCoordinateDim()`
6529939f6067SMatthew G. Knepley 
6530939f6067SMatthew G. Knepley   Output Parameter:
653120f4b53cSBarry Smith . dm - The `DM`
653220f4b53cSBarry Smith 
653320f4b53cSBarry Smith   Level: advanced
6534939f6067SMatthew G. Knepley 
6535a1cb98faSBarry Smith   Note:
6536a1cb98faSBarry Smith   Two triangles sharing a face would have input
6537a1cb98faSBarry Smith .vb
6538a1cb98faSBarry Smith   depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
6539a1cb98faSBarry Smith   cones = [2 3 4  3 5 4], coneOrientations = [0 0 0  0 0 0]
6540a1cb98faSBarry Smith  vertexCoords = [-1.0 0.0  0.0 -1.0  0.0 1.0  1.0 0.0]
6541a1cb98faSBarry Smith .ve
6542939f6067SMatthew G. Knepley   which would result in the DMPlex
6543a1cb98faSBarry Smith .vb
6544a1cb98faSBarry Smith         4
6545a1cb98faSBarry Smith       / | \
6546a1cb98faSBarry Smith      /  |  \
6547a1cb98faSBarry Smith     /   |   \
6548a1cb98faSBarry Smith    2  0 | 1  5
6549a1cb98faSBarry Smith     \   |   /
6550a1cb98faSBarry Smith      \  |  /
6551a1cb98faSBarry Smith       \ | /
6552a1cb98faSBarry Smith         3
6553a1cb98faSBarry Smith .ve
6554a1cb98faSBarry Smith   Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()`
6555939f6067SMatthew G. Knepley 
6556ce78bad3SBarry Smith   Developer Note:
6557ce78bad3SBarry Smith   This does not create anything so should not have create in the name.
6558ce78bad3SBarry Smith 
65591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
6560939f6067SMatthew G. Knepley @*/
6561d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
6562d71ae5a4SJacob Faibussowitsch {
65639298eaa6SMatthew G Knepley   Vec          coordinates;
65649298eaa6SMatthew G Knepley   PetscSection coordSection;
65659298eaa6SMatthew G Knepley   PetscScalar *coords;
6566811e8653SToby Isaac   PetscInt     coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off;
65679298eaa6SMatthew G Knepley 
65689298eaa6SMatthew G Knepley   PetscFunctionBegin;
65699566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
65709566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
657163a3b9bcSJacob Faibussowitsch   PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim);
65729298eaa6SMatthew G Knepley   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
65739566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, pStart, pEnd));
65749298eaa6SMatthew G Knepley   for (p = pStart; p < pEnd; ++p) {
65759566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart]));
6576ad540459SPierre Jolivet     if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart;
657797e052ccSToby Isaac   }
65781dca8a05SBarry Smith   PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]);
65799566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm)); /* Allocate space for cones */
65809298eaa6SMatthew G Knepley   for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) {
65819566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(dm, p, &cones[off]));
65829566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off]));
65839298eaa6SMatthew G Knepley   }
65849566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
65859566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
65869298eaa6SMatthew G Knepley   /* Build coordinates */
65879566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
65889566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
65899566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
65909566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0]));
65919298eaa6SMatthew G Knepley   for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) {
65929566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
65939566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
65949298eaa6SMatthew G Knepley   }
65959566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
65969566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
65979566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
65989566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
65999566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
66009566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, dimEmbed));
66019566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
66029318fe57SMatthew G. Knepley   if (vertexCoords) {
66039566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
66049298eaa6SMatthew G Knepley     for (v = 0; v < numPoints[0]; ++v) {
66059298eaa6SMatthew G Knepley       PetscInt off;
66069298eaa6SMatthew G Knepley 
66079566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off));
6608ad540459SPierre Jolivet       for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d];
66099298eaa6SMatthew G Knepley     }
66109318fe57SMatthew G. Knepley   }
66119566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
66129566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
66139566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
66143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66159298eaa6SMatthew G Knepley }
66168415267dSToby Isaac 
6617a4e35b19SJacob Faibussowitsch /*
6618a1cb98faSBarry Smith   DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file.
6619a1cb98faSBarry Smith 
6620a1cb98faSBarry Smith   Collective
66218ca92349SMatthew G. Knepley 
66228ca92349SMatthew G. Knepley + comm        - The MPI communicator
66238ca92349SMatthew G. Knepley . filename    - Name of the .dat file
66248ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
66258ca92349SMatthew G. Knepley 
66268ca92349SMatthew G. Knepley   Output Parameter:
6627a1cb98faSBarry Smith . dm  - The `DM` object representing the mesh
66288ca92349SMatthew G. Knepley 
66298ca92349SMatthew G. Knepley   Level: beginner
66308ca92349SMatthew G. Knepley 
6631a1cb98faSBarry Smith   Note:
6632a1cb98faSBarry Smith   The format is the simplest possible:
6633a1cb98faSBarry Smith .vb
6634d0812dedSMatthew G. Knepley   dim Ne Nv Nc Nl
6635d0812dedSMatthew G. Knepley   v_1 v_2 ... v_Nc
6636d0812dedSMatthew G. Knepley   ...
6637d0812dedSMatthew G. Knepley   x y z marker_1 ... marker_Nl
6638a1cb98faSBarry Smith .ve
6639a1cb98faSBarry Smith 
6640a1cb98faSBarry Smith   Developer Note:
6641a1cb98faSBarry Smith   Should use a `PetscViewer` not a filename
6642a1cb98faSBarry Smith 
66436afe31f6SMartin Diehl .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
6644a4e35b19SJacob Faibussowitsch */
6645ff6a9541SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
6646d71ae5a4SJacob Faibussowitsch {
66478ca92349SMatthew G. Knepley   DMLabel      marker;
66488ca92349SMatthew G. Knepley   PetscViewer  viewer;
66498ca92349SMatthew G. Knepley   Vec          coordinates;
66508ca92349SMatthew G. Knepley   PetscSection coordSection;
66518ca92349SMatthew G. Knepley   PetscScalar *coords;
66528ca92349SMatthew G. Knepley   char         line[PETSC_MAX_PATH_LEN];
6653d0812dedSMatthew G. Knepley   PetscInt     cdim, coordSize, v, c, d;
66548ca92349SMatthew G. Knepley   PetscMPIInt  rank;
6655d0812dedSMatthew G. Knepley   int          snum, dim, Nv, Nc, Ncn, Nl;
66568ca92349SMatthew G. Knepley 
66578ca92349SMatthew G. Knepley   PetscFunctionBegin;
66589566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
66599566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
66609566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
66619566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
66629566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
6663dd400576SPatrick Sanan   if (rank == 0) {
6664d0812dedSMatthew G. Knepley     PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING));
6665d0812dedSMatthew G. Knepley     snum = sscanf(line, "%d %d %d %d %d", &dim, &Nc, &Nv, &Ncn, &Nl);
6666d0812dedSMatthew G. Knepley     PetscCheck(snum == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
666725ce1634SJed Brown   } else {
6668f8d5e320SMatthew G. Knepley     Nc = Nv = Ncn = Nl = 0;
66698ca92349SMatthew G. Knepley   }
6670d0812dedSMatthew G. Knepley   PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm));
6671835f2295SStefano Zampini   cdim = dim;
66729566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
66739566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
66749566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
6675835f2295SStefano Zampini   PetscCall(DMSetDimension(*dm, dim));
66769566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, cdim));
66778ca92349SMatthew G. Knepley   /* Read topology */
6678dd400576SPatrick Sanan   if (rank == 0) {
6679f8d5e320SMatthew G. Knepley     char     format[PETSC_MAX_PATH_LEN];
6680f8d5e320SMatthew G. Knepley     PetscInt cone[8];
66818ca92349SMatthew G. Knepley     int      vbuf[8], v;
66828ca92349SMatthew G. Knepley 
66839371c9d4SSatish Balay     for (c = 0; c < Ncn; ++c) {
66849371c9d4SSatish Balay       format[c * 3 + 0] = '%';
66859371c9d4SSatish Balay       format[c * 3 + 1] = 'd';
66869371c9d4SSatish Balay       format[c * 3 + 2] = ' ';
66879371c9d4SSatish Balay     }
6688f8d5e320SMatthew G. Knepley     format[Ncn * 3 - 1] = '\0';
66899566063dSJacob Faibussowitsch     for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn));
66909566063dSJacob Faibussowitsch     PetscCall(DMSetUp(*dm));
66918ca92349SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
66929566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING));
6693f8d5e320SMatthew G. Knepley       switch (Ncn) {
6694d71ae5a4SJacob Faibussowitsch       case 2:
6695d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1]);
6696d71ae5a4SJacob Faibussowitsch         break;
6697d71ae5a4SJacob Faibussowitsch       case 3:
6698d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]);
6699d71ae5a4SJacob Faibussowitsch         break;
6700d71ae5a4SJacob Faibussowitsch       case 4:
6701d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]);
6702d71ae5a4SJacob Faibussowitsch         break;
6703d71ae5a4SJacob Faibussowitsch       case 6:
6704d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]);
6705d71ae5a4SJacob Faibussowitsch         break;
6706d71ae5a4SJacob Faibussowitsch       case 8:
6707d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]);
6708d71ae5a4SJacob Faibussowitsch         break;
6709d71ae5a4SJacob Faibussowitsch       default:
6710d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn);
6711f8d5e320SMatthew G. Knepley       }
671208401ef6SPierre Jolivet       PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
6713f8d5e320SMatthew G. Knepley       for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc;
67148ca92349SMatthew G. Knepley       /* Hexahedra are inverted */
6715f8d5e320SMatthew G. Knepley       if (Ncn == 8) {
67168ca92349SMatthew G. Knepley         PetscInt tmp = cone[1];
67178ca92349SMatthew G. Knepley         cone[1]      = cone[3];
67188ca92349SMatthew G. Knepley         cone[3]      = tmp;
67198ca92349SMatthew G. Knepley       }
67209566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(*dm, c, cone));
67218ca92349SMatthew G. Knepley     }
67228ca92349SMatthew G. Knepley   }
67239566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
67249566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
67258ca92349SMatthew G. Knepley   /* Read coordinates */
67269566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
67279566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
67289566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
67299566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
67308ca92349SMatthew G. Knepley   for (v = Nc; v < Nc + Nv; ++v) {
67319566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
67329566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
67338ca92349SMatthew G. Knepley   }
67349566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
67359566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
67369566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
67379566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
67389566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
67399566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
67409566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
67419566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
6742dd400576SPatrick Sanan   if (rank == 0) {
6743f8d5e320SMatthew G. Knepley     char   format[PETSC_MAX_PATH_LEN];
67448ca92349SMatthew G. Knepley     double x[3];
6745f8d5e320SMatthew G. Knepley     int    l, val[3];
67468ca92349SMatthew G. Knepley 
6747f8d5e320SMatthew G. Knepley     if (Nl) {
67489371c9d4SSatish Balay       for (l = 0; l < Nl; ++l) {
67499371c9d4SSatish Balay         format[l * 3 + 0] = '%';
67509371c9d4SSatish Balay         format[l * 3 + 1] = 'd';
67519371c9d4SSatish Balay         format[l * 3 + 2] = ' ';
67529371c9d4SSatish Balay       }
6753f8d5e320SMatthew G. Knepley       format[Nl * 3 - 1] = '\0';
67549566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
67559566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &marker));
6756f8d5e320SMatthew G. Knepley     }
67578ca92349SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
67589566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING));
6759f8d5e320SMatthew G. Knepley       snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]);
676008401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
6761f8d5e320SMatthew G. Knepley       switch (Nl) {
6762d71ae5a4SJacob Faibussowitsch       case 0:
6763d71ae5a4SJacob Faibussowitsch         snum = 0;
6764d71ae5a4SJacob Faibussowitsch         break;
6765d71ae5a4SJacob Faibussowitsch       case 1:
6766d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0]);
6767d71ae5a4SJacob Faibussowitsch         break;
6768d71ae5a4SJacob Faibussowitsch       case 2:
6769d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1]);
6770d71ae5a4SJacob Faibussowitsch         break;
6771d71ae5a4SJacob Faibussowitsch       case 3:
6772d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1], &val[2]);
6773d71ae5a4SJacob Faibussowitsch         break;
6774d71ae5a4SJacob Faibussowitsch       default:
6775d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl);
6776f8d5e320SMatthew G. Knepley       }
677708401ef6SPierre Jolivet       PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
67788ca92349SMatthew G. Knepley       for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d];
67799566063dSJacob Faibussowitsch       for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l]));
67808ca92349SMatthew G. Knepley     }
67818ca92349SMatthew G. Knepley   }
67829566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
67839566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
67849566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
67859566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
67868ca92349SMatthew G. Knepley   if (interpolate) {
67878ca92349SMatthew G. Knepley     DM      idm;
67888ca92349SMatthew G. Knepley     DMLabel bdlabel;
67898ca92349SMatthew G. Knepley 
67909566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
67919566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
67928ca92349SMatthew G. Knepley     *dm = idm;
67938ca92349SMatthew G. Knepley 
6794f8d5e320SMatthew G. Knepley     if (!Nl) {
67959566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
67969566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &bdlabel));
67979566063dSJacob Faibussowitsch       PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel));
67989566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelComplete(*dm, bdlabel));
67998ca92349SMatthew G. Knepley     }
6800f8d5e320SMatthew G. Knepley   }
68013ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68028ca92349SMatthew G. Knepley }
68038ca92349SMatthew G. Knepley 
6804cc4c1da9SBarry Smith /*@
6805a1cb98faSBarry Smith   DMPlexCreateFromFile - This takes a filename and produces a `DM`
6806a1cb98faSBarry Smith 
6807a1cb98faSBarry Smith   Collective
6808ca522641SMatthew G. Knepley 
6809ca522641SMatthew G. Knepley   Input Parameters:
6810ca522641SMatthew G. Knepley + comm        - The communicator
6811ca522641SMatthew G. Knepley . filename    - A file name
6812a1cb98faSBarry Smith . plexname    - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats
6813ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
6814ca522641SMatthew G. Knepley 
6815ca522641SMatthew G. Knepley   Output Parameter:
6816a1cb98faSBarry Smith . dm - The `DM`
6817ca522641SMatthew G. Knepley 
6818a1cb98faSBarry Smith   Options Database Key:
6819a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5
682002ef0d99SVaclav Hapla 
682137fdd005SBarry Smith   Use `-dm_plex_create_ prefix` to pass options to the internal `PetscViewer`, e.g.
6822bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective
6823bca97951SVaclav Hapla 
6824ca522641SMatthew G. Knepley   Level: beginner
6825ca522641SMatthew G. Knepley 
6826a1cb98faSBarry Smith   Notes:
6827a1cb98faSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
6828a1cb98faSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
6829a1cb98faSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
6830a1cb98faSBarry Smith   The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally
6831a1cb98faSBarry Smith   calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats.
6832a1cb98faSBarry Smith 
68331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()`
6834ca522641SMatthew G. Knepley @*/
6835d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm)
6836d71ae5a4SJacob Faibussowitsch {
6837ef3a5affSJacob Faibussowitsch   const char  extGmsh[]      = ".msh";
6838ef3a5affSJacob Faibussowitsch   const char  extGmsh2[]     = ".msh2";
6839ef3a5affSJacob Faibussowitsch   const char  extGmsh4[]     = ".msh4";
6840ef3a5affSJacob Faibussowitsch   const char  extCGNS[]      = ".cgns";
6841ef3a5affSJacob Faibussowitsch   const char  extExodus[]    = ".exo";
6842ef3a5affSJacob Faibussowitsch   const char  extExodus_e[]  = ".e";
6843ef3a5affSJacob Faibussowitsch   const char  extGenesis[]   = ".gen";
6844ef3a5affSJacob Faibussowitsch   const char  extFluent[]    = ".cas";
6845ef3a5affSJacob Faibussowitsch   const char  extHDF5[]      = ".h5";
68466f2c871aSStefano Zampini   const char  extXDMFHDF5[]  = ".xdmf.h5";
6847ef3a5affSJacob Faibussowitsch   const char  extPLY[]       = ".ply";
68485552b385SBrandon   const char  extEGADSlite[] = ".egadslite";
6849ef3a5affSJacob Faibussowitsch   const char  extEGADS[]     = ".egads";
6850ef3a5affSJacob Faibussowitsch   const char  extIGES[]      = ".igs";
68515552b385SBrandon   const char  extIGES2[]     = ".iges";
6852ef3a5affSJacob Faibussowitsch   const char  extSTEP[]      = ".stp";
68535552b385SBrandon   const char  extSTEP2[]     = ".step";
68545552b385SBrandon   const char  extBREP[]      = ".brep";
6855ef3a5affSJacob Faibussowitsch   const char  extCV[]        = ".dat";
6856ca522641SMatthew G. Knepley   size_t      len;
68575552b385SBrandon   PetscBool   isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isPLY, isEGADSlite, isEGADS, isIGES, isIGES2, isSTEP, isSTEP2, isBREP, isCV, isXDMFHDF5;
6858ca522641SMatthew G. Knepley   PetscMPIInt rank;
6859ca522641SMatthew G. Knepley 
6860ca522641SMatthew G. Knepley   PetscFunctionBegin;
68614f572ea9SToby Isaac   PetscAssertPointer(filename, 2);
68624f572ea9SToby Isaac   if (plexname) PetscAssertPointer(plexname, 3);
68634f572ea9SToby Isaac   PetscAssertPointer(dm, 5);
68649566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
68659566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0));
68669566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
68679566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(filename, &len));
686828b400f6SJacob Faibussowitsch   PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path");
6869ef3a5affSJacob Faibussowitsch 
68709371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \
68719371c9d4SSatish Balay   do { \
6872274aaeaaSJacob Faibussowitsch     PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \
6873274aaeaaSJacob Faibussowitsch     /* don't count the null-terminator at the end */ \
6874274aaeaaSJacob Faibussowitsch     const size_t ext_len = sizeof(extension__) - 1; \
6875274aaeaaSJacob Faibussowitsch     if (len < ext_len) { \
6876ef3a5affSJacob Faibussowitsch       is_extension__ = PETSC_FALSE; \
6877ef3a5affSJacob Faibussowitsch     } else { \
6878274aaeaaSJacob Faibussowitsch       PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \
6879ef3a5affSJacob Faibussowitsch     } \
6880ef3a5affSJacob Faibussowitsch   } while (0)
6881ef3a5affSJacob Faibussowitsch 
6882ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh, isGmsh);
6883ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh2, isGmsh2);
6884ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh4, isGmsh4);
6885ef3a5affSJacob Faibussowitsch   CheckExtension(extCGNS, isCGNS);
6886ef3a5affSJacob Faibussowitsch   CheckExtension(extExodus, isExodus);
6887ef3a5affSJacob Faibussowitsch   if (!isExodus) CheckExtension(extExodus_e, isExodus);
6888ef3a5affSJacob Faibussowitsch   CheckExtension(extGenesis, isGenesis);
6889ef3a5affSJacob Faibussowitsch   CheckExtension(extFluent, isFluent);
6890ef3a5affSJacob Faibussowitsch   CheckExtension(extHDF5, isHDF5);
6891ef3a5affSJacob Faibussowitsch   CheckExtension(extPLY, isPLY);
68925552b385SBrandon   CheckExtension(extEGADSlite, isEGADSlite);
6893ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADS, isEGADS);
6894ef3a5affSJacob Faibussowitsch   CheckExtension(extIGES, isIGES);
68955552b385SBrandon   CheckExtension(extIGES2, isIGES2);
6896ef3a5affSJacob Faibussowitsch   CheckExtension(extSTEP, isSTEP);
68975552b385SBrandon   CheckExtension(extSTEP2, isSTEP2);
68985552b385SBrandon   CheckExtension(extBREP, isBREP);
6899ef3a5affSJacob Faibussowitsch   CheckExtension(extCV, isCV);
69006f2c871aSStefano Zampini   CheckExtension(extXDMFHDF5, isXDMFHDF5);
6901ef3a5affSJacob Faibussowitsch 
6902ef3a5affSJacob Faibussowitsch #undef CheckExtension
6903ef3a5affSJacob Faibussowitsch 
6904de78e4feSLisandro Dalcin   if (isGmsh || isGmsh2 || isGmsh4) {
69059566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm));
6906ca522641SMatthew G. Knepley   } else if (isCGNS) {
69079566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm));
690890c68965SMatthew G. Knepley   } else if (isExodus || isGenesis) {
69099566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm));
69102f0bd6dcSMichael Lange   } else if (isFluent) {
69119566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm));
6912cc2f8f65SMatthew G. Knepley   } else if (isHDF5) {
6913cc2f8f65SMatthew G. Knepley     PetscViewer viewer;
6914cc2f8f65SMatthew G. Knepley 
691543b242b4SVaclav 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 */
69166f2c871aSStefano Zampini     PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &isXDMFHDF5, NULL));
69179566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(comm, &viewer));
69189566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5));
69199566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_"));
69209566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetFromOptions(viewer));
69219566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
69229566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(viewer, filename));
6923cd7e8a5eSksagiyam 
69249566063dSJacob Faibussowitsch     PetscCall(DMCreate(comm, dm));
6925f4f49eeaSPierre Jolivet     PetscCall(PetscObjectSetName((PetscObject)*dm, plexname));
69269566063dSJacob Faibussowitsch     PetscCall(DMSetType(*dm, DMPLEX));
69276f2c871aSStefano Zampini     if (isXDMFHDF5) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF));
69289566063dSJacob Faibussowitsch     PetscCall(DMLoad(*dm, viewer));
69296f2c871aSStefano Zampini     if (isXDMFHDF5) PetscCall(PetscViewerPopFormat(viewer));
69309566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
69315fd9971aSMatthew G. Knepley 
69325fd9971aSMatthew G. Knepley     if (interpolate) {
69335fd9971aSMatthew G. Knepley       DM idm;
69345fd9971aSMatthew G. Knepley 
69359566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm));
69369566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
69375fd9971aSMatthew G. Knepley       *dm = idm;
69385fd9971aSMatthew G. Knepley     }
6939f2801cd6SMatthew G. Knepley   } else if (isPLY) {
69409566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm));
69415552b385SBrandon   } else if (isEGADSlite || isEGADS || isIGES || isIGES2 || isSTEP || isSTEP2 || isBREP) {
69425552b385SBrandon     PetscCall(DMPlexCreateGeomFromFile(comm, filename, dm, isEGADSlite));
69435552b385SBrandon 
69447bee2925SMatthew Knepley     if (!interpolate) {
69457bee2925SMatthew Knepley       DM udm;
69467bee2925SMatthew Knepley 
69479566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(*dm, &udm));
69489566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
69497bee2925SMatthew Knepley       *dm = udm;
69507bee2925SMatthew Knepley     }
69518ca92349SMatthew G. Knepley   } else if (isCV) {
69529566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm));
695398921bdaSJacob Faibussowitsch   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename);
69549566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(plexname, &len));
6955f4f49eeaSPierre Jolivet   if (len) PetscCall(PetscObjectSetName((PetscObject)*dm, plexname));
69569566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0));
69573ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6958ca522641SMatthew G. Knepley }
695912b8a6daSStefano Zampini 
6960cc4c1da9SBarry Smith /*@
69619f6c5813SMatthew 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.
69629f6c5813SMatthew G. Knepley 
69630528010dSStefano Zampini   Input Parameters:
69640528010dSStefano Zampini + tr     - The `DMPlexTransform`
69650528010dSStefano Zampini - prefix - An options prefix, or NULL
69669f6c5813SMatthew G. Knepley 
69679f6c5813SMatthew G. Knepley   Output Parameter:
69689f6c5813SMatthew G. Knepley . dm - The `DM`
69699f6c5813SMatthew G. Knepley 
69709f6c5813SMatthew G. Knepley   Level: beginner
69719f6c5813SMatthew G. Knepley 
697220f4b53cSBarry Smith   Notes:
697320f4b53cSBarry 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.
697420f4b53cSBarry Smith 
69759f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
69769f6c5813SMatthew G. Knepley @*/
69770528010dSStefano Zampini PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, const char prefix[], DM *dm)
69789f6c5813SMatthew G. Knepley {
69790528010dSStefano Zampini   DM           bdm, bcdm, cdm;
69800528010dSStefano Zampini   Vec          coordinates, coordinatesNew;
69810528010dSStefano Zampini   PetscSection cs;
6982817b2c36SMatthew G. Knepley   PetscInt     cdim, Nl;
69839f6c5813SMatthew G. Knepley 
69849f6c5813SMatthew G. Knepley   PetscFunctionBegin;
69859f6c5813SMatthew G. Knepley   PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm));
69869f6c5813SMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
69870528010dSStefano Zampini   ((DM_Plex *)(*dm)->data)->interpolated = DMPLEX_INTERPOLATED_FULL;
69880528010dSStefano Zampini   // Handle coordinates
69890528010dSStefano Zampini   PetscCall(DMPlexTransformGetDM(tr, &bdm));
6990817b2c36SMatthew G. Knepley   PetscCall(DMPlexTransformSetDimensions(tr, bdm, *dm));
6991817b2c36SMatthew G. Knepley   PetscCall(DMGetCoordinateDim(*dm, &cdim));
69920528010dSStefano Zampini   PetscCall(DMGetCoordinateDM(bdm, &bcdm));
69930528010dSStefano Zampini   PetscCall(DMGetCoordinateDM(*dm, &cdm));
69940528010dSStefano Zampini   PetscCall(DMCopyDisc(bcdm, cdm));
69950528010dSStefano Zampini   PetscCall(DMGetLocalSection(cdm, &cs));
69960528010dSStefano Zampini   PetscCall(PetscSectionSetNumFields(cs, 1));
69970528010dSStefano Zampini   PetscCall(PetscSectionSetFieldComponents(cs, 0, cdim));
69980528010dSStefano Zampini   PetscCall(DMGetCoordinatesLocal(bdm, &coordinates));
69990528010dSStefano Zampini   PetscCall(VecDuplicate(coordinates, &coordinatesNew));
70000528010dSStefano Zampini   PetscCall(VecCopy(coordinates, coordinatesNew));
70010528010dSStefano Zampini   PetscCall(DMSetCoordinatesLocal(*dm, coordinatesNew));
70020528010dSStefano Zampini   PetscCall(VecDestroy(&coordinatesNew));
70039f6c5813SMatthew G. Knepley 
70049f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)tr));
70059f6c5813SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr));
70069f6c5813SMatthew G. Knepley   ((DM_Plex *)(*dm)->data)->tr = tr;
70070528010dSStefano Zampini   PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE));
70080528010dSStefano Zampini   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix));
70090528010dSStefano Zampini   PetscCall(DMSetFromOptions(*dm));
70109f6c5813SMatthew G. Knepley 
70119f6c5813SMatthew G. Knepley   PetscCall(DMGetNumLabels(bdm, &Nl));
70129f6c5813SMatthew G. Knepley   for (PetscInt l = 0; l < Nl; ++l) {
70139f6c5813SMatthew G. Knepley     DMLabel     label, labelNew;
70149f6c5813SMatthew G. Knepley     const char *lname;
70159f6c5813SMatthew G. Knepley     PetscBool   isDepth, isCellType;
70169f6c5813SMatthew G. Knepley 
70179f6c5813SMatthew G. Knepley     PetscCall(DMGetLabelName(bdm, l, &lname));
70189f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "depth", &isDepth));
70199f6c5813SMatthew G. Knepley     if (isDepth) continue;
70209f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "celltype", &isCellType));
70219f6c5813SMatthew G. Knepley     if (isCellType) continue;
70229f6c5813SMatthew G. Knepley     PetscCall(DMCreateLabel(*dm, lname));
70239f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(bdm, lname, &label));
70249f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(*dm, lname, &labelNew));
70259f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL));
70269f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetLabel(labelNew, label));
70279f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetTransform(labelNew, tr));
70289f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetUp(labelNew));
70299f6c5813SMatthew G. Knepley   }
70303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
70319f6c5813SMatthew G. Knepley }
7032