xref: /petsc/src/dm/impls/plex/plexcreate.c (revision ac9d17c75cb5e991458e9675ca6ec07d361dad47)
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;
296*ac9d17c7SMatthew G. Knepley   PetscInt dim, cdim, dE, qorder, height;
2979318fe57SMatthew G. Knepley 
298e44f6aebSMatthew G. Knepley   PetscFunctionBegin;
2999566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
300*ac9d17c7SMatthew 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));
306*ac9d17c7SMatthew 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));
309*ac9d17c7SMatthew G. Knepley   if (cdim > dim) {
310*ac9d17c7SMatthew G. Knepley     DM           cdm;
311*ac9d17c7SMatthew G. Knepley     PetscSection cs, csNew;
312*ac9d17c7SMatthew G. Knepley     Vec          coordinates, coordinatesNew;
313*ac9d17c7SMatthew G. Knepley     VecType      vectype;
314*ac9d17c7SMatthew G. Knepley     IS           idx;
315*ac9d17c7SMatthew G. Knepley     PetscInt    *indices;
316*ac9d17c7SMatthew G. Knepley     PetscInt     bs, n;
317*ac9d17c7SMatthew G. Knepley 
318*ac9d17c7SMatthew G. Knepley     // Recreate coordinate section
319*ac9d17c7SMatthew G. Knepley     {
320*ac9d17c7SMatthew G. Knepley       const char *fieldName = NULL, *compName = NULL;
321*ac9d17c7SMatthew G. Knepley       PetscInt    Nc, pStart, pEnd;
322*ac9d17c7SMatthew G. Knepley 
323*ac9d17c7SMatthew G. Knepley       PetscCall(DMGetCoordinateDM(dm, &cdm));
324*ac9d17c7SMatthew G. Knepley       PetscCall(DMGetLocalSection(cdm, &cs));
325*ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cs), &csNew));
326*ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetNumFields(csNew, 1));
327*ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionGetFieldName(cs, 0, &fieldName));
328*ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetFieldName(csNew, 0, fieldName));
329*ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionGetFieldComponents(cs, 0, &Nc));
330*ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetFieldComponents(csNew, 0, cdim));
331*ac9d17c7SMatthew G. Knepley       for (PetscInt c = 0; c < Nc; ++c) {
332*ac9d17c7SMatthew G. Knepley         PetscCall(PetscSectionGetComponentName(cs, 0, c, &compName));
333*ac9d17c7SMatthew G. Knepley         PetscCall(PetscSectionSetComponentName(csNew, 0, c, compName));
334*ac9d17c7SMatthew G. Knepley       }
335*ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionGetChart(cs, &pStart, &pEnd));
336*ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetChart(csNew, pStart, pEnd));
337*ac9d17c7SMatthew G. Knepley       for (PetscInt p = pStart; p < pEnd; ++p) {
338*ac9d17c7SMatthew G. Knepley         PetscCall(PetscSectionSetDof(csNew, p, cdim));
339*ac9d17c7SMatthew G. Knepley         PetscCall(PetscSectionSetFieldDof(csNew, p, 0, cdim));
340*ac9d17c7SMatthew G. Knepley       }
341*ac9d17c7SMatthew G. Knepley       PetscCall(PetscSectionSetUp(csNew));
342*ac9d17c7SMatthew G. Knepley     }
343*ac9d17c7SMatthew G. Knepley     PetscCall(DMSetLocalSection(cdm, csNew));
344*ac9d17c7SMatthew G. Knepley     PetscCall(PetscSectionDestroy(&csNew));
345*ac9d17c7SMatthew G. Knepley     // Inject coordinates into higher dimension
346*ac9d17c7SMatthew G. Knepley     PetscCall(DMGetCoordinatesLocal(dm, &coordinates));
347*ac9d17c7SMatthew G. Knepley     PetscCall(VecGetBlockSize(coordinates, &bs));
348*ac9d17c7SMatthew G. Knepley     PetscCheck(bs == dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension");
349*ac9d17c7SMatthew G. Knepley     PetscCall(VecCreate(PetscObjectComm((PetscObject)coordinates), &coordinatesNew));
350*ac9d17c7SMatthew G. Knepley     PetscCall(VecGetType(coordinates, &vectype));
351*ac9d17c7SMatthew G. Knepley     PetscCall(VecSetType(coordinatesNew, vectype));
352*ac9d17c7SMatthew G. Knepley     PetscCall(VecGetLocalSize(coordinates, &n));
353*ac9d17c7SMatthew G. Knepley     PetscCheck(!(n % bs), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension");
354*ac9d17c7SMatthew G. Knepley     n /= bs;
355*ac9d17c7SMatthew G. Knepley     PetscCall(VecSetSizes(coordinatesNew, n * cdim, PETSC_DETERMINE));
356*ac9d17c7SMatthew G. Knepley     PetscCall(VecSetUp(coordinatesNew));
357*ac9d17c7SMatthew G. Knepley     PetscCall(PetscMalloc1(n * bs, &indices));
358*ac9d17c7SMatthew G. Knepley     for (PetscInt i = 0; i < n; ++i)
359*ac9d17c7SMatthew G. Knepley       for (PetscInt b = 0; b < bs; ++b) indices[i * bs + b] = i * cdim + b;
360*ac9d17c7SMatthew G. Knepley     PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n * bs, indices, PETSC_OWN_POINTER, &idx));
361*ac9d17c7SMatthew G. Knepley     PetscCall(VecISCopy(coordinatesNew, idx, SCATTER_FORWARD, coordinates));
362*ac9d17c7SMatthew G. Knepley     PetscCall(ISDestroy(&idx));
363*ac9d17c7SMatthew G. Knepley     PetscCall(DMSetCoordinatesLocal(dm, coordinatesNew));
364*ac9d17c7SMatthew G. Knepley     PetscCall(VecDestroy(&coordinatesNew));
365*ac9d17c7SMatthew G. Knepley     PetscCall(DMSetCoordinateDim(dm, cdim));
366*ac9d17c7SMatthew G. Knepley     {
367*ac9d17c7SMatthew G. Knepley       PetscInt gn;
368*ac9d17c7SMatthew G. Knepley 
369*ac9d17c7SMatthew G. Knepley       PetscCall(DMGetCoordinates(dm, &coordinatesNew));
370*ac9d17c7SMatthew G. Knepley       PetscCall(VecGetLocalSize(coordinatesNew, &gn));
371*ac9d17c7SMatthew 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);
372*ac9d17c7SMatthew G. Knepley     }
373*ac9d17c7SMatthew G. Knepley     dE = cdim;
374*ac9d17c7SMatthew 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 
1239d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate)
1240d71ae5a4SJacob Faibussowitsch {
12419318fe57SMatthew G. Knepley   DM      boundary, vol;
1242c22d3578SMatthew G. Knepley   DMLabel bdlabel;
1243d6218766SMatthew G. Knepley 
1244d6218766SMatthew G. Knepley   PetscFunctionBegin;
12454f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
1246c22d3578SMatthew 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");
12479566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary));
12489566063dSJacob Faibussowitsch   PetscCall(DMSetType(boundary, DMPLEX));
12499566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE));
12509566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol));
1251c22d3578SMatthew G. Knepley   PetscCall(DMGetLabel(vol, "marker", &bdlabel));
1252c22d3578SMatthew G. Knepley   if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel));
12535de52c6dSVaclav Hapla   PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol));
125469d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
12554054ae39SJames Wright   if (interpolate) {
12564054ae39SJames Wright     PetscCall(DMPlexInterpolateInPlace_Internal(dm));
1257d7d2d1d2SJames Wright     PetscCall(DMPlexSetBoxLabel_Internal(dm, periodicity));
12584054ae39SJames Wright   }
12599566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&boundary));
12603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1261d6218766SMatthew G. Knepley }
1262d6218766SMatthew G. Knepley 
1263d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ)
1264d71ae5a4SJacob Faibussowitsch {
1265ed0e4b50SMatthew G. Knepley   DMLabel     cutLabel  = NULL;
1266f4eb4c5dSMatthew G. Knepley   PetscInt    markerTop = 1, faceMarkerTop = 1;
1267f4eb4c5dSMatthew G. Knepley   PetscInt    markerBottom = 1, faceMarkerBottom = 1;
1268f4eb4c5dSMatthew G. Knepley   PetscInt    markerFront = 1, faceMarkerFront = 1;
1269f4eb4c5dSMatthew G. Knepley   PetscInt    markerBack = 1, faceMarkerBack = 1;
1270f4eb4c5dSMatthew G. Knepley   PetscInt    markerRight = 1, faceMarkerRight = 1;
1271f4eb4c5dSMatthew G. Knepley   PetscInt    markerLeft = 1, faceMarkerLeft = 1;
12723dfda0b1SToby Isaac   PetscInt    dim;
1273d8211ee3SMatthew G. Knepley   PetscBool   markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE;
12743dfda0b1SToby Isaac   PetscMPIInt rank;
12753dfda0b1SToby Isaac 
12763dfda0b1SToby Isaac   PetscFunctionBegin;
12779566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
12789566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
12799566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
12809566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
12819566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
12829371c9d4SSatish 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) {
12839371c9d4SSatish Balay     if (cutMarker) {
12849371c9d4SSatish Balay       PetscCall(DMCreateLabel(dm, "periodic_cut"));
12859371c9d4SSatish Balay       PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
12869371c9d4SSatish Balay     }
1287d8211ee3SMatthew G. Knepley   }
12883dfda0b1SToby Isaac   switch (dim) {
12893dfda0b1SToby Isaac   case 2:
1290f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 3;
1291f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
1292f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 2;
1293f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 4;
12943dfda0b1SToby Isaac     break;
12953dfda0b1SToby Isaac   case 3:
1296f4eb4c5dSMatthew G. Knepley     faceMarkerBottom = 1;
1297f4eb4c5dSMatthew G. Knepley     faceMarkerTop    = 2;
1298f4eb4c5dSMatthew G. Knepley     faceMarkerFront  = 3;
1299f4eb4c5dSMatthew G. Knepley     faceMarkerBack   = 4;
1300f4eb4c5dSMatthew G. Knepley     faceMarkerRight  = 5;
1301f4eb4c5dSMatthew G. Knepley     faceMarkerLeft   = 6;
13023dfda0b1SToby Isaac     break;
1303d71ae5a4SJacob Faibussowitsch   default:
1304d71ae5a4SJacob Faibussowitsch     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim);
13053dfda0b1SToby Isaac   }
13069566063dSJacob Faibussowitsch   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL));
1307f4eb4c5dSMatthew G. Knepley   if (markerSeparate) {
1308f4eb4c5dSMatthew G. Knepley     markerBottom = faceMarkerBottom;
1309f4eb4c5dSMatthew G. Knepley     markerTop    = faceMarkerTop;
1310f4eb4c5dSMatthew G. Knepley     markerFront  = faceMarkerFront;
1311f4eb4c5dSMatthew G. Knepley     markerBack   = faceMarkerBack;
1312f4eb4c5dSMatthew G. Knepley     markerRight  = faceMarkerRight;
1313f4eb4c5dSMatthew G. Knepley     markerLeft   = faceMarkerLeft;
13143dfda0b1SToby Isaac   }
13153dfda0b1SToby Isaac   {
1316dd400576SPatrick Sanan     const PetscInt numXEdges    = rank == 0 ? edges[0] : 0;
1317dd400576SPatrick Sanan     const PetscInt numYEdges    = rank == 0 ? edges[1] : 0;
1318dd400576SPatrick Sanan     const PetscInt numZEdges    = rank == 0 ? edges[2] : 0;
1319dd400576SPatrick Sanan     const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0;
1320dd400576SPatrick Sanan     const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0;
1321dd400576SPatrick Sanan     const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0;
13223dfda0b1SToby Isaac     const PetscInt numCells     = numXEdges * numYEdges * numZEdges;
13233dfda0b1SToby Isaac     const PetscInt numXFaces    = numYEdges * numZEdges;
13243dfda0b1SToby Isaac     const PetscInt numYFaces    = numXEdges * numZEdges;
13253dfda0b1SToby Isaac     const PetscInt numZFaces    = numXEdges * numYEdges;
13263dfda0b1SToby Isaac     const PetscInt numTotXFaces = numXVertices * numXFaces;
13273dfda0b1SToby Isaac     const PetscInt numTotYFaces = numYVertices * numYFaces;
13283dfda0b1SToby Isaac     const PetscInt numTotZFaces = numZVertices * numZFaces;
13293dfda0b1SToby Isaac     const PetscInt numFaces     = numTotXFaces + numTotYFaces + numTotZFaces;
13303dfda0b1SToby Isaac     const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices;
13313dfda0b1SToby Isaac     const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices;
13323dfda0b1SToby Isaac     const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices;
13333dfda0b1SToby Isaac     const PetscInt numVertices  = numXVertices * numYVertices * numZVertices;
13343dfda0b1SToby Isaac     const PetscInt numEdges     = numTotXEdges + numTotYEdges + numTotZEdges;
13353dfda0b1SToby Isaac     const PetscInt firstVertex  = (dim == 2) ? numFaces : numCells;
13363dfda0b1SToby Isaac     const PetscInt firstXFace   = (dim == 2) ? 0 : numCells + numVertices;
13373dfda0b1SToby Isaac     const PetscInt firstYFace   = firstXFace + numTotXFaces;
13383dfda0b1SToby Isaac     const PetscInt firstZFace   = firstYFace + numTotYFaces;
13393dfda0b1SToby Isaac     const PetscInt firstXEdge   = numCells + numFaces + numVertices;
13403dfda0b1SToby Isaac     const PetscInt firstYEdge   = firstXEdge + numTotXEdges;
13413dfda0b1SToby Isaac     const PetscInt firstZEdge   = firstYEdge + numTotYEdges;
13423dfda0b1SToby Isaac     Vec            coordinates;
13433dfda0b1SToby Isaac     PetscSection   coordSection;
13443dfda0b1SToby Isaac     PetscScalar   *coords;
13453dfda0b1SToby Isaac     PetscInt       coordSize;
13463dfda0b1SToby Isaac     PetscInt       v, vx, vy, vz;
13473dfda0b1SToby Isaac     PetscInt       c, f, fx, fy, fz, e, ex, ey, ez;
13483dfda0b1SToby Isaac 
13499566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices));
135048a46eb9SPierre Jolivet     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
135148a46eb9SPierre Jolivet     for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4));
135248a46eb9SPierre Jolivet     for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
13539566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm)); /* Allocate space for cones */
13543dfda0b1SToby Isaac     /* Build cells */
13553dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
13563dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
13573dfda0b1SToby Isaac         for (fx = 0; fx < numXEdges; ++fx) {
13583dfda0b1SToby Isaac           PetscInt cell  = (fz * numYEdges + fy) * numXEdges + fx;
13593dfda0b1SToby Isaac           PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
13603dfda0b1SToby Isaac           PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices);
13613dfda0b1SToby Isaac           PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
13623dfda0b1SToby Isaac           PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices);
13633dfda0b1SToby Isaac           PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
13643dfda0b1SToby Isaac           PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices);
13653dfda0b1SToby Isaac           /* B,  T,  F,  K,  R,  L */
1366b5a892a1SMatthew G. Knepley           PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */
136742206facSLisandro Dalcin           PetscInt cone[6];
13683dfda0b1SToby Isaac 
13693dfda0b1SToby Isaac           /* no boundary twisting in 3D */
13709371c9d4SSatish Balay           cone[0] = faceB;
13719371c9d4SSatish Balay           cone[1] = faceT;
13729371c9d4SSatish Balay           cone[2] = faceF;
13739371c9d4SSatish Balay           cone[3] = faceK;
13749371c9d4SSatish Balay           cone[4] = faceR;
13759371c9d4SSatish Balay           cone[5] = faceL;
13769566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, cell, cone));
13779566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, cell, ornt));
13789566063dSJacob Faibussowitsch           if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
13799566063dSJacob Faibussowitsch           if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
13809566063dSJacob Faibussowitsch           if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2));
13813dfda0b1SToby Isaac         }
13823dfda0b1SToby Isaac       }
13833dfda0b1SToby Isaac     }
13843dfda0b1SToby Isaac     /* Build x faces */
13853dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
13863dfda0b1SToby Isaac       for (fy = 0; fy < numYEdges; ++fy) {
13873dfda0b1SToby Isaac         for (fx = 0; fx < numXVertices; ++fx) {
13883dfda0b1SToby Isaac           PetscInt face    = firstXFace + (fz * numYEdges + fy) * numXVertices + fx;
13893dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
13903dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz;
13913dfda0b1SToby Isaac           PetscInt edgeB   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
13923dfda0b1SToby Isaac           PetscInt edgeT   = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy;
1393b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
13943dfda0b1SToby Isaac           PetscInt cone[4];
13953dfda0b1SToby Isaac 
13963dfda0b1SToby Isaac           if (dim == 3) {
13973dfda0b1SToby Isaac             /* markers */
13983dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
13993dfda0b1SToby Isaac               if (fx == numXVertices - 1) {
14009566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight));
14019566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerRight));
14029371c9d4SSatish Balay               } else if (fx == 0) {
14039566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft));
14049566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft));
14053dfda0b1SToby Isaac               }
14063dfda0b1SToby Isaac             }
14073dfda0b1SToby Isaac           }
14089371c9d4SSatish Balay           cone[0] = edgeB;
14099371c9d4SSatish Balay           cone[1] = edgeR;
14109371c9d4SSatish Balay           cone[2] = edgeT;
14119371c9d4SSatish Balay           cone[3] = edgeL;
14129566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
14139566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
14143dfda0b1SToby Isaac         }
14153dfda0b1SToby Isaac       }
14163dfda0b1SToby Isaac     }
14173dfda0b1SToby Isaac     /* Build y faces */
14183dfda0b1SToby Isaac     for (fz = 0; fz < numZEdges; ++fz) {
141942206facSLisandro Dalcin       for (fx = 0; fx < numXEdges; ++fx) {
14203dfda0b1SToby Isaac         for (fy = 0; fy < numYVertices; ++fy) {
14213dfda0b1SToby Isaac           PetscInt face    = firstYFace + (fz * numXEdges + fx) * numYVertices + fy;
14223dfda0b1SToby Isaac           PetscInt edgeL   = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz;
14233dfda0b1SToby Isaac           PetscInt edgeR   = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz;
14243dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
14253dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx;
1426b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
14273dfda0b1SToby Isaac           PetscInt cone[4];
14283dfda0b1SToby Isaac 
14293dfda0b1SToby Isaac           if (dim == 3) {
14303dfda0b1SToby Isaac             /* markers */
14313dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
14323dfda0b1SToby Isaac               if (fy == numYVertices - 1) {
14339566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack));
14349566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBack));
14359371c9d4SSatish Balay               } else if (fy == 0) {
14369566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront));
14379566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerFront));
14383dfda0b1SToby Isaac               }
14393dfda0b1SToby Isaac             }
14403dfda0b1SToby Isaac           }
14419371c9d4SSatish Balay           cone[0] = edgeB;
14429371c9d4SSatish Balay           cone[1] = edgeR;
14439371c9d4SSatish Balay           cone[2] = edgeT;
14449371c9d4SSatish Balay           cone[3] = edgeL;
14459566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
14469566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
14473dfda0b1SToby Isaac         }
14483dfda0b1SToby Isaac       }
14493dfda0b1SToby Isaac     }
14503dfda0b1SToby Isaac     /* Build z faces */
14513dfda0b1SToby Isaac     for (fy = 0; fy < numYEdges; ++fy) {
14523dfda0b1SToby Isaac       for (fx = 0; fx < numXEdges; ++fx) {
14533dfda0b1SToby Isaac         for (fz = 0; fz < numZVertices; fz++) {
14543dfda0b1SToby Isaac           PetscInt face    = firstZFace + (fy * numXEdges + fx) * numZVertices + fz;
14553dfda0b1SToby Isaac           PetscInt edgeL   = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy;
14563dfda0b1SToby Isaac           PetscInt edgeR   = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy;
14573dfda0b1SToby Isaac           PetscInt edgeB   = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx;
14583dfda0b1SToby Isaac           PetscInt edgeT   = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx;
1459b5a892a1SMatthew G. Knepley           PetscInt ornt[4] = {0, 0, -1, -1};
14603dfda0b1SToby Isaac           PetscInt cone[4];
14613dfda0b1SToby Isaac 
14623dfda0b1SToby Isaac           if (dim == 2) {
14639371c9d4SSatish Balay             if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) {
14649371c9d4SSatish Balay               edgeR += numYEdges - 1 - 2 * fy;
14659371c9d4SSatish Balay               ornt[1] = -1;
14669371c9d4SSatish Balay             }
14679371c9d4SSatish Balay             if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) {
14689371c9d4SSatish Balay               edgeT += numXEdges - 1 - 2 * fx;
14699371c9d4SSatish Balay               ornt[2] = 0;
14709371c9d4SSatish Balay             }
14719566063dSJacob Faibussowitsch             if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
14729566063dSJacob Faibussowitsch             if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2));
1473d1c88043SMatthew G. Knepley           } else {
14743dfda0b1SToby Isaac             /* markers */
14753dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
14763dfda0b1SToby Isaac               if (fz == numZVertices - 1) {
14779566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop));
14789566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerTop));
14799371c9d4SSatish Balay               } else if (fz == 0) {
14809566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom));
14819566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom));
14823dfda0b1SToby Isaac               }
14833dfda0b1SToby Isaac             }
14843dfda0b1SToby Isaac           }
14859371c9d4SSatish Balay           cone[0] = edgeB;
14869371c9d4SSatish Balay           cone[1] = edgeR;
14879371c9d4SSatish Balay           cone[2] = edgeT;
14889371c9d4SSatish Balay           cone[3] = edgeL;
14899566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, face, cone));
14909566063dSJacob Faibussowitsch           PetscCall(DMPlexSetConeOrientation(dm, face, ornt));
14913dfda0b1SToby Isaac         }
14923dfda0b1SToby Isaac       }
14933dfda0b1SToby Isaac     }
14943dfda0b1SToby Isaac     /* Build Z edges*/
14953dfda0b1SToby Isaac     for (vy = 0; vy < numYVertices; vy++) {
14963dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
14973dfda0b1SToby Isaac         for (ez = 0; ez < numZEdges; ez++) {
14983dfda0b1SToby Isaac           const PetscInt edge    = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez;
14993dfda0b1SToby Isaac           const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx;
15003dfda0b1SToby Isaac           const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx;
15013dfda0b1SToby Isaac           PetscInt       cone[2];
15023dfda0b1SToby Isaac 
15039371c9d4SSatish Balay           cone[0] = vertexB;
15049371c9d4SSatish Balay           cone[1] = vertexT;
1505c2df9bbfSMatthew G. Knepley           PetscCall(DMPlexSetCone(dm, edge, cone));
15063dfda0b1SToby Isaac           if (dim == 3) {
15073dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
15083dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
15099566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1510c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1511c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1512c2df9bbfSMatthew G. Knepley               } else if (vx == 0) {
15139566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1514c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1515c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
15163dfda0b1SToby Isaac               }
15173dfda0b1SToby Isaac             }
15183dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
15193dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
15209566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1521c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1522c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1523c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
15249566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1525c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1526c2df9bbfSMatthew G. Knepley                 if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
15273dfda0b1SToby Isaac               }
15283dfda0b1SToby Isaac             }
15293dfda0b1SToby Isaac           }
15303dfda0b1SToby Isaac         }
15313dfda0b1SToby Isaac       }
15323dfda0b1SToby Isaac     }
15333dfda0b1SToby Isaac     /* Build Y edges*/
15343dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
15353dfda0b1SToby Isaac       for (vx = 0; vx < numXVertices; vx++) {
15363dfda0b1SToby Isaac         for (ey = 0; ey < numYEdges; ey++) {
15373dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx;
15383dfda0b1SToby Isaac           const PetscInt edge    = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey;
15393dfda0b1SToby Isaac           const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx;
15403dfda0b1SToby Isaac           const PetscInt vertexK = firstVertex + nextv;
15413dfda0b1SToby Isaac           PetscInt       cone[2];
15423dfda0b1SToby Isaac 
15439371c9d4SSatish Balay           cone[0] = vertexF;
15449371c9d4SSatish Balay           cone[1] = vertexK;
15459566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
15463dfda0b1SToby Isaac           if (dim == 2) {
15473dfda0b1SToby Isaac             if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) {
15483dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
15499566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight));
15509566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
15519566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1552c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1553d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
15549566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft));
15559566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
15569566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1557c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
15583dfda0b1SToby Isaac               }
1559d8211ee3SMatthew G. Knepley             } else {
15604c67ea77SStefano Zampini               if (vx == 0 && cutLabel) {
15619566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
15629566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1563c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
15643dfda0b1SToby Isaac               }
1565d8211ee3SMatthew G. Knepley             }
1566d8211ee3SMatthew G. Knepley           } else {
15673dfda0b1SToby Isaac             if (bdX != DM_BOUNDARY_PERIODIC) {
15683dfda0b1SToby Isaac               if (vx == numXVertices - 1) {
15699566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight));
1570c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight));
1571c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight));
1572d8211ee3SMatthew G. Knepley               } else if (vx == 0) {
15739566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft));
1574c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft));
1575c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft));
15763dfda0b1SToby Isaac               }
15773dfda0b1SToby Isaac             }
15783dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
15793dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
15809566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1581c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1582c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1583d8211ee3SMatthew G. Knepley               } else if (vz == 0) {
15849566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1585c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1586c2df9bbfSMatthew G. Knepley                 if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
15873dfda0b1SToby Isaac               }
15883dfda0b1SToby Isaac             }
15893dfda0b1SToby Isaac           }
15903dfda0b1SToby Isaac         }
15913dfda0b1SToby Isaac       }
15923dfda0b1SToby Isaac     }
15933dfda0b1SToby Isaac     /* Build X edges*/
15943dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; vz++) {
15953dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; vy++) {
15963dfda0b1SToby Isaac         for (ex = 0; ex < numXEdges; ex++) {
15973dfda0b1SToby Isaac           const PetscInt nextv   = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices;
15983dfda0b1SToby Isaac           const PetscInt edge    = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex;
15993dfda0b1SToby Isaac           const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex;
16003dfda0b1SToby Isaac           const PetscInt vertexR = firstVertex + nextv;
16013dfda0b1SToby Isaac           PetscInt       cone[2];
16023dfda0b1SToby Isaac 
16039371c9d4SSatish Balay           cone[0] = vertexL;
16049371c9d4SSatish Balay           cone[1] = vertexR;
16059566063dSJacob Faibussowitsch           PetscCall(DMPlexSetCone(dm, edge, cone));
16063dfda0b1SToby Isaac           if (dim == 2) {
16073dfda0b1SToby Isaac             if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) {
16083dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
16099566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop));
16109566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
16119566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1612c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1613d8211ee3SMatthew G. Knepley               } else if (vy == 0) {
16149566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom));
16159566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
16169566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1617c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
16183dfda0b1SToby Isaac               }
1619d8211ee3SMatthew G. Knepley             } else {
16204c67ea77SStefano Zampini               if (vy == 0 && cutLabel) {
16219566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, edge, 1));
16229566063dSJacob Faibussowitsch                 PetscCall(DMLabelSetValue(cutLabel, cone[0], 1));
1623c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1));
16243dfda0b1SToby Isaac               }
1625d8211ee3SMatthew G. Knepley             }
1626d8211ee3SMatthew G. Knepley           } else {
16273dfda0b1SToby Isaac             if (bdY != DM_BOUNDARY_PERIODIC) {
16283dfda0b1SToby Isaac               if (vy == numYVertices - 1) {
16299566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack));
1630c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack));
1631c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack));
1632c2df9bbfSMatthew G. Knepley               } else if (vy == 0) {
16339566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront));
1634c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront));
1635c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront));
16363dfda0b1SToby Isaac               }
16373dfda0b1SToby Isaac             }
16383dfda0b1SToby Isaac             if (bdZ != DM_BOUNDARY_PERIODIC) {
16393dfda0b1SToby Isaac               if (vz == numZVertices - 1) {
16409566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop));
1641c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop));
1642c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop));
1643c2df9bbfSMatthew G. Knepley               } else if (vz == 0) {
16449566063dSJacob Faibussowitsch                 PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom));
1645c2df9bbfSMatthew G. Knepley                 PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom));
1646c2df9bbfSMatthew G. Knepley                 if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom));
16473dfda0b1SToby Isaac               }
16483dfda0b1SToby Isaac             }
16493dfda0b1SToby Isaac           }
16503dfda0b1SToby Isaac         }
16513dfda0b1SToby Isaac       }
16523dfda0b1SToby Isaac     }
16539566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
16549566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
16553dfda0b1SToby Isaac     /* Build coordinates */
16569566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
16579566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
16589566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
16599566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices));
16603dfda0b1SToby Isaac     for (v = firstVertex; v < firstVertex + numVertices; ++v) {
16619566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
16629566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
16633dfda0b1SToby Isaac     }
16649566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
16659566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
16669566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
16679566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
16689566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
16699566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
16709566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
16719566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
16723dfda0b1SToby Isaac     for (vz = 0; vz < numZVertices; ++vz) {
16733dfda0b1SToby Isaac       for (vy = 0; vy < numYVertices; ++vy) {
16743dfda0b1SToby Isaac         for (vx = 0; vx < numXVertices; ++vx) {
16753dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx;
16763dfda0b1SToby Isaac           coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy;
1677ad540459SPierre Jolivet           if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz;
16783dfda0b1SToby Isaac         }
16793dfda0b1SToby Isaac       }
16803dfda0b1SToby Isaac     }
16819566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
16829566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
16839566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
16843dfda0b1SToby Isaac   }
16853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16863dfda0b1SToby Isaac }
16873dfda0b1SToby Isaac 
1688d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1689d71ae5a4SJacob Faibussowitsch {
16909318fe57SMatthew G. Knepley   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
16919318fe57SMatthew G. Knepley   PetscInt       fac[3] = {0, 0, 0}, d;
1692552f7358SJed Brown 
1693552f7358SJed Brown   PetscFunctionBegin;
16944f572ea9SToby Isaac   PetscAssertPointer(dm, 1);
16959318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, dim, 2);
16969566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
16979371c9d4SSatish Balay   for (d = 0; d < dim; ++d) {
16989371c9d4SSatish Balay     fac[d] = faces[d];
16999371c9d4SSatish Balay     bdt[d] = periodicity[d];
17009371c9d4SSatish Balay   }
17019566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2]));
17029371c9d4SSatish 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))) {
17036858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
17046858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
1705552f7358SJed Brown 
17069318fe57SMatthew G. Knepley     for (d = 0; d < dim; ++d) {
17076858538eSMatthew G. Knepley       if (periodicity[d] != DM_BOUNDARY_NONE) {
17089318fe57SMatthew G. Knepley         L[d]       = upper[d] - lower[d];
17099318fe57SMatthew G. Knepley         maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d]));
1710768d5fceSMatthew G. Knepley       }
17116858538eSMatthew G. Knepley     }
17124fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
1713768d5fceSMatthew G. Knepley   }
17149566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
17153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
17169318fe57SMatthew G. Knepley }
17179318fe57SMatthew G. Knepley 
17185dca41c3SJed 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)
1719d71ae5a4SJacob Faibussowitsch {
17209318fe57SMatthew G. Knepley   PetscFunctionBegin;
172146139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
17225dca41c3SJed Brown   if (shape == DM_SHAPE_ZBOX) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
17236725e60dSJed Brown   else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0]));
17249566063dSJacob Faibussowitsch   else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate));
17259566063dSJacob Faibussowitsch   else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity));
17269318fe57SMatthew G. Knepley   if (!interpolate && dim > 1 && !simplex) {
1727768d5fceSMatthew G. Knepley     DM udm;
1728768d5fceSMatthew G. Knepley 
17299566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(dm, &udm));
17309566063dSJacob Faibussowitsch     PetscCall(DMPlexCopyCoordinates(dm, udm));
173169d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &udm));
1732768d5fceSMatthew G. Knepley   }
173346139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
17343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1735c8c68bd8SToby Isaac }
1736c8c68bd8SToby Isaac 
17375d83a8b1SBarry Smith /*@
1738768d5fceSMatthew G. Knepley   DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra).
1739768d5fceSMatthew G. Knepley 
1740d083f849SBarry Smith   Collective
1741768d5fceSMatthew G. Knepley 
1742768d5fceSMatthew G. Knepley   Input Parameters:
1743a1cb98faSBarry Smith + comm               - The communicator for the `DM` object
1744768d5fceSMatthew G. Knepley . dim                - The spatial dimension
1745a1cb98faSBarry Smith . simplex            - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells
174620f4b53cSBarry Smith . faces              - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
174720f4b53cSBarry Smith . lower              - The lower left corner, or `NULL` for (0, 0, 0)
174820f4b53cSBarry Smith . upper              - The upper right corner, or `NULL` for (1, 1, 1)
174920f4b53cSBarry Smith . periodicity        - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE`
175042108689Sksagiyam . interpolate        - Flag to create intermediate mesh pieces (edges, faces)
175142108689Sksagiyam . localizationHeight - Flag to localize edges and faces in addition to cells; only significant for periodic meshes
175242108689Sksagiyam - sparseLocalize     - Flag to localize coordinates only for cells near the periodic boundary; only significant for periodic meshes
1753768d5fceSMatthew G. Knepley 
1754768d5fceSMatthew G. Knepley   Output Parameter:
1755a1cb98faSBarry Smith . dm - The `DM` object
1756768d5fceSMatthew G. Knepley 
1757768d5fceSMatthew G. Knepley   Level: beginner
1758768d5fceSMatthew G. Knepley 
1759a1cb98faSBarry Smith   Note:
1760a1cb98faSBarry Smith   To customize this mesh using options, use
1761a1cb98faSBarry Smith .vb
1762a1cb98faSBarry Smith   DMCreate(comm, &dm);
1763a1cb98faSBarry Smith   DMSetType(dm, DMPLEX);
1764a1cb98faSBarry Smith   DMSetFromOptions(dm);
1765a1cb98faSBarry Smith .ve
1766a1cb98faSBarry Smith   and use the options in `DMSetFromOptions()`.
1767a1cb98faSBarry Smith 
1768a4e35b19SJacob Faibussowitsch   Here is the numbering returned for 2 faces in each direction for tensor cells\:
1769a1cb98faSBarry Smith .vb
1770a1cb98faSBarry Smith  10---17---11---18----12
1771a1cb98faSBarry Smith   |         |         |
1772a1cb98faSBarry Smith   |         |         |
1773a1cb98faSBarry Smith  20    2   22    3    24
1774a1cb98faSBarry Smith   |         |         |
1775a1cb98faSBarry Smith   |         |         |
1776a1cb98faSBarry Smith   7---15----8---16----9
1777a1cb98faSBarry Smith   |         |         |
1778a1cb98faSBarry Smith   |         |         |
1779a1cb98faSBarry Smith  19    0   21    1   23
1780a1cb98faSBarry Smith   |         |         |
1781a1cb98faSBarry Smith   |         |         |
1782a1cb98faSBarry Smith   4---13----5---14----6
1783a1cb98faSBarry Smith .ve
1784a1cb98faSBarry Smith   and for simplicial cells
1785a1cb98faSBarry Smith .vb
1786a1cb98faSBarry Smith  14----8---15----9----16
1787a1cb98faSBarry Smith   |\     5  |\      7 |
1788a1cb98faSBarry Smith   | \       | \       |
1789a1cb98faSBarry Smith  13   2    14    3    15
1790a1cb98faSBarry Smith   | 4   \   | 6   \   |
1791a1cb98faSBarry Smith   |       \ |       \ |
1792a1cb98faSBarry Smith  11----6---12----7----13
1793a1cb98faSBarry Smith   |\        |\        |
1794a1cb98faSBarry Smith   | \    1  | \     3 |
1795a1cb98faSBarry Smith  10   0    11    1    12
1796a1cb98faSBarry Smith   | 0   \   | 2   \   |
1797a1cb98faSBarry Smith   |       \ |       \ |
1798a1cb98faSBarry Smith   8----4----9----5----10
1799a1cb98faSBarry Smith .ve
1800a1cb98faSBarry Smith 
18011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
1802768d5fceSMatthew G. Knepley @*/
180342108689Sksagiyam 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)
1804d71ae5a4SJacob Faibussowitsch {
18059318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
1806fdbf62faSLisandro Dalcin   PetscReal      low[3] = {0, 0, 0};
1807fdbf62faSLisandro Dalcin   PetscReal      upp[3] = {1, 1, 1};
1808fdbf62faSLisandro Dalcin   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
1809552f7358SJed Brown 
1810768d5fceSMatthew G. Knepley   PetscFunctionBegin;
18119566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
18129566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
18135dca41c3SJed Brown   PetscCall(DMPlexCreateBoxMesh_Internal(*dm, DM_SHAPE_BOX, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate));
181442108689Sksagiyam   if (periodicity) {
181542108689Sksagiyam     DM cdm;
181642108689Sksagiyam 
181742108689Sksagiyam     PetscCall(DMGetCoordinateDM(*dm, &cdm));
181842108689Sksagiyam     PetscCall(DMPlexSetMaxProjectionHeight(cdm, localizationHeight));
181942108689Sksagiyam     PetscCall(DMSetSparseLocalize(*dm, sparseLocalize));
182042108689Sksagiyam     PetscCall(DMLocalizeCoordinates(*dm));
182142108689Sksagiyam   }
18223ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
18239318fe57SMatthew G. Knepley }
1824fdbf62faSLisandro Dalcin 
1825d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[])
1826d71ae5a4SJacob Faibussowitsch {
18279318fe57SMatthew G. Knepley   DM       bdm, vol;
18289318fe57SMatthew G. Knepley   PetscInt i;
18299318fe57SMatthew G. Knepley 
18309318fe57SMatthew G. Knepley   PetscFunctionBegin;
18311fcf445aSMatthew G. Knepley   // TODO Now we can support periodicity
183208401ef6SPierre Jolivet   for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported");
18339566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm));
18349566063dSJacob Faibussowitsch   PetscCall(DMSetType(bdm, DMPLEX));
18359566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(bdm, 2));
183646139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, bdm, 0, 0, 0));
18379566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE));
18381fcf445aSMatthew G. Knepley   PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, NULL, NULL, &vol));
183946139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, bdm, 0, 0, 0));
18409566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&bdm));
184169d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
18429318fe57SMatthew G. Knepley   if (lower[2] != 0.0) {
18439318fe57SMatthew G. Knepley     Vec          v;
18449318fe57SMatthew G. Knepley     PetscScalar *x;
18459318fe57SMatthew G. Knepley     PetscInt     cDim, n;
18469318fe57SMatthew G. Knepley 
18479566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &v));
18489566063dSJacob Faibussowitsch     PetscCall(VecGetBlockSize(v, &cDim));
18499566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(v, &n));
18509566063dSJacob Faibussowitsch     PetscCall(VecGetArray(v, &x));
18519318fe57SMatthew G. Knepley     x += cDim;
18529318fe57SMatthew G. Knepley     for (i = 0; i < n; i += cDim) x[i] += lower[2];
18539566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(v, &x));
18549566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, v));
18559318fe57SMatthew G. Knepley   }
18563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1857552f7358SJed Brown }
1858552f7358SJed Brown 
185900dabe28SStefano Zampini /*@
186039f4f5dbSPierre Jolivet   DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tessellating the (x,y) plane and extruding in the third direction using wedge cells.
186100dabe28SStefano Zampini 
1862d083f849SBarry Smith   Collective
186300dabe28SStefano Zampini 
186400dabe28SStefano Zampini   Input Parameters:
1865a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
186620f4b53cSBarry Smith . faces       - Number of faces per dimension, or `NULL` for (1, 1, 1)
186720f4b53cSBarry Smith . lower       - The lower left corner, or `NULL` for (0, 0, 0)
186820f4b53cSBarry Smith . upper       - The upper right corner, or `NULL` for (1, 1, 1)
186920f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE`
1870a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first
187100dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces)
187200dabe28SStefano Zampini 
187300dabe28SStefano Zampini   Output Parameter:
1874a1cb98faSBarry Smith . dm - The `DM` object
187500dabe28SStefano Zampini 
187600dabe28SStefano Zampini   Level: beginner
187700dabe28SStefano Zampini 
18781cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
187900dabe28SStefano Zampini @*/
1880d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm)
1881d71ae5a4SJacob Faibussowitsch {
18829318fe57SMatthew G. Knepley   PetscInt       fac[3] = {1, 1, 1};
188300dabe28SStefano Zampini   PetscReal      low[3] = {0, 0, 0};
188400dabe28SStefano Zampini   PetscReal      upp[3] = {1, 1, 1};
188500dabe28SStefano Zampini   DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
188600dabe28SStefano Zampini 
188700dabe28SStefano Zampini   PetscFunctionBegin;
18889566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
18899566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
18909566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt));
1891d410b0cfSMatthew G. Knepley   if (!interpolate) {
1892d410b0cfSMatthew G. Knepley     DM udm;
189300dabe28SStefano Zampini 
18949566063dSJacob Faibussowitsch     PetscCall(DMPlexUninterpolate(*dm, &udm));
189569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(*dm, &udm));
189600dabe28SStefano Zampini   }
18977ff04441SMatthew G. Knepley   if (periodicity) PetscCall(DMLocalizeCoordinates(*dm));
18983ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
189900dabe28SStefano Zampini }
190000dabe28SStefano Zampini 
1901cfb853baSMatthew G. Knepley /*
1902cfb853baSMatthew 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.
1903cfb853baSMatthew G. Knepley 
1904cfb853baSMatthew G. Knepley   Input Parameters:
1905cfb853baSMatthew G. Knepley + len - The length of the tuple
1906cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max)
1907cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition
1908cfb853baSMatthew G. Knepley 
1909cfb853baSMatthew G. Knepley   Output Parameter:
191020f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max`
1911cfb853baSMatthew G. Knepley 
1912cfb853baSMatthew G. Knepley   Level: developer
1913cfb853baSMatthew G. Knepley 
191420f4b53cSBarry Smith   Note:
191520f4b53cSBarry Smith   Ordering is lexicographic with lowest index as least significant in ordering.
191620f4b53cSBarry 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}.
191720f4b53cSBarry Smith 
1918cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal()
1919cfb853baSMatthew G. Knepley */
1920cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[])
1921cfb853baSMatthew G. Knepley {
1922cfb853baSMatthew G. Knepley   PetscInt i;
1923cfb853baSMatthew G. Knepley 
1924cfb853baSMatthew G. Knepley   PetscFunctionBegin;
1925cfb853baSMatthew G. Knepley   for (i = 0; i < len; ++i) {
1926cfb853baSMatthew G. Knepley     if (tup[i] < max[i] - 1) {
1927cfb853baSMatthew G. Knepley       break;
1928cfb853baSMatthew G. Knepley     } else {
1929cfb853baSMatthew G. Knepley       tup[i] = 0;
1930cfb853baSMatthew G. Knepley     }
1931cfb853baSMatthew G. Knepley   }
1932cfb853baSMatthew G. Knepley   if (i == len) tup[i - 1] = max[i - 1];
1933cfb853baSMatthew G. Knepley   else ++tup[i];
19343ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1935cfb853baSMatthew G. Knepley }
1936cfb853baSMatthew G. Knepley 
1937cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[])
1938cfb853baSMatthew G. Knepley {
19398d2ec52aSSatish Balay   PetscInt idx = tup[len - 1];
1940cfb853baSMatthew G. Knepley 
19418d2ec52aSSatish Balay   for (PetscInt i = len - 2; i >= 0; --i) {
1942cfb853baSMatthew G. Knepley     idx *= max[i];
1943cfb853baSMatthew G. Knepley     idx += tup[i];
1944cfb853baSMatthew G. Knepley   }
1945cfb853baSMatthew G. Knepley   return idx;
1946cfb853baSMatthew G. Knepley }
1947cfb853baSMatthew G. Knepley 
19488d2ec52aSSatish Balay static void IndexToTuple_Private(PetscInt len, const PetscInt max[], PetscInt idx, PetscInt tup[])
1949cfb853baSMatthew G. Knepley {
19508d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
19518d2ec52aSSatish Balay     tup[i] = idx % max[i];
19528d2ec52aSSatish Balay     idx    = (idx - tup[i]) / max[i];
19538d2ec52aSSatish Balay   }
19548d2ec52aSSatish Balay }
19558d2ec52aSSatish Balay 
19568d2ec52aSSatish Balay static void TupleToRanks_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt tup[], PetscInt ranks[])
19578d2ec52aSSatish Balay {
19588d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
19598d2ec52aSSatish Balay     const PetscInt div = max[i] / procs[i];
19608d2ec52aSSatish Balay     const PetscInt rem = max[i] % procs[i];
19618d2ec52aSSatish Balay     const PetscInt idx = (tup[i] < 0 ? max[i] + tup[i] : tup[i]) % max[i];
19628d2ec52aSSatish Balay 
19638d2ec52aSSatish Balay     if (idx < rem * (div + 1)) ranks[i] = idx / (div + 1);
19648d2ec52aSSatish Balay     else ranks[i] = rem + (idx - rem * (div + 1)) / div;
19658d2ec52aSSatish Balay   }
19668d2ec52aSSatish Balay }
19678d2ec52aSSatish Balay 
19688d2ec52aSSatish Balay static void RanksToSizes_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt ranks[], PetscInt sizes[])
19698d2ec52aSSatish Balay {
19708d2ec52aSSatish Balay   for (PetscInt i = 0; i < len; ++i) {
19718d2ec52aSSatish Balay     const PetscInt div = max[i] / procs[i];
19728d2ec52aSSatish Balay     const PetscInt rem = max[i] % procs[i];
19738d2ec52aSSatish Balay 
19748d2ec52aSSatish Balay     sizes[i] = ranks[i] < rem ? div + 1 : div;
19758d2ec52aSSatish Balay   }
19768d2ec52aSSatish Balay }
19778d2ec52aSSatish Balay 
19788d2ec52aSSatish Balay /*
19798d2ec52aSSatish 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.
19808d2ec52aSSatish Balay 
19818d2ec52aSSatish 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.
19828d2ec52aSSatish Balay 
19838d2ec52aSSatish 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.
1984dfe9cfe5SMatthew Knepley 
1985dfe9cfe5SMatthew Knepley   Parallel Layout:
1986dfe9cfe5SMatthew Knepley 
1987dfe9cfe5SMatthew 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.
19888d2ec52aSSatish Balay */
19898d2ec52aSSatish Balay static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], PetscInt overlap, const DMBoundaryType bd[])
19908d2ec52aSSatish Balay {
19918d2ec52aSSatish Balay   const PetscInt debug = ((DM_Plex *)dm->data)->printAdj;
19928d2ec52aSSatish Balay   PetscSF        sf;
1993cfb853baSMatthew G. Knepley   Vec            coordinates;
1994cfb853baSMatthew G. Knepley   PetscSection   coordSection;
1995cfb853baSMatthew G. Knepley   DMLabel        cutLabel    = NULL;
1996cfb853baSMatthew G. Knepley   PetscBool      cutMarker   = PETSC_FALSE;
1997cfb853baSMatthew G. Knepley   PetscBool      periodic    = PETSC_FALSE;
19988d2ec52aSSatish Balay   PetscInt       numCells    = 1;
19998d2ec52aSSatish Balay   PetscInt       numVertices = 1;
20008d2ec52aSSatish Balay   PetscSFNode   *remotes;
2001cfb853baSMatthew G. Knepley   PetscScalar   *coords;
20028d2ec52aSSatish Balay   PetscInt      *procs;     // The number of processes along each dimension
20038d2ec52aSSatish Balay   PetscInt      *lrank;     // Rank in each dimension, lrank[d] \in [0, procs[d])
20048d2ec52aSSatish Balay   PetscInt      *ledges;    // The number of edges along each dimension for this process
20058d2ec52aSSatish Balay   PetscInt      *vstart;    // The first vertex along each dimension on this processes
20068d2ec52aSSatish Balay   PetscInt      *vertices;  // The number of vertices along each dimension on this process
20078d2ec52aSSatish Balay   PetscInt      *rvert;     // The global (not local) vertex number along each dimension
20088d2ec52aSSatish Balay   PetscInt      *rrank;     // The rank along each dimension for the process owning rvert[]
20098d2ec52aSSatish Balay   PetscInt      *rvertices; // The number of vertices along each dimension for the process rrank[]
20108d2ec52aSSatish Balay   PetscInt      *vert, *vtmp, *supp, cone[2], *leaves;
20118d2ec52aSSatish Balay   PetscInt       cell = 0, coordSize, Nl = 0, Nl2 = 0;
20128d2ec52aSSatish Balay   PetscMPIInt    rank, size;
20138d2ec52aSSatish Balay   MPI_Comm       comm;
2014cfb853baSMatthew G. Knepley 
2015cfb853baSMatthew G. Knepley   PetscFunctionBegin;
20168d2ec52aSSatish Balay   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
20178d2ec52aSSatish Balay   PetscCallMPI(MPI_Comm_rank(comm, &rank));
20188d2ec52aSSatish Balay   PetscCallMPI(MPI_Comm_size(comm, &size));
2019cfb853baSMatthew G. Knepley   PetscCall(DMSetDimension(dm, dim));
20208d2ec52aSSatish Balay   PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
20218d2ec52aSSatish Balay   PetscCall(PetscCalloc4(dim, &procs, dim, &lrank, dim, &rrank, 2 * dim, &supp));
20228d2ec52aSSatish Balay   PetscCall(PetscCalloc7(dim, &ledges, dim, &vertices, dim, &rvertices, dim, &vert, dim, &rvert, dim, &vstart, dim, &vtmp));
2023cfb853baSMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "marker"));
2024cfb853baSMatthew G. Knepley   PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL));
20258d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE;
2026cfb853baSMatthew G. Knepley   if (periodic && cutMarker) {
2027cfb853baSMatthew G. Knepley     PetscCall(DMCreateLabel(dm, "periodic_cut"));
2028cfb853baSMatthew G. Knepley     PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel));
2029cfb853baSMatthew G. Knepley   }
20308d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, comm, PETSC_ERR_SUP, "Hypercubic mesh must be periodic now");
20318d2ec52aSSatish Balay   overlap = overlap == PETSC_DETERMINE ? 1 : overlap;
20328d2ec52aSSatish Balay   PetscCheck(overlap >= 1, comm, PETSC_ERR_SUP, "Overlap %" PetscInt_FMT " must be greater than 0", overlap);
20338d2ec52aSSatish Balay   if (size > 1) {
20348d2ec52aSSatish Balay     PetscInt Npr = 1;
20358d2ec52aSSatish Balay 
20368d2ec52aSSatish Balay     // Make process grid
20378d2ec52aSSatish Balay     if (debug) PetscCall(PetscPrintf(comm, "Process grid:"));
20388d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
20398d2ec52aSSatish Balay       procs[d] = PetscRintReal(PetscPowReal(size, 1. / dim));
20408d2ec52aSSatish Balay       Npr *= procs[d];
20418d2ec52aSSatish Balay       if (debug) PetscCall(PetscPrintf(comm, " %" PetscInt_FMT, procs[d]));
20428d2ec52aSSatish Balay     }
20438d2ec52aSSatish Balay     if (debug) PetscCall(PetscPrintf(comm, "\n"));
20448d2ec52aSSatish Balay     PetscCheck(Npr == size, comm, PETSC_ERR_PLIB, "Process grid size %" PetscInt_FMT " != %d comm size", Npr, size);
20458d2ec52aSSatish Balay     IndexToTuple_Private(dim, procs, rank, lrank);
20468d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
20478d2ec52aSSatish Balay       ledges[d] = edges[d] / procs[d] + (edges[d] % procs[d] > lrank[d] ? 1 : 0);
20488d2ec52aSSatish Balay       vstart[d] = 0;
20498d2ec52aSSatish Balay       for (PetscInt r = 0; r < lrank[d]; ++r) vstart[d] += edges[d] / procs[d] + (edges[d] % procs[d] > r ? 1 : 0);
20508d2ec52aSSatish Balay       vstart[d] -= overlap; // For halo
20518d2ec52aSSatish Balay     }
20528d2ec52aSSatish Balay   } else {
20538d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
20548d2ec52aSSatish Balay       procs[d]  = 1;
20558d2ec52aSSatish Balay       ledges[d] = edges[d];
20568d2ec52aSSatish Balay     }
20578d2ec52aSSatish Balay   }
20588d2ec52aSSatish Balay   // Calculate local patch size
20598d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) {
20608d2ec52aSSatish Balay     vertices[d] = ledges[d] + (procs[d] > 1 ? 2 * overlap : 0);
2061cfb853baSMatthew G. Knepley     numVertices *= vertices[d];
2062cfb853baSMatthew G. Knepley   }
2063cfb853baSMatthew G. Knepley   numCells = numVertices * dim;
2064cfb853baSMatthew G. Knepley   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
20658d2ec52aSSatish Balay   for (PetscInt c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2));
20668d2ec52aSSatish Balay   for (PetscInt v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim));
2067cfb853baSMatthew G. Knepley   PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */
2068cfb853baSMatthew G. Knepley   /* Build cell cones and vertex supports */
2069cfb853baSMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "celltype"));
20708d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Topology for rank %d:\n", rank));
2071cfb853baSMatthew G. Knepley   while (vert[dim - 1] < vertices[dim - 1]) {
2072cfb853baSMatthew G. Knepley     const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells;
2073cfb853baSMatthew G. Knepley     PetscInt       s      = 0;
20748d2ec52aSSatish Balay     PetscBool      leaf   = PETSC_FALSE;
2075cfb853baSMatthew G. Knepley 
20768d2ec52aSSatish Balay     if (debug) {
20778d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex));
20788d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d]));
20798d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "\n"));
20808d2ec52aSSatish Balay     }
2081cfb853baSMatthew G. Knepley     PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT));
20828d2ec52aSSatish Balay     // Define edge cones
20838d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
20848d2ec52aSSatish Balay       for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e];
2085cfb853baSMatthew G. Knepley       vtmp[d] = (vert[d] + 1) % vertices[d];
2086cfb853baSMatthew G. Knepley       cone[0] = vertex;
2087cfb853baSMatthew G. Knepley       cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells;
20888d2ec52aSSatish Balay       if (debug) {
20898d2ec52aSSatish Balay         PetscCall(PetscSynchronizedPrintf(comm, "  Vertex %" PetscInt_FMT ":", cone[1]));
20908d2ec52aSSatish Balay         for (PetscInt e = 0; e < dim; ++e) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vtmp[e]));
20918d2ec52aSSatish Balay         PetscCall(PetscSynchronizedPrintf(comm, "\n"));
20928d2ec52aSSatish Balay       }
2093cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetCone(dm, cell, cone));
2094cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT));
20958d2ec52aSSatish Balay       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "  Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1]));
2096cfb853baSMatthew G. Knepley       ++cell;
20978d2ec52aSSatish Balay       // Shared vertices are any in the first or last overlap layers
20988d2ec52aSSatish Balay       if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE;
2099cfb853baSMatthew G. Knepley     }
21008d2ec52aSSatish Balay     if (size > 1 && leaf) ++Nl;
21018d2ec52aSSatish Balay     // Define vertex supports
21028d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
21038d2ec52aSSatish Balay       for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e];
2104cfb853baSMatthew G. Knepley       vtmp[d]   = (vert[d] + vertices[d] - 1) % vertices[d];
2105cfb853baSMatthew G. Knepley       supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d;
2106cfb853baSMatthew G. Knepley       supp[s++] = (vertex - numCells) * dim + d;
2107cfb853baSMatthew G. Knepley       PetscCall(DMPlexSetSupport(dm, vertex, supp));
2108cfb853baSMatthew G. Knepley     }
2109cfb853baSMatthew G. Knepley     PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert));
2110cfb853baSMatthew G. Knepley   }
21118d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
2112cfb853baSMatthew G. Knepley   PetscCall(DMPlexStratify(dm));
21138d2ec52aSSatish Balay   // Allocate for SF
21148d2ec52aSSatish Balay   PetscCall(PetscMalloc1(Nl, &leaves));
21158d2ec52aSSatish Balay   PetscCall(PetscMalloc1(Nl, &remotes));
21168d2ec52aSSatish Balay   // Build coordinates
2117cfb853baSMatthew G. Knepley   PetscCall(DMGetCoordinateSection(dm, &coordSection));
2118cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetNumFields(coordSection, 1));
2119cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
2120cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
21218d2ec52aSSatish Balay   for (PetscInt v = numCells; v < numCells + numVertices; ++v) {
2122cfb853baSMatthew G. Knepley     PetscCall(PetscSectionSetDof(coordSection, v, dim));
2123cfb853baSMatthew G. Knepley     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
2124cfb853baSMatthew G. Knepley   }
2125cfb853baSMatthew G. Knepley   PetscCall(PetscSectionSetUp(coordSection));
2126cfb853baSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
21278d2ec52aSSatish Balay   PetscCall(VecCreate(comm, &coordinates));
2128cfb853baSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
2129cfb853baSMatthew G. Knepley   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
2130cfb853baSMatthew G. Knepley   PetscCall(VecSetBlockSize(coordinates, dim));
2131cfb853baSMatthew G. Knepley   PetscCall(VecSetType(coordinates, VECSTANDARD));
2132cfb853baSMatthew G. Knepley   PetscCall(VecGetArray(coordinates, &coords));
21338d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Geometry for rank %d:\n", rank));
21348d2ec52aSSatish Balay   for (PetscInt d = 0; d < dim; ++d) vert[d] = 0;
2135cfb853baSMatthew G. Knepley   while (vert[dim - 1] < vertices[dim - 1]) {
2136cfb853baSMatthew G. Knepley     const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert);
21378d2ec52aSSatish Balay     PetscBool      leaf   = PETSC_FALSE;
2138cfb853baSMatthew G. Knepley 
21398d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
21408d2ec52aSSatish Balay       coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / edges[d]) * (vert[d] + vstart[d]);
21418d2ec52aSSatish Balay       if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE;
21428d2ec52aSSatish Balay     }
21438d2ec52aSSatish Balay     if (size > 1 && leaf) {
21448d2ec52aSSatish Balay       PetscInt rnumCells = 1;
21458d2ec52aSSatish Balay 
21468d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) rvert[d] = vert[d] + vstart[d];
21478d2ec52aSSatish Balay       TupleToRanks_Private(dim, edges, procs, rvert, rrank);
21488d2ec52aSSatish Balay       leaves[Nl2]       = vertex + numCells;
21498d2ec52aSSatish Balay       remotes[Nl2].rank = TupleToIndex_Private(dim, procs, rrank);
21508d2ec52aSSatish Balay       RanksToSizes_Private(dim, edges, procs, rrank, rvertices);
21518d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) {
21528d2ec52aSSatish Balay         rvertices[d] += 2 * overlap; // Add halo
21538d2ec52aSSatish Balay         rnumCells *= rvertices[d];
21548d2ec52aSSatish Balay       }
21558d2ec52aSSatish Balay       rnumCells *= dim;
21568d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) {
21578d2ec52aSSatish Balay         const PetscInt diff = rrank[d] - lrank[d];
21588d2ec52aSSatish Balay 
21598d2ec52aSSatish Balay         if (!diff) rvert[d] = vert[d];                                     // Vertex is local
21608d2ec52aSSatish Balay         else if (rvert[d] < 0) rvert[d] = rvertices[d] - 1 + rvert[d];     // Wrap around at the bottom
21618d2ec52aSSatish Balay         else if (rvert[d] >= edges[d]) rvert[d] = rvert[d] - edges[d] + 1; // Wrap around at the top
21628d2ec52aSSatish Balay         else if (diff == -1) rvert[d] = rvertices[d] - 1 + (vert[d] - overlap);
21638d2ec52aSSatish Balay         else if (diff == 1) rvert[d] = (vertices[d] - vert[d] - 1) + overlap;
21648d2ec52aSSatish Balay         else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Process distance %" PetscInt_FMT " in direction %" PetscInt_FMT " should not be possible", diff, d);
21658d2ec52aSSatish Balay       }
21668d2ec52aSSatish Balay       remotes[Nl2].index = TupleToIndex_Private(dim, rvertices, rvert) + rnumCells;
21678d2ec52aSSatish Balay       if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Shared Vertex %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", leaves[Nl2], remotes[Nl2].rank, remotes[Nl2].index));
21688d2ec52aSSatish Balay       ++Nl2;
21698d2ec52aSSatish Balay     }
21708d2ec52aSSatish Balay     if (debug) {
21718d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex));
21728d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d] + vstart[d]));
21738d2ec52aSSatish Balay       for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %g", (double)PetscRealPart(coords[vertex * dim + d])));
21748d2ec52aSSatish Balay       PetscCall(PetscSynchronizedPrintf(comm, "\n"));
21758d2ec52aSSatish Balay     }
2176cfb853baSMatthew G. Knepley     PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert));
2177cfb853baSMatthew G. Knepley   }
21788d2ec52aSSatish Balay   if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL));
2179cfb853baSMatthew G. Knepley   PetscCall(VecRestoreArray(coordinates, &coords));
2180cfb853baSMatthew G. Knepley   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
2181cfb853baSMatthew G. Knepley   PetscCall(VecDestroy(&coordinates));
21828d2ec52aSSatish Balay   // Build SF
21838d2ec52aSSatish Balay   PetscCheck(Nl == Nl2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Initial number of leaves %" PetscInt_FMT " != %" PetscInt_FMT " final number", Nl, Nl2);
21848d2ec52aSSatish Balay   PetscCall(DMGetPointSF(dm, &sf));
21858d2ec52aSSatish Balay   PetscCall(PetscSFSetGraph(sf, numCells + numVertices, Nl, leaves, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER));
21868d2ec52aSSatish Balay   if (debug) PetscCall(PetscSFView(sf, PETSC_VIEWER_STDOUT_WORLD));
2187cfb853baSMatthew G. Knepley   //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper));
2188cfb853baSMatthew G. Knepley   // Attach the extent
2189cfb853baSMatthew G. Knepley   {
2190cfb853baSMatthew G. Knepley     PetscContainer c;
21918d2ec52aSSatish Balay     PetscInt      *extent, *lextent;
2192cfb853baSMatthew G. Knepley 
2193cfb853baSMatthew G. Knepley     PetscCall(PetscMalloc1(dim, &extent));
21948d2ec52aSSatish Balay     PetscCall(PetscMalloc1(dim, &lextent));
21958d2ec52aSSatish Balay     for (PetscInt d = 0; d < dim; ++d) {
21968d2ec52aSSatish Balay       extent[d]  = edges[d];
21978d2ec52aSSatish Balay       lextent[d] = ledges[d];
21988d2ec52aSSatish Balay     }
2199cfb853baSMatthew G. Knepley     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c));
220049abdd8aSBarry Smith     PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault));
2201cfb853baSMatthew G. Knepley     PetscCall(PetscContainerSetPointer(c, extent));
2202cfb853baSMatthew G. Knepley     PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c));
2203cfb853baSMatthew G. Knepley     PetscCall(PetscContainerDestroy(&c));
22048d2ec52aSSatish Balay     PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c));
22058d2ec52aSSatish Balay     PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault));
22068d2ec52aSSatish Balay     PetscCall(PetscContainerSetPointer(c, lextent));
22078d2ec52aSSatish Balay     PetscCall(PetscObjectCompose((PetscObject)dm, "_lextent", (PetscObject)c));
22088d2ec52aSSatish Balay     PetscCall(PetscContainerDestroy(&c));
2209cfb853baSMatthew G. Knepley   }
22108d2ec52aSSatish Balay   PetscCall(PetscFree4(procs, lrank, rrank, supp));
22118d2ec52aSSatish Balay   PetscCall(PetscFree7(ledges, vertices, rvertices, vert, rvert, vstart, vtmp));
22123ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2213cfb853baSMatthew G. Knepley }
2214cfb853baSMatthew G. Knepley 
2215cfb853baSMatthew G. Knepley /*@C
2216aaa8cc7dSPierre Jolivet   DMPlexCreateHypercubicMesh - Creates a periodic mesh on the tensor product of unit intervals using only vertices and edges.
2217cfb853baSMatthew G. Knepley 
2218cfb853baSMatthew G. Knepley   Collective
2219cfb853baSMatthew G. Knepley 
2220cfb853baSMatthew G. Knepley   Input Parameters:
22218d2ec52aSSatish Balay + comm    - The communicator for the `DM` object
2222cfb853baSMatthew G. Knepley . dim     - The spatial dimension
222320f4b53cSBarry Smith . edges   - Number of edges per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D
222420f4b53cSBarry Smith . lower   - The lower left corner, or `NULL` for (0, 0, 0)
22258d2ec52aSSatish Balay . upper   - The upper right corner, or `NULL` for (1, 1, 1)
22268d2ec52aSSatish Balay - overlap - The number of vertices in each direction to include in the overlap (default is 1)
2227cfb853baSMatthew G. Knepley 
2228cfb853baSMatthew G. Knepley   Output Parameter:
2229cfb853baSMatthew G. Knepley . dm - The DM object
2230cfb853baSMatthew G. Knepley 
223120f4b53cSBarry Smith   Level: beginner
223220f4b53cSBarry Smith 
223320f4b53cSBarry Smith   Note:
223420f4b53cSBarry Smith   If you want to customize this mesh using options, you just need to
223520f4b53cSBarry Smith .vb
223620f4b53cSBarry Smith   DMCreate(comm, &dm);
223720f4b53cSBarry Smith   DMSetType(dm, DMPLEX);
223820f4b53cSBarry Smith   DMSetFromOptions(dm);
223920f4b53cSBarry Smith .ve
224020f4b53cSBarry Smith   and use the options on the `DMSetFromOptions()` page.
2241cfb853baSMatthew G. Knepley 
2242cfb853baSMatthew G. Knepley   The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively,
224320f4b53cSBarry Smith .vb
224420f4b53cSBarry Smith  18--0-19--2-20--4-18
224520f4b53cSBarry Smith   |     |     |     |
224620f4b53cSBarry Smith  13    15    17    13
224720f4b53cSBarry Smith   |     |     |     |
224820f4b53cSBarry Smith  24-12-25-14-26-16-24
224920f4b53cSBarry Smith   |     |     |     |
225020f4b53cSBarry Smith   7     9    11     7
225120f4b53cSBarry Smith   |     |     |     |
225220f4b53cSBarry Smith  21--6-22--8-23-10-21
225320f4b53cSBarry Smith   |     |     |     |
225420f4b53cSBarry Smith   1     3     5     1
225520f4b53cSBarry Smith   |     |     |     |
225620f4b53cSBarry Smith  18--0-19--2-20--4-18
225720f4b53cSBarry Smith .ve
2258cfb853baSMatthew G. Knepley 
225976fbde31SPierre Jolivet .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()`
2260cfb853baSMatthew G. Knepley @*/
22618d2ec52aSSatish Balay PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], PetscInt overlap, DM *dm)
2262cfb853baSMatthew G. Knepley {
2263cfb853baSMatthew G. Knepley   PetscInt       *edg;
2264cfb853baSMatthew G. Knepley   PetscReal      *low, *upp;
2265cfb853baSMatthew G. Knepley   DMBoundaryType *bdt;
2266cfb853baSMatthew G. Knepley   PetscInt        d;
2267cfb853baSMatthew G. Knepley 
2268cfb853baSMatthew G. Knepley   PetscFunctionBegin;
2269cfb853baSMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
2270cfb853baSMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
2271cfb853baSMatthew G. Knepley   PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt));
2272cfb853baSMatthew G. Knepley   for (d = 0; d < dim; ++d) {
2273cfb853baSMatthew G. Knepley     edg[d] = edges ? edges[d] : 1;
2274cfb853baSMatthew G. Knepley     low[d] = lower ? lower[d] : 0.;
2275cfb853baSMatthew G. Knepley     upp[d] = upper ? upper[d] : 1.;
2276cfb853baSMatthew G. Knepley     bdt[d] = DM_BOUNDARY_PERIODIC;
2277cfb853baSMatthew G. Knepley   }
22788d2ec52aSSatish Balay   PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, overlap, bdt));
2279cfb853baSMatthew G. Knepley   PetscCall(PetscFree4(edg, low, upp, bdt));
22803ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2281cfb853baSMatthew G. Knepley }
2282cfb853baSMatthew G. Knepley 
2283cc4c1da9SBarry Smith /*@
2284a1cb98faSBarry Smith   DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database.
2285a9074c1eSMatthew G. Knepley 
228620f4b53cSBarry Smith   Logically Collective
2287a9074c1eSMatthew G. Knepley 
2288a9074c1eSMatthew G. Knepley   Input Parameters:
228920f4b53cSBarry Smith + dm     - the `DM` context
2290a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names
2291a9074c1eSMatthew G. Knepley 
2292a1cb98faSBarry Smith   Level: advanced
2293a1cb98faSBarry Smith 
2294a1cb98faSBarry Smith   Note:
2295a9074c1eSMatthew G. Knepley   A hyphen (-) must NOT be given at the beginning of the prefix name.
2296a9074c1eSMatthew G. Knepley   The first character of all runtime options is AUTOMATICALLY the hyphen.
2297a9074c1eSMatthew G. Knepley 
22981cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()`
2299a9074c1eSMatthew G. Knepley @*/
2300d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[])
2301d71ae5a4SJacob Faibussowitsch {
2302a9074c1eSMatthew G. Knepley   DM_Plex *mesh = (DM_Plex *)dm->data;
2303a9074c1eSMatthew G. Knepley 
2304a9074c1eSMatthew G. Knepley   PetscFunctionBegin;
2305a9074c1eSMatthew G. Knepley   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
23069566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix));
23079566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix));
23083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2309a9074c1eSMatthew G. Knepley }
2310a9074c1eSMatthew G. Knepley 
23119318fe57SMatthew G. Knepley /* Remap geometry to cylinder
231261a622f3SMatthew G. Knepley    TODO: This only works for a single refinement, then it is broken
231361a622f3SMatthew G. Knepley 
23149318fe57SMatthew G. Knepley      Interior square: Linear interpolation is correct
23159318fe57SMatthew G. Knepley      The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing
23169318fe57SMatthew G. Knepley      such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance
23170510c589SMatthew G. Knepley 
23189318fe57SMatthew G. Knepley        phi     = arctan(y/x)
23199318fe57SMatthew G. Knepley        d_close = sqrt(1/8 + 1/4 sin^2(phi))
23209318fe57SMatthew G. Knepley        d_far   = sqrt(1/2 + sin^2(phi))
23210510c589SMatthew G. Knepley 
23229318fe57SMatthew G. Knepley      so we remap them using
23230510c589SMatthew G. Knepley 
23249318fe57SMatthew G. Knepley        x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close)
23259318fe57SMatthew G. Knepley        y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close)
23260510c589SMatthew G. Knepley 
23279318fe57SMatthew G. Knepley      If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y.
23289318fe57SMatthew G. Knepley */
2329d71ae5a4SJacob 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[])
2330d71ae5a4SJacob Faibussowitsch {
23319318fe57SMatthew G. Knepley   const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
23329318fe57SMatthew G. Knepley   const PetscReal ds2 = 0.5 * dis;
233322cc497dSMatthew G. Knepley 
23349318fe57SMatthew G. Knepley   if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) {
23359318fe57SMatthew G. Knepley     f0[0] = u[0];
23369318fe57SMatthew G. Knepley     f0[1] = u[1];
23379318fe57SMatthew G. Knepley   } else {
23389318fe57SMatthew G. Knepley     PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc;
23390510c589SMatthew G. Knepley 
23409318fe57SMatthew G. Knepley     x    = PetscRealPart(u[0]);
23419318fe57SMatthew G. Knepley     y    = PetscRealPart(u[1]);
23429318fe57SMatthew G. Knepley     phi  = PetscAtan2Real(y, x);
23439318fe57SMatthew G. Knepley     sinp = PetscSinReal(phi);
23449318fe57SMatthew G. Knepley     cosp = PetscCosReal(phi);
23459318fe57SMatthew G. Knepley     if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) {
23469318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / sinp);
23479318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / sinp);
23489318fe57SMatthew G. Knepley       xc = ds2 * x / PetscAbsReal(y);
23499318fe57SMatthew G. Knepley       yc = ds2 * PetscSignReal(y);
23509318fe57SMatthew G. Knepley     } else {
23519318fe57SMatthew G. Knepley       dc = PetscAbsReal(ds2 / cosp);
23529318fe57SMatthew G. Knepley       df = PetscAbsReal(dis / cosp);
23539318fe57SMatthew G. Knepley       xc = ds2 * PetscSignReal(x);
23549318fe57SMatthew G. Knepley       yc = ds2 * y / PetscAbsReal(x);
23559318fe57SMatthew G. Knepley     }
23569318fe57SMatthew G. Knepley     f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc);
23579318fe57SMatthew G. Knepley     f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc);
23589318fe57SMatthew G. Knepley   }
23599318fe57SMatthew G. Knepley   f0[2] = u[2];
23609318fe57SMatthew G. Knepley }
23610510c589SMatthew G. Knepley 
236249704ca5SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ, PetscInt Nr)
2363d71ae5a4SJacob Faibussowitsch {
23640510c589SMatthew G. Knepley   const PetscInt dim = 3;
23659318fe57SMatthew G. Knepley   PetscInt       numCells, numVertices;
2366d8c47e87SMatthew G. Knepley   PetscMPIInt    rank;
23670510c589SMatthew G. Knepley 
23680510c589SMatthew G. Knepley   PetscFunctionBegin;
236946139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
23709566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
23719566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
23720510c589SMatthew G. Knepley   /* Create topology */
23730510c589SMatthew G. Knepley   {
23740510c589SMatthew G. Knepley     PetscInt cone[8], c;
23750510c589SMatthew G. Knepley 
2376dd400576SPatrick Sanan     numCells    = rank == 0 ? 5 : 0;
2377dd400576SPatrick Sanan     numVertices = rank == 0 ? 16 : 0;
2378006a8963SMatthew G. Knepley     if (periodicZ == DM_BOUNDARY_PERIODIC) {
2379ae8bcbbbSMatthew G. Knepley       numCells *= 3;
2380dd400576SPatrick Sanan       numVertices = rank == 0 ? 24 : 0;
2381006a8963SMatthew G. Knepley     }
23829566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
23839566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8));
23849566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
2385dd400576SPatrick Sanan     if (rank == 0) {
2386006a8963SMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
23879371c9d4SSatish Balay         cone[0] = 15;
23889371c9d4SSatish Balay         cone[1] = 18;
23899371c9d4SSatish Balay         cone[2] = 17;
23909371c9d4SSatish Balay         cone[3] = 16;
23919371c9d4SSatish Balay         cone[4] = 31;
23929371c9d4SSatish Balay         cone[5] = 32;
23939371c9d4SSatish Balay         cone[6] = 33;
23949371c9d4SSatish Balay         cone[7] = 34;
23959566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
23969371c9d4SSatish Balay         cone[0] = 16;
23979371c9d4SSatish Balay         cone[1] = 17;
23989371c9d4SSatish Balay         cone[2] = 24;
23999371c9d4SSatish Balay         cone[3] = 23;
24009371c9d4SSatish Balay         cone[4] = 32;
24019371c9d4SSatish Balay         cone[5] = 36;
24029371c9d4SSatish Balay         cone[6] = 37;
24039371c9d4SSatish Balay         cone[7] = 33; /* 22 25 26 21 */
24049566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
24059371c9d4SSatish Balay         cone[0] = 18;
24069371c9d4SSatish Balay         cone[1] = 27;
24079371c9d4SSatish Balay         cone[2] = 24;
24089371c9d4SSatish Balay         cone[3] = 17;
24099371c9d4SSatish Balay         cone[4] = 34;
24109371c9d4SSatish Balay         cone[5] = 33;
24119371c9d4SSatish Balay         cone[6] = 37;
24129371c9d4SSatish Balay         cone[7] = 38;
24139566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
24149371c9d4SSatish Balay         cone[0] = 29;
24159371c9d4SSatish Balay         cone[1] = 27;
24169371c9d4SSatish Balay         cone[2] = 18;
24179371c9d4SSatish Balay         cone[3] = 15;
24189371c9d4SSatish Balay         cone[4] = 35;
24199371c9d4SSatish Balay         cone[5] = 31;
24209371c9d4SSatish Balay         cone[6] = 34;
24219371c9d4SSatish Balay         cone[7] = 38;
24229566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
24239371c9d4SSatish Balay         cone[0] = 29;
24249371c9d4SSatish Balay         cone[1] = 15;
24259371c9d4SSatish Balay         cone[2] = 16;
24269371c9d4SSatish Balay         cone[3] = 23;
24279371c9d4SSatish Balay         cone[4] = 35;
24289371c9d4SSatish Balay         cone[5] = 36;
24299371c9d4SSatish Balay         cone[6] = 32;
24309371c9d4SSatish Balay         cone[7] = 31;
24319566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
2432006a8963SMatthew G. Knepley 
24339371c9d4SSatish Balay         cone[0] = 31;
24349371c9d4SSatish Balay         cone[1] = 34;
24359371c9d4SSatish Balay         cone[2] = 33;
24369371c9d4SSatish Balay         cone[3] = 32;
24379371c9d4SSatish Balay         cone[4] = 19;
24389371c9d4SSatish Balay         cone[5] = 22;
24399371c9d4SSatish Balay         cone[6] = 21;
24409371c9d4SSatish Balay         cone[7] = 20;
24419566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
24429371c9d4SSatish Balay         cone[0] = 32;
24439371c9d4SSatish Balay         cone[1] = 33;
24449371c9d4SSatish Balay         cone[2] = 37;
24459371c9d4SSatish Balay         cone[3] = 36;
24469371c9d4SSatish Balay         cone[4] = 22;
24479371c9d4SSatish Balay         cone[5] = 25;
24489371c9d4SSatish Balay         cone[6] = 26;
24499371c9d4SSatish Balay         cone[7] = 21;
24509566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 6, cone));
24519371c9d4SSatish Balay         cone[0] = 34;
24529371c9d4SSatish Balay         cone[1] = 38;
24539371c9d4SSatish Balay         cone[2] = 37;
24549371c9d4SSatish Balay         cone[3] = 33;
24559371c9d4SSatish Balay         cone[4] = 20;
24569371c9d4SSatish Balay         cone[5] = 21;
24579371c9d4SSatish Balay         cone[6] = 26;
24589371c9d4SSatish Balay         cone[7] = 28;
24599566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 7, cone));
24609371c9d4SSatish Balay         cone[0] = 35;
24619371c9d4SSatish Balay         cone[1] = 38;
24629371c9d4SSatish Balay         cone[2] = 34;
24639371c9d4SSatish Balay         cone[3] = 31;
24649371c9d4SSatish Balay         cone[4] = 30;
24659371c9d4SSatish Balay         cone[5] = 19;
24669371c9d4SSatish Balay         cone[6] = 20;
24679371c9d4SSatish Balay         cone[7] = 28;
24689566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 8, cone));
24699371c9d4SSatish Balay         cone[0] = 35;
24709371c9d4SSatish Balay         cone[1] = 31;
24719371c9d4SSatish Balay         cone[2] = 32;
24729371c9d4SSatish Balay         cone[3] = 36;
24739371c9d4SSatish Balay         cone[4] = 30;
24749371c9d4SSatish Balay         cone[5] = 25;
24759371c9d4SSatish Balay         cone[6] = 22;
24769371c9d4SSatish Balay         cone[7] = 19;
24779566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 9, cone));
2478ae8bcbbbSMatthew G. Knepley 
24799371c9d4SSatish Balay         cone[0] = 19;
24809371c9d4SSatish Balay         cone[1] = 20;
24819371c9d4SSatish Balay         cone[2] = 21;
24829371c9d4SSatish Balay         cone[3] = 22;
24839371c9d4SSatish Balay         cone[4] = 15;
24849371c9d4SSatish Balay         cone[5] = 16;
24859371c9d4SSatish Balay         cone[6] = 17;
24869371c9d4SSatish Balay         cone[7] = 18;
24879566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 10, cone));
24889371c9d4SSatish Balay         cone[0] = 22;
24899371c9d4SSatish Balay         cone[1] = 21;
24909371c9d4SSatish Balay         cone[2] = 26;
24919371c9d4SSatish Balay         cone[3] = 25;
24929371c9d4SSatish Balay         cone[4] = 16;
24939371c9d4SSatish Balay         cone[5] = 23;
24949371c9d4SSatish Balay         cone[6] = 24;
24959371c9d4SSatish Balay         cone[7] = 17;
24969566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 11, cone));
24979371c9d4SSatish Balay         cone[0] = 20;
24989371c9d4SSatish Balay         cone[1] = 28;
24999371c9d4SSatish Balay         cone[2] = 26;
25009371c9d4SSatish Balay         cone[3] = 21;
25019371c9d4SSatish Balay         cone[4] = 18;
25029371c9d4SSatish Balay         cone[5] = 17;
25039371c9d4SSatish Balay         cone[6] = 24;
25049371c9d4SSatish Balay         cone[7] = 27;
25059566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 12, cone));
25069371c9d4SSatish Balay         cone[0] = 30;
25079371c9d4SSatish Balay         cone[1] = 28;
25089371c9d4SSatish Balay         cone[2] = 20;
25099371c9d4SSatish Balay         cone[3] = 19;
25109371c9d4SSatish Balay         cone[4] = 29;
25119371c9d4SSatish Balay         cone[5] = 15;
25129371c9d4SSatish Balay         cone[6] = 18;
25139371c9d4SSatish Balay         cone[7] = 27;
25149566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 13, cone));
25159371c9d4SSatish Balay         cone[0] = 30;
25169371c9d4SSatish Balay         cone[1] = 19;
25179371c9d4SSatish Balay         cone[2] = 22;
25189371c9d4SSatish Balay         cone[3] = 25;
25199371c9d4SSatish Balay         cone[4] = 29;
25209371c9d4SSatish Balay         cone[5] = 23;
25219371c9d4SSatish Balay         cone[6] = 16;
25229371c9d4SSatish Balay         cone[7] = 15;
25239566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
2524006a8963SMatthew G. Knepley       } else {
25259371c9d4SSatish Balay         cone[0] = 5;
25269371c9d4SSatish Balay         cone[1] = 8;
25279371c9d4SSatish Balay         cone[2] = 7;
25289371c9d4SSatish Balay         cone[3] = 6;
25299371c9d4SSatish Balay         cone[4] = 9;
25309371c9d4SSatish Balay         cone[5] = 12;
25319371c9d4SSatish Balay         cone[6] = 11;
25329371c9d4SSatish Balay         cone[7] = 10;
25339566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
25349371c9d4SSatish Balay         cone[0] = 6;
25359371c9d4SSatish Balay         cone[1] = 7;
25369371c9d4SSatish Balay         cone[2] = 14;
25379371c9d4SSatish Balay         cone[3] = 13;
25389371c9d4SSatish Balay         cone[4] = 12;
25399371c9d4SSatish Balay         cone[5] = 15;
25409371c9d4SSatish Balay         cone[6] = 16;
25419371c9d4SSatish Balay         cone[7] = 11;
25429566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
25439371c9d4SSatish Balay         cone[0] = 8;
25449371c9d4SSatish Balay         cone[1] = 17;
25459371c9d4SSatish Balay         cone[2] = 14;
25469371c9d4SSatish Balay         cone[3] = 7;
25479371c9d4SSatish Balay         cone[4] = 10;
25489371c9d4SSatish Balay         cone[5] = 11;
25499371c9d4SSatish Balay         cone[6] = 16;
25509371c9d4SSatish Balay         cone[7] = 18;
25519566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
25529371c9d4SSatish Balay         cone[0] = 19;
25539371c9d4SSatish Balay         cone[1] = 17;
25549371c9d4SSatish Balay         cone[2] = 8;
25559371c9d4SSatish Balay         cone[3] = 5;
25569371c9d4SSatish Balay         cone[4] = 20;
25579371c9d4SSatish Balay         cone[5] = 9;
25589371c9d4SSatish Balay         cone[6] = 10;
25599371c9d4SSatish Balay         cone[7] = 18;
25609566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
25619371c9d4SSatish Balay         cone[0] = 19;
25629371c9d4SSatish Balay         cone[1] = 5;
25639371c9d4SSatish Balay         cone[2] = 6;
25649371c9d4SSatish Balay         cone[3] = 13;
25659371c9d4SSatish Balay         cone[4] = 20;
25669371c9d4SSatish Balay         cone[5] = 15;
25679371c9d4SSatish Balay         cone[6] = 12;
25689371c9d4SSatish Balay         cone[7] = 9;
25699566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
2570006a8963SMatthew G. Knepley       }
2571d8c47e87SMatthew G. Knepley     }
25729566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
25739566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
25740510c589SMatthew G. Knepley   }
2575dbc1dc17SMatthew G. Knepley   /* Create cube geometry */
25760510c589SMatthew G. Knepley   {
25770510c589SMatthew G. Knepley     Vec             coordinates;
25780510c589SMatthew G. Knepley     PetscSection    coordSection;
25790510c589SMatthew G. Knepley     PetscScalar    *coords;
25800510c589SMatthew G. Knepley     PetscInt        coordSize, v;
25810510c589SMatthew G. Knepley     const PetscReal dis = 1.0 / PetscSqrtReal(2.0);
25820510c589SMatthew G. Knepley     const PetscReal ds2 = dis / 2.0;
25830510c589SMatthew G. Knepley 
25840510c589SMatthew G. Knepley     /* Build coordinates */
25859566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
25869566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
25879566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
25889566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
25890510c589SMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
25909566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
25919566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
25920510c589SMatthew G. Knepley     }
25939566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
25949566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
25959566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
25969566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
25979566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
25989566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
25999566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
26009566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
2601dd400576SPatrick Sanan     if (rank == 0) {
26029371c9d4SSatish Balay       coords[0 * dim + 0]  = -ds2;
26039371c9d4SSatish Balay       coords[0 * dim + 1]  = -ds2;
26049371c9d4SSatish Balay       coords[0 * dim + 2]  = 0.0;
26059371c9d4SSatish Balay       coords[1 * dim + 0]  = ds2;
26069371c9d4SSatish Balay       coords[1 * dim + 1]  = -ds2;
26079371c9d4SSatish Balay       coords[1 * dim + 2]  = 0.0;
26089371c9d4SSatish Balay       coords[2 * dim + 0]  = ds2;
26099371c9d4SSatish Balay       coords[2 * dim + 1]  = ds2;
26109371c9d4SSatish Balay       coords[2 * dim + 2]  = 0.0;
26119371c9d4SSatish Balay       coords[3 * dim + 0]  = -ds2;
26129371c9d4SSatish Balay       coords[3 * dim + 1]  = ds2;
26139371c9d4SSatish Balay       coords[3 * dim + 2]  = 0.0;
26149371c9d4SSatish Balay       coords[4 * dim + 0]  = -ds2;
26159371c9d4SSatish Balay       coords[4 * dim + 1]  = -ds2;
26169371c9d4SSatish Balay       coords[4 * dim + 2]  = 1.0;
26179371c9d4SSatish Balay       coords[5 * dim + 0]  = -ds2;
26189371c9d4SSatish Balay       coords[5 * dim + 1]  = ds2;
26199371c9d4SSatish Balay       coords[5 * dim + 2]  = 1.0;
26209371c9d4SSatish Balay       coords[6 * dim + 0]  = ds2;
26219371c9d4SSatish Balay       coords[6 * dim + 1]  = ds2;
26229371c9d4SSatish Balay       coords[6 * dim + 2]  = 1.0;
26239371c9d4SSatish Balay       coords[7 * dim + 0]  = ds2;
26249371c9d4SSatish Balay       coords[7 * dim + 1]  = -ds2;
26259371c9d4SSatish Balay       coords[7 * dim + 2]  = 1.0;
26269371c9d4SSatish Balay       coords[8 * dim + 0]  = dis;
26279371c9d4SSatish Balay       coords[8 * dim + 1]  = -dis;
26289371c9d4SSatish Balay       coords[8 * dim + 2]  = 0.0;
26299371c9d4SSatish Balay       coords[9 * dim + 0]  = dis;
26309371c9d4SSatish Balay       coords[9 * dim + 1]  = dis;
26319371c9d4SSatish Balay       coords[9 * dim + 2]  = 0.0;
26329371c9d4SSatish Balay       coords[10 * dim + 0] = dis;
26339371c9d4SSatish Balay       coords[10 * dim + 1] = -dis;
26349371c9d4SSatish Balay       coords[10 * dim + 2] = 1.0;
26359371c9d4SSatish Balay       coords[11 * dim + 0] = dis;
26369371c9d4SSatish Balay       coords[11 * dim + 1] = dis;
26379371c9d4SSatish Balay       coords[11 * dim + 2] = 1.0;
26389371c9d4SSatish Balay       coords[12 * dim + 0] = -dis;
26399371c9d4SSatish Balay       coords[12 * dim + 1] = dis;
26409371c9d4SSatish Balay       coords[12 * dim + 2] = 0.0;
26419371c9d4SSatish Balay       coords[13 * dim + 0] = -dis;
26429371c9d4SSatish Balay       coords[13 * dim + 1] = dis;
26439371c9d4SSatish Balay       coords[13 * dim + 2] = 1.0;
26449371c9d4SSatish Balay       coords[14 * dim + 0] = -dis;
26459371c9d4SSatish Balay       coords[14 * dim + 1] = -dis;
26469371c9d4SSatish Balay       coords[14 * dim + 2] = 0.0;
26479371c9d4SSatish Balay       coords[15 * dim + 0] = -dis;
26489371c9d4SSatish Balay       coords[15 * dim + 1] = -dis;
26499371c9d4SSatish Balay       coords[15 * dim + 2] = 1.0;
2650ae8bcbbbSMatthew G. Knepley       if (periodicZ == DM_BOUNDARY_PERIODIC) {
26519371c9d4SSatish Balay         /* 15 31 19 */ coords[16 * dim + 0] = -ds2;
26529371c9d4SSatish Balay         coords[16 * dim + 1]                = -ds2;
26539371c9d4SSatish Balay         coords[16 * dim + 2]                = 0.5;
26549371c9d4SSatish Balay         /* 16 32 22 */ coords[17 * dim + 0] = ds2;
26559371c9d4SSatish Balay         coords[17 * dim + 1]                = -ds2;
26569371c9d4SSatish Balay         coords[17 * dim + 2]                = 0.5;
26579371c9d4SSatish Balay         /* 17 33 21 */ coords[18 * dim + 0] = ds2;
26589371c9d4SSatish Balay         coords[18 * dim + 1]                = ds2;
26599371c9d4SSatish Balay         coords[18 * dim + 2]                = 0.5;
26609371c9d4SSatish Balay         /* 18 34 20 */ coords[19 * dim + 0] = -ds2;
26619371c9d4SSatish Balay         coords[19 * dim + 1]                = ds2;
26629371c9d4SSatish Balay         coords[19 * dim + 2]                = 0.5;
26639371c9d4SSatish Balay         /* 29 35 30 */ coords[20 * dim + 0] = -dis;
26649371c9d4SSatish Balay         coords[20 * dim + 1]                = -dis;
26659371c9d4SSatish Balay         coords[20 * dim + 2]                = 0.5;
26669371c9d4SSatish Balay         /* 23 36 25 */ coords[21 * dim + 0] = dis;
26679371c9d4SSatish Balay         coords[21 * dim + 1]                = -dis;
26689371c9d4SSatish Balay         coords[21 * dim + 2]                = 0.5;
26699371c9d4SSatish Balay         /* 24 37 26 */ coords[22 * dim + 0] = dis;
26709371c9d4SSatish Balay         coords[22 * dim + 1]                = dis;
26719371c9d4SSatish Balay         coords[22 * dim + 2]                = 0.5;
26729371c9d4SSatish Balay         /* 27 38 28 */ coords[23 * dim + 0] = -dis;
26739371c9d4SSatish Balay         coords[23 * dim + 1]                = dis;
26749371c9d4SSatish Balay         coords[23 * dim + 2]                = 0.5;
2675ae8bcbbbSMatthew G. Knepley       }
2676d8c47e87SMatthew G. Knepley     }
26779566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
26789566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
26799566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
26800510c589SMatthew G. Knepley   }
2681006a8963SMatthew G. Knepley   /* Create periodicity */
2682006a8963SMatthew G. Knepley   if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) {
26836858538eSMatthew G. Knepley     PetscReal L[3]       = {-1., -1., 0.};
26846858538eSMatthew G. Knepley     PetscReal maxCell[3] = {-1., -1., 0.};
2685006a8963SMatthew G. Knepley     PetscReal lower[3]   = {0.0, 0.0, 0.0};
2686ae8bcbbbSMatthew G. Knepley     PetscReal upper[3]   = {1.0, 1.0, 1.5};
26876858538eSMatthew G. Knepley     PetscInt  numZCells  = 3;
2688006a8963SMatthew G. Knepley 
26896858538eSMatthew G. Knepley     L[2]       = upper[2] - lower[2];
26906858538eSMatthew G. Knepley     maxCell[2] = 1.1 * (L[2] / numZCells);
26914fb89dddSMatthew G. Knepley     PetscCall(DMSetPeriodicity(dm, maxCell, lower, L));
2692006a8963SMatthew G. Knepley   }
2693dbc1dc17SMatthew G. Knepley   {
26949318fe57SMatthew G. Knepley     DM          cdm;
26959318fe57SMatthew G. Knepley     PetscDS     cds;
26969318fe57SMatthew G. Knepley     PetscScalar c[2] = {1.0, 1.0};
2697dbc1dc17SMatthew G. Knepley 
269849704ca5SMatthew G. Knepley     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL));
26999566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
27009566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
27019566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 2, c));
2702dbc1dc17SMatthew G. Knepley   }
270346139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
270446139095SJed Brown 
27059318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
27069566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(dm));
270749704ca5SMatthew G. Knepley 
270849704ca5SMatthew G. Knepley   char        oldprefix[PETSC_MAX_PATH_LEN];
270949704ca5SMatthew G. Knepley   const char *prefix;
271049704ca5SMatthew G. Knepley 
271149704ca5SMatthew G. Knepley   PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
271249704ca5SMatthew G. Knepley   PetscCall(PetscStrncpy(oldprefix, prefix, PETSC_MAX_PATH_LEN));
271349704ca5SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, "petsc_cyl_ref_"));
271449704ca5SMatthew G. Knepley   for (PetscInt r = 0; r < PetscMax(0, Nr); ++r) {
271549704ca5SMatthew G. Knepley     DM rdm;
271649704ca5SMatthew G. Knepley 
271749704ca5SMatthew G. Knepley     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
271849704ca5SMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &rdm));
271949704ca5SMatthew G. Knepley   }
272049704ca5SMatthew G. Knepley   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldprefix));
272149704ca5SMatthew G. Knepley   PetscCall(DMPlexRemapGeometry(dm, 0.0, snapToCylinder));
272249704ca5SMatthew G. Knepley 
272349704ca5SMatthew G. Knepley   DMLabel         bdlabel, edgelabel;
272449704ca5SMatthew G. Knepley   IS              faceIS;
272549704ca5SMatthew G. Knepley   const PetscInt *faces;
272649704ca5SMatthew G. Knepley   PetscInt        Nf;
272749704ca5SMatthew G. Knepley 
272849704ca5SMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "marker"));
272949704ca5SMatthew G. Knepley   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
273049704ca5SMatthew G. Knepley   PetscCall(DMCreateLabel(dm, "generatrix"));
273149704ca5SMatthew G. Knepley   PetscCall(DMGetLabel(dm, "generatrix", &edgelabel));
273249704ca5SMatthew G. Knepley   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
273349704ca5SMatthew G. Knepley   // Remove faces on top and bottom
273449704ca5SMatthew G. Knepley   PetscCall(DMLabelGetStratumIS(bdlabel, 1, &faceIS));
2735ba1b3593SJeremy L Thompson   if (faceIS) {
273649704ca5SMatthew G. Knepley     PetscCall(ISGetLocalSize(faceIS, &Nf));
273749704ca5SMatthew G. Knepley     PetscCall(ISGetIndices(faceIS, &faces));
273849704ca5SMatthew G. Knepley     for (PetscInt f = 0; f < Nf; ++f) {
273949704ca5SMatthew G. Knepley       PetscReal vol, normal[3];
274049704ca5SMatthew G. Knepley 
274149704ca5SMatthew G. Knepley       PetscCall(DMPlexComputeCellGeometryFVM(dm, faces[f], &vol, NULL, normal));
274249704ca5SMatthew G. Knepley       if (PetscAbsReal(normal[2]) < PETSC_SMALL) PetscCall(DMLabelSetValue(edgelabel, faces[f], 1));
274349704ca5SMatthew G. Knepley     }
274449704ca5SMatthew G. Knepley     PetscCall(ISRestoreIndices(faceIS, &faces));
274549704ca5SMatthew G. Knepley     PetscCall(ISDestroy(&faceIS));
2746ba1b3593SJeremy L Thompson   }
274749704ca5SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(dm, bdlabel));
274849704ca5SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(dm, edgelabel));
27493ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
27500510c589SMatthew G. Knepley }
27510510c589SMatthew G. Knepley 
275224119c2aSMatthew G. Knepley /*@
27539318fe57SMatthew G. Knepley   DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra.
275424119c2aSMatthew G. Knepley 
2755d083f849SBarry Smith   Collective
275624119c2aSMatthew G. Knepley 
275724119c2aSMatthew G. Knepley   Input Parameters:
2758a1cb98faSBarry Smith + comm      - The communicator for the `DM` object
275949704ca5SMatthew G. Knepley . periodicZ - The boundary type for the Z direction
276049704ca5SMatthew G. Knepley - Nr        - The number of refinements to carry out
276124119c2aSMatthew G. Knepley 
276224119c2aSMatthew G. Knepley   Output Parameter:
276320f4b53cSBarry Smith . dm - The `DM` object
276424119c2aSMatthew G. Knepley 
276524119c2aSMatthew G. Knepley   Level: beginner
276624119c2aSMatthew G. Knepley 
2767a1cb98faSBarry Smith   Note:
2768a4e35b19SJacob Faibussowitsch   Here is the output numbering looking from the bottom of the cylinder\:
2769a1cb98faSBarry Smith .vb
2770a1cb98faSBarry Smith        17-----14
2771a1cb98faSBarry Smith         |     |
2772a1cb98faSBarry Smith         |  2  |
2773a1cb98faSBarry Smith         |     |
2774a1cb98faSBarry Smith  17-----8-----7-----14
2775a1cb98faSBarry Smith   |     |     |     |
2776a1cb98faSBarry Smith   |  3  |  0  |  1  |
2777a1cb98faSBarry Smith   |     |     |     |
2778a1cb98faSBarry Smith  19-----5-----6-----13
2779a1cb98faSBarry Smith         |     |
2780a1cb98faSBarry Smith         |  4  |
2781a1cb98faSBarry Smith         |     |
2782a1cb98faSBarry Smith        19-----13
2783a1cb98faSBarry Smith 
2784a1cb98faSBarry Smith  and up through the top
2785a1cb98faSBarry Smith 
2786a1cb98faSBarry Smith        18-----16
2787a1cb98faSBarry Smith         |     |
2788a1cb98faSBarry Smith         |  2  |
2789a1cb98faSBarry Smith         |     |
2790a1cb98faSBarry Smith  18----10----11-----16
2791a1cb98faSBarry Smith   |     |     |     |
2792a1cb98faSBarry Smith   |  3  |  0  |  1  |
2793a1cb98faSBarry Smith   |     |     |     |
2794a1cb98faSBarry Smith  20-----9----12-----15
2795a1cb98faSBarry Smith         |     |
2796a1cb98faSBarry Smith         |  4  |
2797a1cb98faSBarry Smith         |     |
2798a1cb98faSBarry Smith        20-----15
2799a1cb98faSBarry Smith .ve
2800a1cb98faSBarry Smith 
28011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
280224119c2aSMatthew G. Knepley @*/
280349704ca5SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, PetscInt Nr, DM *dm)
2804d71ae5a4SJacob Faibussowitsch {
28059318fe57SMatthew G. Knepley   PetscFunctionBegin;
280649704ca5SMatthew G. Knepley   PetscAssertPointer(dm, 4);
28079566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
28089566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
280949704ca5SMatthew G. Knepley   PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ, Nr));
28103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28119318fe57SMatthew G. Knepley }
28129318fe57SMatthew G. Knepley 
2813d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate)
2814d71ae5a4SJacob Faibussowitsch {
281524119c2aSMatthew G. Knepley   const PetscInt dim = 3;
2816412e9a14SMatthew G. Knepley   PetscInt       numCells, numVertices, v;
28179fe9f049SMatthew G. Knepley   PetscMPIInt    rank;
281824119c2aSMatthew G. Knepley 
281924119c2aSMatthew G. Knepley   PetscFunctionBegin;
282063a3b9bcSJacob Faibussowitsch   PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n);
282146139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
28229566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
28239566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
2824412e9a14SMatthew G. Knepley   /* Must create the celltype label here so that we do not automatically try to compute the types */
28259566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "celltype"));
282624119c2aSMatthew G. Knepley   /* Create topology */
282724119c2aSMatthew G. Knepley   {
282824119c2aSMatthew G. Knepley     PetscInt cone[6], c;
282924119c2aSMatthew G. Knepley 
2830dd400576SPatrick Sanan     numCells    = rank == 0 ? n : 0;
2831dd400576SPatrick Sanan     numVertices = rank == 0 ? 2 * (n + 1) : 0;
28329566063dSJacob Faibussowitsch     PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
28339566063dSJacob Faibussowitsch     for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6));
28349566063dSJacob Faibussowitsch     PetscCall(DMSetUp(dm));
283524119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
28369371c9d4SSatish Balay       cone[0] = c + n * 1;
28379371c9d4SSatish Balay       cone[1] = (c + 1) % n + n * 1;
28389371c9d4SSatish Balay       cone[2] = 0 + 3 * n;
28399371c9d4SSatish Balay       cone[3] = c + n * 2;
28409371c9d4SSatish Balay       cone[4] = (c + 1) % n + n * 2;
28419371c9d4SSatish Balay       cone[5] = 1 + 3 * n;
28429566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(dm, c, cone));
28439566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR));
284424119c2aSMatthew G. Knepley     }
28459566063dSJacob Faibussowitsch     PetscCall(DMPlexSymmetrize(dm));
28469566063dSJacob Faibussowitsch     PetscCall(DMPlexStratify(dm));
284724119c2aSMatthew G. Knepley   }
284848a46eb9SPierre Jolivet   for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT));
284924119c2aSMatthew G. Knepley   /* Create cylinder geometry */
285024119c2aSMatthew G. Knepley   {
285124119c2aSMatthew G. Knepley     Vec          coordinates;
285224119c2aSMatthew G. Knepley     PetscSection coordSection;
285324119c2aSMatthew G. Knepley     PetscScalar *coords;
2854412e9a14SMatthew G. Knepley     PetscInt     coordSize, c;
285524119c2aSMatthew G. Knepley 
285624119c2aSMatthew G. Knepley     /* Build coordinates */
28579566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateSection(dm, &coordSection));
28589566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetNumFields(coordSection, 1));
28599566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim));
28609566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
286124119c2aSMatthew G. Knepley     for (v = numCells; v < numCells + numVertices; ++v) {
28629566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetDof(coordSection, v, dim));
28639566063dSJacob Faibussowitsch       PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim));
286424119c2aSMatthew G. Knepley     }
28659566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
28669566063dSJacob Faibussowitsch     PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
28679566063dSJacob Faibussowitsch     PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
28689566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
28699566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
28709566063dSJacob Faibussowitsch     PetscCall(VecSetBlockSize(coordinates, dim));
28719566063dSJacob Faibussowitsch     PetscCall(VecSetType(coordinates, VECSTANDARD));
28729566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
287324119c2aSMatthew G. Knepley     for (c = 0; c < numCells; c++) {
28749371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
28759371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
28769371c9d4SSatish Balay       coords[(c + 0 * n) * dim + 2] = 1.0;
28779371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n);
28789371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n);
28799371c9d4SSatish Balay       coords[(c + 1 * n) * dim + 2] = 0.0;
288024119c2aSMatthew G. Knepley     }
2881dd400576SPatrick Sanan     if (rank == 0) {
28829371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 0] = 0.0;
28839371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 1] = 0.0;
28849371c9d4SSatish Balay       coords[(2 * n + 0) * dim + 2] = 1.0;
28859371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 0] = 0.0;
28869371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 1] = 0.0;
28879371c9d4SSatish Balay       coords[(2 * n + 1) * dim + 2] = 0.0;
28889fe9f049SMatthew G. Knepley     }
28899566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(coordinates, &coords));
28909566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinatesLocal(dm, coordinates));
28919566063dSJacob Faibussowitsch     PetscCall(VecDestroy(&coordinates));
289224119c2aSMatthew G. Knepley   }
289346139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
28949318fe57SMatthew G. Knepley   /* Interpolate */
28959566063dSJacob Faibussowitsch   if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
28963ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
28979318fe57SMatthew G. Knepley }
28989318fe57SMatthew G. Knepley 
28999318fe57SMatthew G. Knepley /*@
29009318fe57SMatthew G. Knepley   DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges.
29019318fe57SMatthew G. Knepley 
29029318fe57SMatthew G. Knepley   Collective
29039318fe57SMatthew G. Knepley 
29049318fe57SMatthew G. Knepley   Input Parameters:
2905a1cb98faSBarry Smith + comm        - The communicator for the `DM` object
29069318fe57SMatthew G. Knepley . n           - The number of wedges around the origin
29079318fe57SMatthew G. Knepley - interpolate - Create edges and faces
29089318fe57SMatthew G. Knepley 
29099318fe57SMatthew G. Knepley   Output Parameter:
2910a1cb98faSBarry Smith . dm - The `DM` object
29119318fe57SMatthew G. Knepley 
29129318fe57SMatthew G. Knepley   Level: beginner
29139318fe57SMatthew G. Knepley 
29141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
29159318fe57SMatthew G. Knepley @*/
2916d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm)
2917d71ae5a4SJacob Faibussowitsch {
29189318fe57SMatthew G. Knepley   PetscFunctionBegin;
29194f572ea9SToby Isaac   PetscAssertPointer(dm, 4);
29209566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
29219566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
29229566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate));
29233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
292424119c2aSMatthew G. Knepley }
292524119c2aSMatthew G. Knepley 
2926d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2927d71ae5a4SJacob Faibussowitsch {
292865a81367SMatthew G. Knepley   PetscReal prod = 0.0;
292965a81367SMatthew G. Knepley   PetscInt  i;
293065a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]);
293165a81367SMatthew G. Knepley   return PetscSqrtReal(prod);
293265a81367SMatthew G. Knepley }
2933dd2b43ebSStefano Zampini 
2934d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[])
2935d71ae5a4SJacob Faibussowitsch {
293665a81367SMatthew G. Knepley   PetscReal prod = 0.0;
293765a81367SMatthew G. Knepley   PetscInt  i;
293865a81367SMatthew G. Knepley   for (i = 0; i < dim; ++i) prod += x[i] * y[i];
293965a81367SMatthew G. Knepley   return prod;
294065a81367SMatthew G. Knepley }
294165a81367SMatthew G. Knepley 
294251a74b61SMatthew G. Knepley /* The first constant is the sphere radius */
2943d71ae5a4SJacob 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[])
2944d71ae5a4SJacob Faibussowitsch {
294551a74b61SMatthew G. Knepley   PetscReal r     = PetscRealPart(constants[0]);
294651a74b61SMatthew G. Knepley   PetscReal norm2 = 0.0, fac;
294751a74b61SMatthew G. Knepley   PetscInt  n     = uOff[1] - uOff[0], d;
294851a74b61SMatthew G. Knepley 
294951a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d]));
295051a74b61SMatthew G. Knepley   fac = r / PetscSqrtReal(norm2);
295151a74b61SMatthew G. Knepley   for (d = 0; d < n; ++d) f0[d] = u[d] * fac;
295251a74b61SMatthew G. Knepley }
295351a74b61SMatthew G. Knepley 
2954d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R)
2955d71ae5a4SJacob Faibussowitsch {
295665a81367SMatthew G. Knepley   const PetscInt embedDim = dim + 1;
295765a81367SMatthew G. Knepley   PetscSection   coordSection;
295865a81367SMatthew G. Knepley   Vec            coordinates;
295965a81367SMatthew G. Knepley   PetscScalar   *coords;
296065a81367SMatthew G. Knepley   PetscReal     *coordsIn;
296107c565c5SJose E. Roman   PetscInt       numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, e;
296265a81367SMatthew G. Knepley   PetscMPIInt    rank;
296365a81367SMatthew G. Knepley 
296465a81367SMatthew G. Knepley   PetscFunctionBegin;
29659318fe57SMatthew G. Knepley   PetscValidLogicalCollectiveBool(dm, simplex, 3);
296646139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
29679566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, dim));
29689566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, dim + 1));
29699566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
297065a81367SMatthew G. Knepley   switch (dim) {
29715c344501SMatthew G. Knepley   case 1:
29725c344501SMatthew G. Knepley     numCells = 16;
29735c344501SMatthew G. Knepley     numVerts = numCells;
29745c344501SMatthew G. Knepley 
29755c344501SMatthew G. Knepley     // Build Topology
29765c344501SMatthew G. Knepley     PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
29775c344501SMatthew G. Knepley     for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
29785c344501SMatthew G. Knepley     PetscCall(DMSetUp(dm));
29795c344501SMatthew G. Knepley     for (PetscInt c = 0; c < numCells; ++c) {
29805c344501SMatthew G. Knepley       PetscInt cone[2];
29815c344501SMatthew G. Knepley 
29825c344501SMatthew G. Knepley       cone[0] = c + numCells;
29835c344501SMatthew G. Knepley       cone[1] = (c + 1) % numVerts + numCells;
29845c344501SMatthew G. Knepley       PetscCall(DMPlexSetCone(dm, c, cone));
29855c344501SMatthew G. Knepley     }
29865c344501SMatthew G. Knepley     PetscCall(DMPlexSymmetrize(dm));
29875c344501SMatthew G. Knepley     PetscCall(DMPlexStratify(dm));
29885c344501SMatthew G. Knepley     PetscCall(PetscMalloc1(numVerts * embedDim, &coordsIn));
29895c344501SMatthew G. Knepley     for (PetscInt v = 0; v < numVerts; ++v) {
29905c344501SMatthew G. Knepley       const PetscReal rad = 2. * PETSC_PI * v / numVerts;
29915c344501SMatthew G. Knepley 
29925c344501SMatthew G. Knepley       coordsIn[v * embedDim + 0] = PetscCosReal(rad);
29935c344501SMatthew G. Knepley       coordsIn[v * embedDim + 1] = PetscSinReal(rad);
29945c344501SMatthew G. Knepley     }
29955c344501SMatthew G. Knepley     break;
299665a81367SMatthew G. Knepley   case 2:
299765a81367SMatthew G. Knepley     if (simplex) {
299851a74b61SMatthew G. Knepley       const PetscReal radius    = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI);
299951a74b61SMatthew G. Knepley       const PetscReal edgeLen   = 2.0 / (1.0 + PETSC_PHI) * (R / radius);
300065a81367SMatthew G. Knepley       const PetscInt  degree    = 5;
300151a74b61SMatthew G. Knepley       PetscReal       vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)};
300265a81367SMatthew G. Knepley       PetscInt        s[3]      = {1, 1, 1};
300365a81367SMatthew G. Knepley       PetscInt        cone[3];
300407c565c5SJose E. Roman       PetscInt       *graph;
300565a81367SMatthew G. Knepley 
30069371c9d4SSatish Balay       vertex[0] *= R / radius;
30079371c9d4SSatish Balay       vertex[1] *= R / radius;
30089371c9d4SSatish Balay       vertex[2] *= R / radius;
3009dd400576SPatrick Sanan       numCells    = rank == 0 ? 20 : 0;
3010dd400576SPatrick Sanan       numVerts    = rank == 0 ? 12 : 0;
301165a81367SMatthew G. Knepley       firstVertex = numCells;
301251a74b61SMatthew G. Knepley       /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of
301365a81367SMatthew G. Knepley 
301465a81367SMatthew G. Knepley            (0, \pm 1/\phi+1, \pm \phi/\phi+1)
301565a81367SMatthew G. Knepley 
301665a81367SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
301751a74b61SMatthew G. Knepley          length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393.
301865a81367SMatthew G. Knepley       */
301965a81367SMatthew G. Knepley       /* Construct vertices */
30209566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3021dd400576SPatrick Sanan       if (rank == 0) {
302207c565c5SJose E. Roman         for (PetscInt p = 0, i = 0; p < embedDim; ++p) {
302365a81367SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
302465a81367SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
302565a81367SMatthew G. Knepley               for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim];
302665a81367SMatthew G. Knepley               ++i;
302765a81367SMatthew G. Knepley             }
302865a81367SMatthew G. Knepley           }
302965a81367SMatthew G. Knepley         }
303045da822fSValeria Barra       }
303165a81367SMatthew G. Knepley       /* Construct graph */
30329566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
303307c565c5SJose E. Roman       for (PetscInt i = 0; i < numVerts; ++i) {
303407c565c5SJose E. Roman         PetscInt k = 0;
303507c565c5SJose E. Roman         for (PetscInt j = 0; j < numVerts; ++j) {
30369371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
30379371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
30389371c9d4SSatish Balay             ++k;
30399371c9d4SSatish Balay           }
304065a81367SMatthew G. Knepley         }
304163a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
304265a81367SMatthew G. Knepley       }
304365a81367SMatthew G. Knepley       /* Build Topology */
30449566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
304507c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
30469566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
304765a81367SMatthew G. Knepley       /* Cells */
304807c565c5SJose E. Roman       for (PetscInt i = 0, c = 0; i < numVerts; ++i) {
304907c565c5SJose E. Roman         for (PetscInt j = 0; j < i; ++j) {
305007c565c5SJose E. Roman           for (PetscInt k = 0; k < j; ++k) {
305165a81367SMatthew G. Knepley             if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) {
30529371c9d4SSatish Balay               cone[0] = firstVertex + i;
30539371c9d4SSatish Balay               cone[1] = firstVertex + j;
30549371c9d4SSatish Balay               cone[2] = firstVertex + k;
305565a81367SMatthew G. Knepley               /* Check orientation */
305665a81367SMatthew G. Knepley               {
30579371c9d4SSatish Balay                 const PetscInt epsilon[3][3][3] = {
30589371c9d4SSatish Balay                   {{0, 0, 0},  {0, 0, 1},  {0, -1, 0}},
30599371c9d4SSatish Balay                   {{0, 0, -1}, {0, 0, 0},  {1, 0, 0} },
30609371c9d4SSatish Balay                   {{0, 1, 0},  {-1, 0, 0}, {0, 0, 0} }
30619371c9d4SSatish Balay                 };
306265a81367SMatthew G. Knepley                 PetscReal normal[3];
306365a81367SMatthew G. Knepley                 PetscInt  e, f;
306465a81367SMatthew G. Knepley 
306565a81367SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) {
306665a81367SMatthew G. Knepley                   normal[d] = 0.0;
306765a81367SMatthew G. Knepley                   for (e = 0; e < embedDim; ++e) {
3068ad540459SPierre 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]);
306965a81367SMatthew G. Knepley                   }
307065a81367SMatthew G. Knepley                 }
30719371c9d4SSatish Balay                 if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
30729371c9d4SSatish Balay                   PetscInt tmp = cone[1];
30739371c9d4SSatish Balay                   cone[1]      = cone[2];
30749371c9d4SSatish Balay                   cone[2]      = tmp;
307565a81367SMatthew G. Knepley                 }
307665a81367SMatthew G. Knepley               }
30779566063dSJacob Faibussowitsch               PetscCall(DMPlexSetCone(dm, c++, cone));
307865a81367SMatthew G. Knepley             }
307965a81367SMatthew G. Knepley           }
308065a81367SMatthew G. Knepley         }
308165a81367SMatthew G. Knepley       }
30829566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
30839566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
30849566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
308565a81367SMatthew G. Knepley     } else {
30862829fed8SMatthew G. Knepley       /*
30872829fed8SMatthew G. Knepley         12-21--13
30882829fed8SMatthew G. Knepley          |     |
30892829fed8SMatthew G. Knepley         25  4  24
30902829fed8SMatthew G. Knepley          |     |
30912829fed8SMatthew G. Knepley   12-25--9-16--8-24--13
30922829fed8SMatthew G. Knepley    |     |     |     |
30932829fed8SMatthew G. Knepley   23  5 17  0 15  3  22
30942829fed8SMatthew G. Knepley    |     |     |     |
30952829fed8SMatthew G. Knepley   10-20--6-14--7-19--11
30962829fed8SMatthew G. Knepley          |     |
30972829fed8SMatthew G. Knepley         20  1  19
30982829fed8SMatthew G. Knepley          |     |
30992829fed8SMatthew G. Knepley         10-18--11
31002829fed8SMatthew G. Knepley          |     |
31012829fed8SMatthew G. Knepley         23  2  22
31022829fed8SMatthew G. Knepley          |     |
31032829fed8SMatthew G. Knepley         12-21--13
31042829fed8SMatthew G. Knepley        */
31052829fed8SMatthew G. Knepley       PetscInt cone[4], ornt[4];
31062829fed8SMatthew G. Knepley 
3107dd400576SPatrick Sanan       numCells    = rank == 0 ? 6 : 0;
3108dd400576SPatrick Sanan       numEdges    = rank == 0 ? 12 : 0;
3109dd400576SPatrick Sanan       numVerts    = rank == 0 ? 8 : 0;
311065a81367SMatthew G. Knepley       firstVertex = numCells;
311165a81367SMatthew G. Knepley       firstEdge   = numCells + numVerts;
31122829fed8SMatthew G. Knepley       /* Build Topology */
31139566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts));
311407c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4));
311548a46eb9SPierre Jolivet       for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2));
31169566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3117dd400576SPatrick Sanan       if (rank == 0) {
31182829fed8SMatthew G. Knepley         /* Cell 0 */
31199371c9d4SSatish Balay         cone[0] = 14;
31209371c9d4SSatish Balay         cone[1] = 15;
31219371c9d4SSatish Balay         cone[2] = 16;
31229371c9d4SSatish Balay         cone[3] = 17;
31239566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 0, cone));
31249371c9d4SSatish Balay         ornt[0] = 0;
31259371c9d4SSatish Balay         ornt[1] = 0;
31269371c9d4SSatish Balay         ornt[2] = 0;
31279371c9d4SSatish Balay         ornt[3] = 0;
31289566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 0, ornt));
31292829fed8SMatthew G. Knepley         /* Cell 1 */
31309371c9d4SSatish Balay         cone[0] = 18;
31319371c9d4SSatish Balay         cone[1] = 19;
31329371c9d4SSatish Balay         cone[2] = 14;
31339371c9d4SSatish Balay         cone[3] = 20;
31349566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 1, cone));
31359371c9d4SSatish Balay         ornt[0] = 0;
31369371c9d4SSatish Balay         ornt[1] = 0;
31379371c9d4SSatish Balay         ornt[2] = -1;
31389371c9d4SSatish Balay         ornt[3] = 0;
31399566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 1, ornt));
31402829fed8SMatthew G. Knepley         /* Cell 2 */
31419371c9d4SSatish Balay         cone[0] = 21;
31429371c9d4SSatish Balay         cone[1] = 22;
31439371c9d4SSatish Balay         cone[2] = 18;
31449371c9d4SSatish Balay         cone[3] = 23;
31459566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 2, cone));
31469371c9d4SSatish Balay         ornt[0] = 0;
31479371c9d4SSatish Balay         ornt[1] = 0;
31489371c9d4SSatish Balay         ornt[2] = -1;
31499371c9d4SSatish Balay         ornt[3] = 0;
31509566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 2, ornt));
31512829fed8SMatthew G. Knepley         /* Cell 3 */
31529371c9d4SSatish Balay         cone[0] = 19;
31539371c9d4SSatish Balay         cone[1] = 22;
31549371c9d4SSatish Balay         cone[2] = 24;
31559371c9d4SSatish Balay         cone[3] = 15;
31569566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 3, cone));
31579371c9d4SSatish Balay         ornt[0] = -1;
31589371c9d4SSatish Balay         ornt[1] = -1;
31599371c9d4SSatish Balay         ornt[2] = 0;
31609371c9d4SSatish Balay         ornt[3] = -1;
31619566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 3, ornt));
31622829fed8SMatthew G. Knepley         /* Cell 4 */
31639371c9d4SSatish Balay         cone[0] = 16;
31649371c9d4SSatish Balay         cone[1] = 24;
31659371c9d4SSatish Balay         cone[2] = 21;
31669371c9d4SSatish Balay         cone[3] = 25;
31679566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 4, cone));
31689371c9d4SSatish Balay         ornt[0] = -1;
31699371c9d4SSatish Balay         ornt[1] = -1;
31709371c9d4SSatish Balay         ornt[2] = -1;
31719371c9d4SSatish Balay         ornt[3] = 0;
31729566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 4, ornt));
31732829fed8SMatthew G. Knepley         /* Cell 5 */
31749371c9d4SSatish Balay         cone[0] = 20;
31759371c9d4SSatish Balay         cone[1] = 17;
31769371c9d4SSatish Balay         cone[2] = 25;
31779371c9d4SSatish Balay         cone[3] = 23;
31789566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 5, cone));
31799371c9d4SSatish Balay         ornt[0] = -1;
31809371c9d4SSatish Balay         ornt[1] = -1;
31819371c9d4SSatish Balay         ornt[2] = -1;
31829371c9d4SSatish Balay         ornt[3] = -1;
31839566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeOrientation(dm, 5, ornt));
31842829fed8SMatthew G. Knepley         /* Edges */
31859371c9d4SSatish Balay         cone[0] = 6;
31869371c9d4SSatish Balay         cone[1] = 7;
31879566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 14, cone));
31889371c9d4SSatish Balay         cone[0] = 7;
31899371c9d4SSatish Balay         cone[1] = 8;
31909566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 15, cone));
31919371c9d4SSatish Balay         cone[0] = 8;
31929371c9d4SSatish Balay         cone[1] = 9;
31939566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 16, cone));
31949371c9d4SSatish Balay         cone[0] = 9;
31959371c9d4SSatish Balay         cone[1] = 6;
31969566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 17, cone));
31979371c9d4SSatish Balay         cone[0] = 10;
31989371c9d4SSatish Balay         cone[1] = 11;
31999566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 18, cone));
32009371c9d4SSatish Balay         cone[0] = 11;
32019371c9d4SSatish Balay         cone[1] = 7;
32029566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 19, cone));
32039371c9d4SSatish Balay         cone[0] = 6;
32049371c9d4SSatish Balay         cone[1] = 10;
32059566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 20, cone));
32069371c9d4SSatish Balay         cone[0] = 12;
32079371c9d4SSatish Balay         cone[1] = 13;
32089566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 21, cone));
32099371c9d4SSatish Balay         cone[0] = 13;
32109371c9d4SSatish Balay         cone[1] = 11;
32119566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 22, cone));
32129371c9d4SSatish Balay         cone[0] = 10;
32139371c9d4SSatish Balay         cone[1] = 12;
32149566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 23, cone));
32159371c9d4SSatish Balay         cone[0] = 13;
32169371c9d4SSatish Balay         cone[1] = 8;
32179566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 24, cone));
32189371c9d4SSatish Balay         cone[0] = 12;
32199371c9d4SSatish Balay         cone[1] = 9;
32209566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(dm, 25, cone));
322145da822fSValeria Barra       }
32229566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
32239566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
32242829fed8SMatthew G. Knepley       /* Build coordinates */
32259566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3226dd400576SPatrick Sanan       if (rank == 0) {
32279371c9d4SSatish Balay         coordsIn[0 * embedDim + 0] = -R;
32289371c9d4SSatish Balay         coordsIn[0 * embedDim + 1] = R;
32299371c9d4SSatish Balay         coordsIn[0 * embedDim + 2] = -R;
32309371c9d4SSatish Balay         coordsIn[1 * embedDim + 0] = R;
32319371c9d4SSatish Balay         coordsIn[1 * embedDim + 1] = R;
32329371c9d4SSatish Balay         coordsIn[1 * embedDim + 2] = -R;
32339371c9d4SSatish Balay         coordsIn[2 * embedDim + 0] = R;
32349371c9d4SSatish Balay         coordsIn[2 * embedDim + 1] = -R;
32359371c9d4SSatish Balay         coordsIn[2 * embedDim + 2] = -R;
32369371c9d4SSatish Balay         coordsIn[3 * embedDim + 0] = -R;
32379371c9d4SSatish Balay         coordsIn[3 * embedDim + 1] = -R;
32389371c9d4SSatish Balay         coordsIn[3 * embedDim + 2] = -R;
32399371c9d4SSatish Balay         coordsIn[4 * embedDim + 0] = -R;
32409371c9d4SSatish Balay         coordsIn[4 * embedDim + 1] = R;
32419371c9d4SSatish Balay         coordsIn[4 * embedDim + 2] = R;
32429371c9d4SSatish Balay         coordsIn[5 * embedDim + 0] = R;
32439371c9d4SSatish Balay         coordsIn[5 * embedDim + 1] = R;
32449371c9d4SSatish Balay         coordsIn[5 * embedDim + 2] = R;
32459371c9d4SSatish Balay         coordsIn[6 * embedDim + 0] = -R;
32469371c9d4SSatish Balay         coordsIn[6 * embedDim + 1] = -R;
32479371c9d4SSatish Balay         coordsIn[6 * embedDim + 2] = R;
32489371c9d4SSatish Balay         coordsIn[7 * embedDim + 0] = R;
32499371c9d4SSatish Balay         coordsIn[7 * embedDim + 1] = -R;
32509371c9d4SSatish Balay         coordsIn[7 * embedDim + 2] = R;
325165a81367SMatthew G. Knepley       }
325245da822fSValeria Barra     }
325365a81367SMatthew G. Knepley     break;
325465a81367SMatthew G. Knepley   case 3:
3255116ded15SMatthew G. Knepley     if (simplex) {
3256116ded15SMatthew G. Knepley       const PetscReal edgeLen         = 1.0 / PETSC_PHI;
325751a74b61SMatthew G. Knepley       PetscReal       vertexA[4]      = {0.5, 0.5, 0.5, 0.5};
325851a74b61SMatthew G. Knepley       PetscReal       vertexB[4]      = {1.0, 0.0, 0.0, 0.0};
325951a74b61SMatthew G. Knepley       PetscReal       vertexC[4]      = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0};
3260116ded15SMatthew G. Knepley       const PetscInt  degree          = 12;
3261116ded15SMatthew G. Knepley       PetscInt        s[4]            = {1, 1, 1};
32629371c9d4SSatish Balay       PetscInt        evenPerm[12][4] = {
32639371c9d4SSatish Balay         {0, 1, 2, 3},
32649371c9d4SSatish Balay         {0, 2, 3, 1},
32659371c9d4SSatish Balay         {0, 3, 1, 2},
32669371c9d4SSatish Balay         {1, 0, 3, 2},
32679371c9d4SSatish Balay         {1, 2, 0, 3},
32689371c9d4SSatish Balay         {1, 3, 2, 0},
32699371c9d4SSatish Balay         {2, 0, 1, 3},
32709371c9d4SSatish Balay         {2, 1, 3, 0},
32719371c9d4SSatish Balay         {2, 3, 0, 1},
32729371c9d4SSatish Balay         {3, 0, 2, 1},
32739371c9d4SSatish Balay         {3, 1, 0, 2},
32749371c9d4SSatish Balay         {3, 2, 1, 0}
32759371c9d4SSatish Balay       };
3276116ded15SMatthew G. Knepley       PetscInt  cone[4];
3277116ded15SMatthew G. Knepley       PetscInt *graph, p, i, j, k, l;
3278116ded15SMatthew G. Knepley 
32799371c9d4SSatish Balay       vertexA[0] *= R;
32809371c9d4SSatish Balay       vertexA[1] *= R;
32819371c9d4SSatish Balay       vertexA[2] *= R;
32829371c9d4SSatish Balay       vertexA[3] *= R;
32839371c9d4SSatish Balay       vertexB[0] *= R;
32849371c9d4SSatish Balay       vertexB[1] *= R;
32859371c9d4SSatish Balay       vertexB[2] *= R;
32869371c9d4SSatish Balay       vertexB[3] *= R;
32879371c9d4SSatish Balay       vertexC[0] *= R;
32889371c9d4SSatish Balay       vertexC[1] *= R;
32899371c9d4SSatish Balay       vertexC[2] *= R;
32909371c9d4SSatish Balay       vertexC[3] *= R;
3291dd400576SPatrick Sanan       numCells    = rank == 0 ? 600 : 0;
3292dd400576SPatrick Sanan       numVerts    = rank == 0 ? 120 : 0;
3293116ded15SMatthew G. Knepley       firstVertex = numCells;
3294116ded15SMatthew G. Knepley       /* Use the 600-cell, which for a unit sphere has coordinates which are
3295116ded15SMatthew G. Knepley 
3296116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm 1,    \pm 1, \pm 1)                          16
3297116ded15SMatthew G. Knepley                (\pm 1,    0,       0,      0)  all cyclic permutations   8
3298116ded15SMatthew G. Knepley            1/2 (\pm 1, \pm phi, \pm 1/phi, 0)  all even permutations    96
3299116ded15SMatthew G. Knepley 
3300116ded15SMatthew G. Knepley          where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge
33016333ae4fSvaleriabarra          length is then given by 1/\phi = 0.61803.
3302116ded15SMatthew G. Knepley 
3303116ded15SMatthew G. Knepley          http://buzzard.pugetsound.edu/sage-practice/ch03s03.html
3304116ded15SMatthew G. Knepley          http://mathworld.wolfram.com/600-Cell.html
3305116ded15SMatthew G. Knepley       */
3306116ded15SMatthew G. Knepley       /* Construct vertices */
33079566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn));
3308116ded15SMatthew G. Knepley       i = 0;
3309dd400576SPatrick Sanan       if (rank == 0) {
3310116ded15SMatthew G. Knepley         for (s[0] = -1; s[0] < 2; s[0] += 2) {
3311116ded15SMatthew G. Knepley           for (s[1] = -1; s[1] < 2; s[1] += 2) {
3312116ded15SMatthew G. Knepley             for (s[2] = -1; s[2] < 2; s[2] += 2) {
3313116ded15SMatthew G. Knepley               for (s[3] = -1; s[3] < 2; s[3] += 2) {
3314116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d];
3315116ded15SMatthew G. Knepley                 ++i;
3316116ded15SMatthew G. Knepley               }
3317116ded15SMatthew G. Knepley             }
3318116ded15SMatthew G. Knepley           }
3319116ded15SMatthew G. Knepley         }
3320116ded15SMatthew G. Knepley         for (p = 0; p < embedDim; ++p) {
3321116ded15SMatthew G. Knepley           s[1] = s[2] = s[3] = 1;
3322116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
3323116ded15SMatthew G. Knepley             for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim];
3324116ded15SMatthew G. Knepley             ++i;
3325116ded15SMatthew G. Knepley           }
3326116ded15SMatthew G. Knepley         }
3327116ded15SMatthew G. Knepley         for (p = 0; p < 12; ++p) {
3328116ded15SMatthew G. Knepley           s[3] = 1;
3329116ded15SMatthew G. Knepley           for (s[0] = -1; s[0] < 2; s[0] += 2) {
3330116ded15SMatthew G. Knepley             for (s[1] = -1; s[1] < 2; s[1] += 2) {
3331116ded15SMatthew G. Knepley               for (s[2] = -1; s[2] < 2; s[2] += 2) {
3332116ded15SMatthew G. Knepley                 for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]];
3333116ded15SMatthew G. Knepley                 ++i;
3334116ded15SMatthew G. Knepley               }
3335116ded15SMatthew G. Knepley             }
3336116ded15SMatthew G. Knepley           }
3337116ded15SMatthew G. Knepley         }
333845da822fSValeria Barra       }
333963a3b9bcSJacob Faibussowitsch       PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts);
3340116ded15SMatthew G. Knepley       /* Construct graph */
33419566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numVerts * numVerts, &graph));
3342116ded15SMatthew G. Knepley       for (i = 0; i < numVerts; ++i) {
3343116ded15SMatthew G. Knepley         for (j = 0, k = 0; j < numVerts; ++j) {
33449371c9d4SSatish Balay           if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) {
33459371c9d4SSatish Balay             graph[i * numVerts + j] = 1;
33469371c9d4SSatish Balay             ++k;
33479371c9d4SSatish Balay           }
3348116ded15SMatthew G. Knepley         }
334963a3b9bcSJacob Faibussowitsch         PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree);
3350116ded15SMatthew G. Knepley       }
3351116ded15SMatthew G. Knepley       /* Build Topology */
33529566063dSJacob Faibussowitsch       PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts));
335307c565c5SJose E. Roman       for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim));
33549566063dSJacob Faibussowitsch       PetscCall(DMSetUp(dm)); /* Allocate space for cones */
3355116ded15SMatthew G. Knepley       /* Cells */
3356dd400576SPatrick Sanan       if (rank == 0) {
335707c565c5SJose E. Roman         for (PetscInt i = 0, c = 0; i < numVerts; ++i) {
3358116ded15SMatthew G. Knepley           for (j = 0; j < i; ++j) {
3359116ded15SMatthew G. Knepley             for (k = 0; k < j; ++k) {
3360116ded15SMatthew G. Knepley               for (l = 0; l < k; ++l) {
33619371c9d4SSatish 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]) {
33629371c9d4SSatish Balay                   cone[0] = firstVertex + i;
33639371c9d4SSatish Balay                   cone[1] = firstVertex + j;
33649371c9d4SSatish Balay                   cone[2] = firstVertex + k;
33659371c9d4SSatish Balay                   cone[3] = firstVertex + l;
3366116ded15SMatthew G. Knepley                   /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */
3367116ded15SMatthew G. Knepley                   {
33689371c9d4SSatish Balay                     const PetscInt epsilon[4][4][4][4] = {
33699371c9d4SSatish 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}}},
3370116ded15SMatthew G. Knepley 
33719371c9d4SSatish 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}}},
3372116ded15SMatthew G. Knepley 
33739371c9d4SSatish 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}}},
3374116ded15SMatthew G. Knepley 
33759371c9d4SSatish 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}} }
33769371c9d4SSatish Balay                     };
3377116ded15SMatthew G. Knepley                     PetscReal normal[4];
3378116ded15SMatthew G. Knepley                     PetscInt  e, f, g;
3379116ded15SMatthew G. Knepley 
3380116ded15SMatthew G. Knepley                     for (d = 0; d < embedDim; ++d) {
3381116ded15SMatthew G. Knepley                       normal[d] = 0.0;
3382116ded15SMatthew G. Knepley                       for (e = 0; e < embedDim; ++e) {
3383116ded15SMatthew G. Knepley                         for (f = 0; f < embedDim; ++f) {
3384116ded15SMatthew G. Knepley                           for (g = 0; g < embedDim; ++g) {
3385116ded15SMatthew 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]);
3386116ded15SMatthew G. Knepley                           }
3387116ded15SMatthew G. Knepley                         }
3388116ded15SMatthew G. Knepley                       }
3389116ded15SMatthew G. Knepley                     }
33909371c9d4SSatish Balay                     if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) {
33919371c9d4SSatish Balay                       PetscInt tmp = cone[1];
33929371c9d4SSatish Balay                       cone[1]      = cone[2];
33939371c9d4SSatish Balay                       cone[2]      = tmp;
33949371c9d4SSatish Balay                     }
3395116ded15SMatthew G. Knepley                   }
33969566063dSJacob Faibussowitsch                   PetscCall(DMPlexSetCone(dm, c++, cone));
3397116ded15SMatthew G. Knepley                 }
3398116ded15SMatthew G. Knepley               }
3399116ded15SMatthew G. Knepley             }
3400116ded15SMatthew G. Knepley           }
3401116ded15SMatthew G. Knepley         }
340245da822fSValeria Barra       }
34039566063dSJacob Faibussowitsch       PetscCall(DMPlexSymmetrize(dm));
34049566063dSJacob Faibussowitsch       PetscCall(DMPlexStratify(dm));
34059566063dSJacob Faibussowitsch       PetscCall(PetscFree(graph));
3406116ded15SMatthew G. Knepley     }
3407f4d061e9SPierre Jolivet     break;
3408d71ae5a4SJacob Faibussowitsch   default:
3409d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim);
341065a81367SMatthew G. Knepley   }
341165a81367SMatthew G. Knepley   /* Create coordinates */
34129566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
34139566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
34149566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim));
34159566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts));
34162829fed8SMatthew G. Knepley   for (v = firstVertex; v < firstVertex + numVerts; ++v) {
34179566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, embedDim));
34189566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim));
34192829fed8SMatthew G. Knepley   }
34209566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
34219566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
34229566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
34239566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, embedDim));
34249566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
34259566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
34269566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
34279566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
34289371c9d4SSatish Balay   for (v = 0; v < numVerts; ++v)
3429ad540459SPierre Jolivet     for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d];
34309566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
34319566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
34329566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
34339566063dSJacob Faibussowitsch   PetscCall(PetscFree(coordsIn));
343451a74b61SMatthew G. Knepley   {
343551a74b61SMatthew G. Knepley     DM          cdm;
343651a74b61SMatthew G. Knepley     PetscDS     cds;
34379318fe57SMatthew G. Knepley     PetscScalar c = R;
343851a74b61SMatthew G. Knepley 
3439e44f6aebSMatthew G. Knepley     PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, snapToSphere));
34409566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
34419566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
34429566063dSJacob Faibussowitsch     PetscCall(PetscDSSetConstants(cds, 1, &c));
344351a74b61SMatthew G. Knepley   }
344446139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
34459318fe57SMatthew G. Knepley   /* Wait for coordinate creation before doing in-place modification */
34469566063dSJacob Faibussowitsch   if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm));
34473ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
34489318fe57SMatthew G. Knepley }
34499318fe57SMatthew G. Knepley 
3450b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]);
3451b7f5c055SJed Brown 
3452b7f5c055SJed Brown /*
3453b7f5c055SJed Brown  The Schwarz P implicit surface is
3454b7f5c055SJed Brown 
3455b7f5c055SJed Brown      f(x) = cos(x0) + cos(x1) + cos(x2) = 0
3456b7f5c055SJed Brown */
3457d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
3458d71ae5a4SJacob Faibussowitsch {
3459b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)};
3460b7f5c055SJed Brown   PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)};
3461b7f5c055SJed Brown   f[0]           = c[0] + c[1] + c[2];
3462b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
3463b7f5c055SJed Brown     grad[i] = PETSC_PI * g[i];
3464ad540459SPierre Jolivet     for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.;
3465b7f5c055SJed Brown   }
3466b7f5c055SJed Brown }
3467b7f5c055SJed Brown 
34684663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
3469d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
3470d71ae5a4SJacob Faibussowitsch {
3471ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI);
34723ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
34734663dae6SJed Brown }
34744663dae6SJed Brown 
3475b7f5c055SJed Brown /*
3476b7f5c055SJed Brown  The Gyroid implicit surface is
3477b7f5c055SJed Brown 
3478b7f5c055SJed 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)
3479b7f5c055SJed Brown 
3480b7f5c055SJed Brown */
3481d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3])
3482d71ae5a4SJacob Faibussowitsch {
3483b7f5c055SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))};
3484b7f5c055SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))};
3485b7f5c055SJed Brown   f[0]           = s[0] * c[1] + s[1] * c[2] + s[2] * c[0];
3486b7f5c055SJed Brown   grad[0]        = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
3487b7f5c055SJed Brown   grad[1]        = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
3488b7f5c055SJed Brown   grad[2]        = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
3489b7f5c055SJed Brown   hess[0][0]     = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]);
3490b7f5c055SJed Brown   hess[0][1]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
3491b7f5c055SJed Brown   hess[0][2]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
3492b7f5c055SJed Brown   hess[1][0]     = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]);
3493b7f5c055SJed Brown   hess[1][1]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
3494b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[0] * s[1]);
3495b7f5c055SJed Brown   hess[2][0]     = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]);
3496b7f5c055SJed Brown   hess[2][1]     = -PetscSqr(PETSC_PI) * (c[2] * s[0]);
3497b7f5c055SJed Brown   hess[2][2]     = -PetscSqr(PETSC_PI) * (c[1] * s[2]);
3498b7f5c055SJed Brown }
3499b7f5c055SJed Brown 
35004663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction
3501d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx)
3502d71ae5a4SJacob Faibussowitsch {
35034663dae6SJed Brown   PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))};
35044663dae6SJed Brown   PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))};
35054663dae6SJed Brown   u[0]           = PETSC_PI * (c[0] * c[1] - s[2] * s[0]);
35064663dae6SJed Brown   u[1]           = PETSC_PI * (c[1] * c[2] - s[0] * s[1]);
35074663dae6SJed Brown   u[2]           = PETSC_PI * (c[2] * c[0] - s[1] * s[2]);
35083ba16761SJacob Faibussowitsch   return PETSC_SUCCESS;
35094663dae6SJed Brown }
35104663dae6SJed Brown 
3511b7f5c055SJed Brown /*
3512b7f5c055SJed Brown    We wish to solve
3513b7f5c055SJed Brown 
3514b7f5c055SJed Brown          min_y || y - x ||^2  subject to f(y) = 0
3515b7f5c055SJed Brown 
3516b7f5c055SJed Brown    Let g(y) = grad(f).  The minimization problem is equivalent to asking to satisfy
3517b7f5c055SJed 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
3518b7f5c055SJed Brown    tangent space and ask for both components in the tangent space to be zero.
3519b7f5c055SJed Brown 
3520b7f5c055SJed Brown    Take g to be a column vector and compute the "full QR" factorization Q R = g,
3521b7f5c055SJed Brown    where Q = I - 2 n n^T is a symmetric orthogonal matrix.
3522b7f5c055SJed Brown    The first column of Q is parallel to g so the remaining two columns span the null space.
3523b7f5c055SJed Brown    Let Qn = Q[:,1:] be those remaining columns.  Then Qn Qn^T is an orthogonal projector into the tangent space.
3524da81f932SPierre Jolivet    Since Q is symmetric, this is equivalent to multiplying by Q and taking the last two entries.
3525b7f5c055SJed Brown    In total, we have a system of 3 equations in 3 unknowns:
3526b7f5c055SJed Brown 
3527b7f5c055SJed Brown      f(y) = 0                       1 equation
3528b7f5c055SJed Brown      Qn^T (y - x) = 0               2 equations
3529b7f5c055SJed Brown 
3530b7f5c055SJed Brown    Here, we compute the residual and Jacobian of this system.
3531b7f5c055SJed Brown */
3532d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[])
3533d71ae5a4SJacob Faibussowitsch {
3534b7f5c055SJed Brown   PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])};
3535b7f5c055SJed Brown   PetscReal d[3]     = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])};
35362f0490c0SSatish Balay   PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign;
35379371c9d4SSatish Balay   PetscReal n_y[3][3] = {
35389371c9d4SSatish Balay     {0, 0, 0},
35399371c9d4SSatish Balay     {0, 0, 0},
35409371c9d4SSatish Balay     {0, 0, 0}
35419371c9d4SSatish Balay   };
3542b7f5c055SJed Brown 
3543b7f5c055SJed Brown   feval(yreal, &f, grad, n_y);
3544b7f5c055SJed Brown 
3545b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n[i] = grad[i];
3546b7f5c055SJed Brown   norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
3547ad540459SPierre Jolivet   for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i];
3548b7f5c055SJed Brown 
3549b7f5c055SJed Brown   // Define the Householder reflector
3550b7f5c055SJed Brown   sign = n[0] >= 0 ? 1. : -1.;
3551b7f5c055SJed Brown   n[0] += norm * sign;
3552b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign;
3553b7f5c055SJed Brown 
3554b7f5c055SJed Brown   norm      = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2]));
3555b7f5c055SJed Brown   norm_y[0] = 1. / norm * (n[0] * n_y[0][0]);
3556b7f5c055SJed Brown   norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]);
3557b7f5c055SJed Brown   norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]);
3558b7f5c055SJed Brown 
3559b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) {
3560b7f5c055SJed Brown     n[i] /= norm;
3561b7f5c055SJed Brown     for (PetscInt j = 0; j < 3; j++) {
3562b7f5c055SJed Brown       // note that n[i] is n_old[i]/norm when executing the code below
3563b7f5c055SJed Brown       n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j];
3564b7f5c055SJed Brown     }
3565b7f5c055SJed Brown   }
3566b7f5c055SJed Brown 
3567b7f5c055SJed Brown   nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2];
3568b7f5c055SJed 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];
3569b7f5c055SJed Brown 
3570b7f5c055SJed Brown   res[0] = f;
3571b7f5c055SJed Brown   res[1] = d[1] - 2 * n[1] * nd;
3572b7f5c055SJed Brown   res[2] = d[2] - 2 * n[2] * nd;
3573b7f5c055SJed Brown   // J[j][i] is J_{ij} (column major)
3574b7f5c055SJed Brown   for (PetscInt j = 0; j < 3; j++) {
3575b7f5c055SJed Brown     J[0 + j * 3] = grad[j];
3576b7f5c055SJed Brown     J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]);
3577b7f5c055SJed Brown     J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]);
3578b7f5c055SJed Brown   }
3579b7f5c055SJed Brown }
3580b7f5c055SJed Brown 
3581b7f5c055SJed Brown /*
3582b7f5c055SJed Brown    Project x to the nearest point on the implicit surface using Newton's method.
3583b7f5c055SJed Brown */
3584d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[])
3585d71ae5a4SJacob Faibussowitsch {
3586b7f5c055SJed Brown   PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess
3587b7f5c055SJed Brown 
3588b7f5c055SJed Brown   PetscFunctionBegin;
3589b7f5c055SJed Brown   for (PetscInt iter = 0; iter < 10; iter++) {
3590b7f5c055SJed Brown     PetscScalar res[3], J[9];
3591b7f5c055SJed Brown     PetscReal   resnorm;
3592b7f5c055SJed Brown     TPSNearestPointResJac(feval, x, y, res, J);
3593b7f5c055SJed Brown     resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2])));
3594b7f5c055SJed Brown     if (0) { // Turn on this monitor if you need to confirm quadratic convergence
359563a3b9bcSJacob 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])));
3596b7f5c055SJed Brown     }
3597b7f5c055SJed Brown     if (resnorm < PETSC_SMALL) break;
3598b7f5c055SJed Brown 
3599b7f5c055SJed Brown     // Take the Newton step
36009566063dSJacob Faibussowitsch     PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL));
3601b7f5c055SJed Brown     PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res);
3602b7f5c055SJed Brown   }
3603b7f5c055SJed Brown   for (PetscInt i = 0; i < 3; i++) x[i] = y[i];
36043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3605b7f5c055SJed Brown }
3606b7f5c055SJed Brown 
3607b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL};
3608b7f5c055SJed Brown 
3609d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness)
3610d71ae5a4SJacob Faibussowitsch {
3611b7f5c055SJed Brown   PetscMPIInt rank;
3612b7f5c055SJed Brown   PetscInt    topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0;
3613b7f5c055SJed Brown   PetscInt(*edges)[2] = NULL, *edgeSets = NULL;
3614b7f5c055SJed Brown   PetscInt           *cells_flat = NULL;
3615b7f5c055SJed Brown   PetscReal          *vtxCoords  = NULL;
3616b7f5c055SJed Brown   TPSEvaluateFunc     evalFunc   = NULL;
36178434afd1SBarry Smith   PetscSimplePointFn *normalFunc = NULL;
3618b7f5c055SJed Brown   DMLabel             label;
3619b7f5c055SJed Brown 
3620b7f5c055SJed Brown   PetscFunctionBegin;
362146139095SJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0));
36229566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank));
362363a3b9bcSJacob 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);
3624b7f5c055SJed Brown   switch (tpstype) {
3625b7f5c055SJed Brown   case DMPLEX_TPS_SCHWARZ_P:
3626b7f5c055SJed 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");
3627c5853193SPierre Jolivet     if (rank == 0) {
3628b7f5c055SJed Brown       PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn]
3629b7f5c055SJed Brown       PetscInt  Njunctions = 0, Ncuts = 0, Npipes[3], vcount;
3630b7f5c055SJed Brown       PetscReal L = 1;
3631b7f5c055SJed Brown 
3632b7f5c055SJed Brown       Npipes[0]   = (extent[0] + 1) * extent[1] * extent[2];
3633b7f5c055SJed Brown       Npipes[1]   = extent[0] * (extent[1] + 1) * extent[2];
3634b7f5c055SJed Brown       Npipes[2]   = extent[0] * extent[1] * (extent[2] + 1);
3635b7f5c055SJed Brown       Njunctions  = extent[0] * extent[1] * extent[2];
3636b7f5c055SJed Brown       Ncuts       = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]);
3637b7f5c055SJed Brown       numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions;
36389566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords));
36399566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Njunctions, &cells));
36409566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edges));
36419566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets));
3642b7f5c055SJed Brown       // x-normal pipes
3643b7f5c055SJed Brown       vcount = 0;
3644b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0] + 1; i++) {
3645b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3646b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3647b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3648b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * i - 1) * L;
3649b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3650b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3651b7f5c055SJed Brown             }
3652b7f5c055SJed Brown           }
3653b7f5c055SJed Brown         }
3654b7f5c055SJed Brown       }
3655b7f5c055SJed Brown       // y-normal pipes
3656b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3657b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1] + 1; j++) {
3658b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3659b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3660b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3661b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * j - 1) * L;
3662b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3663b7f5c055SJed Brown             }
3664b7f5c055SJed Brown           }
3665b7f5c055SJed Brown         }
3666b7f5c055SJed Brown       }
3667b7f5c055SJed Brown       // z-normal pipes
3668b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3669b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3670b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2] + 1; k++) {
3671b7f5c055SJed Brown             for (PetscInt l = 0; l < 4; l++) {
3672b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3673b7f5c055SJed Brown               vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2;
3674b7f5c055SJed Brown               vtxCoords[vcount++] = (2 * k - 1) * L;
3675b7f5c055SJed Brown             }
3676b7f5c055SJed Brown           }
3677b7f5c055SJed Brown         }
3678b7f5c055SJed Brown       }
3679b7f5c055SJed Brown       // junctions
3680b7f5c055SJed Brown       for (PetscInt i = 0; i < extent[0]; i++) {
3681b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3682b7f5c055SJed Brown           for (PetscInt k = 0; k < extent[2]; k++) {
3683b7f5c055SJed Brown             const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8;
3684b7f5c055SJed Brown             PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count");
3685b7f5c055SJed Brown             for (PetscInt ii = 0; ii < 2; ii++) {
3686b7f5c055SJed Brown               for (PetscInt jj = 0; jj < 2; jj++) {
3687b7f5c055SJed Brown                 for (PetscInt kk = 0; kk < 2; kk++) {
3688b7f5c055SJed Brown                   double Ls           = (1 - sqrt(2) / 4) * L;
3689b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls;
3690b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls;
3691b7f5c055SJed Brown                   vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls;
3692b7f5c055SJed Brown                 }
3693b7f5c055SJed Brown               }
3694b7f5c055SJed Brown             }
3695b7f5c055SJed Brown             const PetscInt jfaces[3][2][4] = {
3696b7f5c055SJed Brown               {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned
3697b7f5c055SJed Brown               {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned
3698b7f5c055SJed Brown               {{6, 2, 0, 4}, {7, 3, 1, 5}}  // z-aligned
3699b7f5c055SJed Brown             };
3700b7f5c055SJed Brown             const PetscInt pipe_lo[3] = {// vertex numbers of pipes
37019371c9d4SSatish 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};
3702b7f5c055SJed Brown             const PetscInt pipe_hi[3] = {// vertex numbers of pipes
37039371c9d4SSatish 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};
3704b7f5c055SJed Brown             for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z
3705b7f5c055SJed Brown               const PetscInt ijk[3] = {i, j, k};
3706b7f5c055SJed Brown               for (PetscInt l = 0; l < 4; l++) { // rotations
3707b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l;
3708b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l];
3709b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4];
3710b7f5c055SJed Brown                 cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4;
3711b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l];
3712b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l;
3713b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4;
3714b7f5c055SJed Brown                 cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4];
3715b7f5c055SJed Brown                 if (ijk[dir] == 0) {
3716b7f5c055SJed Brown                   edges[numEdges][0] = pipe_lo[dir] + l;
3717b7f5c055SJed Brown                   edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4;
3718b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 1;
3719b7f5c055SJed Brown                   numEdges++;
3720b7f5c055SJed Brown                 }
3721b7f5c055SJed Brown                 if (ijk[dir] + 1 == extent[dir]) {
3722b7f5c055SJed Brown                   edges[numEdges][0] = pipe_hi[dir] + l;
3723b7f5c055SJed Brown                   edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4;
3724b7f5c055SJed Brown                   edgeSets[numEdges] = dir * 2 + 2;
3725b7f5c055SJed Brown                   numEdges++;
3726b7f5c055SJed Brown                 }
3727b7f5c055SJed Brown               }
3728b7f5c055SJed Brown             }
3729b7f5c055SJed Brown           }
3730b7f5c055SJed Brown         }
3731b7f5c055SJed Brown       }
373263a3b9bcSJacob Faibussowitsch       PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts);
3733b7f5c055SJed Brown       numFaces   = 24 * Njunctions;
3734b7f5c055SJed Brown       cells_flat = cells[0][0][0];
3735b7f5c055SJed Brown     }
3736b7f5c055SJed Brown     evalFunc   = TPSEvaluate_SchwarzP;
37374663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_SchwarzP;
3738b7f5c055SJed Brown     break;
3739b7f5c055SJed Brown   case DMPLEX_TPS_GYROID:
3740c5853193SPierre Jolivet     if (rank == 0) {
3741b7f5c055SJed Brown       // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set
3742b7f5c055SJed Brown       //
3743b7f5c055SJed 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)
3744b7f5c055SJed Brown       //
3745b7f5c055SJed Brown       // on the cell [0,2]^3.
3746b7f5c055SJed Brown       //
3747b7f5c055SJed Brown       // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2].
3748b7f5c055SJed Brown       // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins
3749b7f5c055SJed Brown       // like a boomerang:
3750b7f5c055SJed Brown       //
3751b7f5c055SJed Brown       //     z = 0          z = 1/4        z = 1/2        z = 3/4     //
3752b7f5c055SJed Brown       //     -----          -------        -------        -------     //
3753b7f5c055SJed Brown       //                                                              //
3754b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
3755b7f5c055SJed Brown       //      \                                   /            \      //
3756b7f5c055SJed Brown       //       \            `-_   _-'            /              }     //
3757b7f5c055SJed Brown       //        *-_            `-'            _-'              /      //
3758b7f5c055SJed Brown       //     +     `-+      +       +      +-'     +      +   /   +   //
3759b7f5c055SJed Brown       //                                                              //
3760b7f5c055SJed Brown       //                                                              //
3761b7f5c055SJed Brown       //     z = 1          z = 5/4        z = 3/2        z = 7/4     //
3762b7f5c055SJed Brown       //     -----          -------        -------        -------     //
3763b7f5c055SJed Brown       //                                                              //
3764b7f5c055SJed Brown       //     +-_     +      +       +      +     _-+      +   /   +   //
3765b7f5c055SJed Brown       //        `-_            _-_            _-`            /        //
3766b7f5c055SJed Brown       //           \        _-'   `-_        /              {         //
3767b7f5c055SJed Brown       //            \                       /                \        //
3768b7f5c055SJed Brown       //     +       +      +       +      +       +      +   \   +   //
3769b7f5c055SJed Brown       //
3770b7f5c055SJed Brown       //
3771b7f5c055SJed Brown       // This course mesh approximates each of these slices by two line segments,
3772b7f5c055SJed Brown       // and then connects the segments in consecutive layers with quadrilateral faces.
3773b7f5c055SJed Brown       // All of the end points of the segments are multiples of 1/4 except for the
3774b7f5c055SJed Brown       // point * in the picture for z = 0 above and the similar points in other layers.
3775b7f5c055SJed Brown       // That point is at (gamma, gamma, 0), where gamma is calculated below.
3776b7f5c055SJed Brown       //
3777b7f5c055SJed Brown       // The column  [1,2]x[1,2]x[0,2] looks the same as this column;
3778b7f5c055SJed Brown       // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images.
3779b7f5c055SJed Brown       //
3780b7f5c055SJed Brown       // As for how this method turned into the names given to the vertices:
3781b7f5c055SJed Brown       // that was not systematic, it was just the way it worked out in my handwritten notes.
3782b7f5c055SJed Brown 
3783b7f5c055SJed Brown       PetscInt facesPerBlock = 64;
3784b7f5c055SJed Brown       PetscInt vertsPerBlock = 56;
3785b7f5c055SJed Brown       PetscInt extentPlus[3];
3786b7f5c055SJed Brown       PetscInt numBlocks, numBlocksPlus;
37879371c9d4SSatish 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;
37889371c9d4SSatish Balay       const PetscInt pattern[64][4] = {
37899371c9d4SSatish Balay         /* face to vertex within the coarse discretization of a single gyroid block */
3790b7f5c055SJed Brown         /* layer 0 */
37919371c9d4SSatish Balay         {A,           C,           K,           G          },
37929371c9d4SSatish Balay         {C,           B,           II,          K          },
37939371c9d4SSatish Balay         {D,           A,           H,           L          },
37949371c9d4SSatish Balay         {B + 56 * 1,  D,           L,           J          },
37959371c9d4SSatish Balay         {E,           B + 56 * 1,  J,           N          },
37969371c9d4SSatish Balay         {A + 56 * 2,  E,           N,           H + 56 * 2 },
37979371c9d4SSatish Balay         {F,           A + 56 * 2,  G + 56 * 2,  M          },
37989371c9d4SSatish Balay         {B,           F,           M,           II         },
3799b7f5c055SJed Brown         /* layer 1 */
38009371c9d4SSatish Balay         {G,           K,           Q,           O          },
38019371c9d4SSatish Balay         {K,           II,          P,           Q          },
38029371c9d4SSatish Balay         {L,           H,           O + 56 * 1,  R          },
38039371c9d4SSatish Balay         {J,           L,           R,           P          },
38049371c9d4SSatish Balay         {N,           J,           P,           S          },
38059371c9d4SSatish Balay         {H + 56 * 2,  N,           S,           O + 56 * 3 },
38069371c9d4SSatish Balay         {M,           G + 56 * 2,  O + 56 * 2,  T          },
38079371c9d4SSatish Balay         {II,          M,           T,           P          },
3808b7f5c055SJed Brown         /* layer 2 */
38099371c9d4SSatish Balay         {O,           Q,           Y,           U          },
38109371c9d4SSatish Balay         {Q,           P,           W,           Y          },
38119371c9d4SSatish Balay         {R,           O + 56 * 1,  U + 56 * 1,  Ap         },
38129371c9d4SSatish Balay         {P,           R,           Ap,          W          },
38139371c9d4SSatish Balay         {S,           P,           X,           Bp         },
38149371c9d4SSatish Balay         {O + 56 * 3,  S,           Bp,          V + 56 * 1 },
38159371c9d4SSatish Balay         {T,           O + 56 * 2,  V,           Z          },
38169371c9d4SSatish Balay         {P,           T,           Z,           X          },
3817b7f5c055SJed Brown         /* layer 3 */
38189371c9d4SSatish Balay         {U,           Y,           Ep,          Dp         },
38199371c9d4SSatish Balay         {Y,           W,           Cp,          Ep         },
38209371c9d4SSatish Balay         {Ap,          U + 56 * 1,  Dp + 56 * 1, Gp         },
38219371c9d4SSatish Balay         {W,           Ap,          Gp,          Cp         },
38229371c9d4SSatish Balay         {Bp,          X,           Cp + 56 * 2, Fp         },
38239371c9d4SSatish Balay         {V + 56 * 1,  Bp,          Fp,          Dp + 56 * 1},
38249371c9d4SSatish Balay         {Z,           V,           Dp,          Hp         },
38259371c9d4SSatish Balay         {X,           Z,           Hp,          Cp + 56 * 2},
3826b7f5c055SJed Brown         /* layer 4 */
38279371c9d4SSatish Balay         {Dp,          Ep,          Mp,          Kp         },
38289371c9d4SSatish Balay         {Ep,          Cp,          Ip,          Mp         },
38299371c9d4SSatish Balay         {Gp,          Dp + 56 * 1, Lp,          Np         },
38309371c9d4SSatish Balay         {Cp,          Gp,          Np,          Jp         },
38319371c9d4SSatish Balay         {Fp,          Cp + 56 * 2, Jp + 56 * 2, Pp         },
38329371c9d4SSatish Balay         {Dp + 56 * 1, Fp,          Pp,          Lp         },
38339371c9d4SSatish Balay         {Hp,          Dp,          Kp,          Op         },
38349371c9d4SSatish Balay         {Cp + 56 * 2, Hp,          Op,          Ip + 56 * 2},
3835b7f5c055SJed Brown         /* layer 5 */
38369371c9d4SSatish Balay         {Kp,          Mp,          Sp,          Rp         },
38379371c9d4SSatish Balay         {Mp,          Ip,          Qp,          Sp         },
38389371c9d4SSatish Balay         {Np,          Lp,          Rp,          Tp         },
38399371c9d4SSatish Balay         {Jp,          Np,          Tp,          Qp + 56 * 1},
38409371c9d4SSatish Balay         {Pp,          Jp + 56 * 2, Qp + 56 * 3, Up         },
38419371c9d4SSatish Balay         {Lp,          Pp,          Up,          Rp         },
38429371c9d4SSatish Balay         {Op,          Kp,          Rp,          Vp         },
38439371c9d4SSatish Balay         {Ip + 56 * 2, Op,          Vp,          Qp + 56 * 2},
3844b7f5c055SJed Brown         /* layer 6 */
38459371c9d4SSatish Balay         {Rp,          Sp,          Aq,          Yp         },
38469371c9d4SSatish Balay         {Sp,          Qp,          Wp,          Aq         },
38479371c9d4SSatish Balay         {Tp,          Rp,          Yp,          Cq         },
38489371c9d4SSatish Balay         {Qp + 56 * 1, Tp,          Cq,          Wp + 56 * 1},
38499371c9d4SSatish Balay         {Up,          Qp + 56 * 3, Xp + 56 * 1, Dq         },
38509371c9d4SSatish Balay         {Rp,          Up,          Dq,          Zp         },
38519371c9d4SSatish Balay         {Vp,          Rp,          Zp,          Bq         },
38529371c9d4SSatish Balay         {Qp + 56 * 2, Vp,          Bq,          Xp         },
3853b7f5c055SJed Brown         /* layer 7 (the top is the periodic image of the bottom of layer 0) */
38549371c9d4SSatish Balay         {Yp,          Aq,          C + 56 * 4,  A + 56 * 4 },
38559371c9d4SSatish Balay         {Aq,          Wp,          B + 56 * 4,  C + 56 * 4 },
38569371c9d4SSatish Balay         {Cq,          Yp,          A + 56 * 4,  D + 56 * 4 },
38579371c9d4SSatish Balay         {Wp + 56 * 1, Cq,          D + 56 * 4,  B + 56 * 5 },
38589371c9d4SSatish Balay         {Dq,          Xp + 56 * 1, B + 56 * 5,  E + 56 * 4 },
38599371c9d4SSatish Balay         {Zp,          Dq,          E + 56 * 4,  A + 56 * 6 },
38609371c9d4SSatish Balay         {Bq,          Zp,          A + 56 * 6,  F + 56 * 4 },
38619371c9d4SSatish Balay         {Xp,          Bq,          F + 56 * 4,  B + 56 * 4 }
3862b7f5c055SJed Brown       };
3863b7f5c055SJed Brown       const PetscReal gamma                = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI;
38649371c9d4SSatish Balay       const PetscReal patternCoords[56][3] = {
3865bee3fc89SBarry Smith         {1.,        0.,        0.  }, /* A  */
3866bee3fc89SBarry Smith         {0.,        1.,        0.  }, /* B  */
3867bee3fc89SBarry Smith         {gamma,     gamma,     0.  }, /* C  */
3868bee3fc89SBarry Smith         {1 + gamma, 1 - gamma, 0.  }, /* D  */
3869bee3fc89SBarry Smith         {2 - gamma, 2 - gamma, 0.  }, /* E  */
3870bee3fc89SBarry Smith         {1 - gamma, 1 + gamma, 0.  }, /* F  */
3871b7f5c055SJed Brown 
3872bee3fc89SBarry Smith         {.5,        0,         .25 }, /* G  */
3873bee3fc89SBarry Smith         {1.5,       0.,        .25 }, /* H  */
3874bee3fc89SBarry Smith         {.5,        1.,        .25 }, /* II */
3875bee3fc89SBarry Smith         {1.5,       1.,        .25 }, /* J  */
3876bee3fc89SBarry Smith         {.25,       .5,        .25 }, /* K  */
3877bee3fc89SBarry Smith         {1.25,      .5,        .25 }, /* L  */
3878bee3fc89SBarry Smith         {.75,       1.5,       .25 }, /* M  */
3879bee3fc89SBarry Smith         {1.75,      1.5,       .25 }, /* N  */
3880b7f5c055SJed Brown 
3881bee3fc89SBarry Smith         {0.,        0.,        .5  }, /* O  */
3882bee3fc89SBarry Smith         {1.,        1.,        .5  }, /* P  */
3883bee3fc89SBarry Smith         {gamma,     1 - gamma, .5  }, /* Q  */
3884bee3fc89SBarry Smith         {1 + gamma, gamma,     .5  }, /* R  */
3885bee3fc89SBarry Smith         {2 - gamma, 1 + gamma, .5  }, /* S  */
3886bee3fc89SBarry Smith         {1 - gamma, 2 - gamma, .5  }, /* T  */
3887b7f5c055SJed Brown 
3888bee3fc89SBarry Smith         {0.,        .5,        .75 }, /* U  */
3889bee3fc89SBarry Smith         {0.,        1.5,       .75 }, /* V  */
3890bee3fc89SBarry Smith         {1.,        .5,        .75 }, /* W  */
3891bee3fc89SBarry Smith         {1.,        1.5,       .75 }, /* X  */
3892bee3fc89SBarry Smith         {.5,        .75,       .75 }, /* Y  */
3893bee3fc89SBarry Smith         {.5,        1.75,      .75 }, /* Z  */
3894bee3fc89SBarry Smith         {1.5,       .25,       .75 }, /* Ap */
3895bee3fc89SBarry Smith         {1.5,       1.25,      .75 }, /* Bp */
3896b7f5c055SJed Brown 
3897bee3fc89SBarry Smith         {1.,        0.,        1.  }, /* Cp */
3898bee3fc89SBarry Smith         {0.,        1.,        1.  }, /* Dp */
3899bee3fc89SBarry Smith         {1 - gamma, 1 - gamma, 1.  }, /* Ep */
3900bee3fc89SBarry Smith         {1 + gamma, 1 + gamma, 1.  }, /* Fp */
3901bee3fc89SBarry Smith         {2 - gamma, gamma,     1.  }, /* Gp */
3902bee3fc89SBarry Smith         {gamma,     2 - gamma, 1.  }, /* Hp */
3903b7f5c055SJed Brown 
3904bee3fc89SBarry Smith         {.5,        0.,        1.25}, /* Ip */
3905bee3fc89SBarry Smith         {1.5,       0.,        1.25}, /* Jp */
3906bee3fc89SBarry Smith         {.5,        1.,        1.25}, /* Kp */
3907bee3fc89SBarry Smith         {1.5,       1.,        1.25}, /* Lp */
3908bee3fc89SBarry Smith         {.75,       .5,        1.25}, /* Mp */
3909bee3fc89SBarry Smith         {1.75,      .5,        1.25}, /* Np */
3910bee3fc89SBarry Smith         {.25,       1.5,       1.25}, /* Op */
3911bee3fc89SBarry Smith         {1.25,      1.5,       1.25}, /* Pp */
3912b7f5c055SJed Brown 
3913bee3fc89SBarry Smith         {0.,        0.,        1.5 }, /* Qp */
3914bee3fc89SBarry Smith         {1.,        1.,        1.5 }, /* Rp */
3915bee3fc89SBarry Smith         {1 - gamma, gamma,     1.5 }, /* Sp */
3916bee3fc89SBarry Smith         {2 - gamma, 1 - gamma, 1.5 }, /* Tp */
3917bee3fc89SBarry Smith         {1 + gamma, 2 - gamma, 1.5 }, /* Up */
3918bee3fc89SBarry Smith         {gamma,     1 + gamma, 1.5 }, /* Vp */
3919b7f5c055SJed Brown 
3920bee3fc89SBarry Smith         {0.,        .5,        1.75}, /* Wp */
3921bee3fc89SBarry Smith         {0.,        1.5,       1.75}, /* Xp */
3922bee3fc89SBarry Smith         {1.,        .5,        1.75}, /* Yp */
3923bee3fc89SBarry Smith         {1.,        1.5,       1.75}, /* Zp */
3924bee3fc89SBarry Smith         {.5,        .25,       1.75}, /* Aq */
3925bee3fc89SBarry Smith         {.5,        1.25,      1.75}, /* Bq */
3926bee3fc89SBarry Smith         {1.5,       .75,       1.75}, /* Cq */
3927bee3fc89SBarry Smith         {1.5,       1.75,      1.75}, /* Dq */
3928b7f5c055SJed Brown       };
3929b7f5c055SJed Brown       PetscInt(*cells)[64][4] = NULL;
3930b7f5c055SJed Brown       PetscBool *seen;
3931b7f5c055SJed Brown       PetscInt  *vertToTrueVert;
3932b7f5c055SJed Brown       PetscInt   count;
3933b7f5c055SJed Brown 
3934b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1;
3935b7f5c055SJed Brown       numBlocks = 1;
3936b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i];
3937b7f5c055SJed Brown       numBlocksPlus = 1;
3938b7f5c055SJed Brown       for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i];
3939b7f5c055SJed Brown       numFaces = numBlocks * facesPerBlock;
39409566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocks, &cells));
39419566063dSJacob Faibussowitsch       PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen));
3942b7f5c055SJed Brown       for (PetscInt k = 0; k < extent[2]; k++) {
3943b7f5c055SJed Brown         for (PetscInt j = 0; j < extent[1]; j++) {
3944b7f5c055SJed Brown           for (PetscInt i = 0; i < extent[0]; i++) {
3945b7f5c055SJed Brown             for (PetscInt f = 0; f < facesPerBlock; f++) {
3946b7f5c055SJed Brown               for (PetscInt v = 0; v < 4; v++) {
3947b7f5c055SJed Brown                 PetscInt vertRaw     = pattern[f][v];
3948b7f5c055SJed Brown                 PetscInt blockidx    = vertRaw / 56;
3949b7f5c055SJed Brown                 PetscInt patternvert = vertRaw % 56;
3950b7f5c055SJed Brown                 PetscInt xplus       = (blockidx & 1);
3951b7f5c055SJed Brown                 PetscInt yplus       = (blockidx & 2) >> 1;
3952b7f5c055SJed Brown                 PetscInt zplus       = (blockidx & 4) >> 2;
3953b7f5c055SJed Brown                 PetscInt zcoord      = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus);
3954b7f5c055SJed Brown                 PetscInt ycoord      = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus);
3955b7f5c055SJed Brown                 PetscInt xcoord      = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus);
3956b7f5c055SJed Brown                 PetscInt vert        = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert;
3957b7f5c055SJed Brown 
3958b7f5c055SJed Brown                 cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert;
3959b7f5c055SJed Brown                 seen[vert]                                       = PETSC_TRUE;
3960b7f5c055SJed Brown               }
3961b7f5c055SJed Brown             }
3962b7f5c055SJed Brown           }
3963b7f5c055SJed Brown         }
3964b7f5c055SJed Brown       }
39659371c9d4SSatish Balay       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++)
39669371c9d4SSatish Balay         if (seen[i]) numVertices++;
3967b7f5c055SJed Brown       count = 0;
39689566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert));
39699566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords));
3970b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1;
3971b7f5c055SJed Brown       for (PetscInt k = 0; k < extentPlus[2]; k++) {
3972b7f5c055SJed Brown         for (PetscInt j = 0; j < extentPlus[1]; j++) {
3973b7f5c055SJed Brown           for (PetscInt i = 0; i < extentPlus[0]; i++) {
3974b7f5c055SJed Brown             for (PetscInt v = 0; v < vertsPerBlock; v++) {
3975b7f5c055SJed Brown               PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v;
3976b7f5c055SJed Brown 
3977b7f5c055SJed Brown               if (seen[vIdx]) {
3978b7f5c055SJed Brown                 PetscInt thisVert;
3979b7f5c055SJed Brown 
3980b7f5c055SJed Brown                 vertToTrueVert[vIdx] = thisVert = count++;
3981b7f5c055SJed Brown 
3982b7f5c055SJed Brown                 for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d];
3983b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 0] += i * 2;
3984b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 1] += j * 2;
3985b7f5c055SJed Brown                 vtxCoords[3 * thisVert + 2] += k * 2;
3986b7f5c055SJed Brown               }
3987b7f5c055SJed Brown             }
3988b7f5c055SJed Brown           }
3989b7f5c055SJed Brown         }
3990b7f5c055SJed Brown       }
3991b7f5c055SJed Brown       for (PetscInt i = 0; i < numBlocks; i++) {
3992b7f5c055SJed Brown         for (PetscInt f = 0; f < facesPerBlock; f++) {
3993ad540459SPierre Jolivet           for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]];
3994b7f5c055SJed Brown         }
3995b7f5c055SJed Brown       }
39969566063dSJacob Faibussowitsch       PetscCall(PetscFree(vertToTrueVert));
39979566063dSJacob Faibussowitsch       PetscCall(PetscFree(seen));
3998b7f5c055SJed Brown       cells_flat = cells[0][0];
3999b7f5c055SJed Brown       numEdges   = 0;
4000b7f5c055SJed Brown       for (PetscInt i = 0; i < numFaces; i++) {
4001b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
4002b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
4003b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
4004b7f5c055SJed Brown 
4005b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
4006b7f5c055SJed Brown             if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) {
4007b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++;
4008b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++;
4009b7f5c055SJed Brown             }
4010b7f5c055SJed Brown           }
4011b7f5c055SJed Brown         }
4012b7f5c055SJed Brown       }
40139566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edges));
40149566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numEdges, &edgeSets));
4015b7f5c055SJed Brown       for (PetscInt edge = 0, i = 0; i < numFaces; i++) {
4016b7f5c055SJed Brown         for (PetscInt e = 0; e < 4; e++) {
4017b7f5c055SJed Brown           PetscInt         ev[]       = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]};
4018b7f5c055SJed Brown           const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]};
4019b7f5c055SJed Brown 
4020b7f5c055SJed Brown           for (PetscInt d = 0; d < 3; d++) {
4021b7f5c055SJed Brown             if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) {
4022b7f5c055SJed Brown               if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) {
4023b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
4024b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
4025b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d;
4026b7f5c055SJed Brown               }
4027b7f5c055SJed Brown               if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) {
4028b7f5c055SJed Brown                 edges[edge][0]   = ev[0];
4029b7f5c055SJed Brown                 edges[edge][1]   = ev[1];
4030b7f5c055SJed Brown                 edgeSets[edge++] = 2 * d + 1;
4031b7f5c055SJed Brown               }
4032b7f5c055SJed Brown             }
4033b7f5c055SJed Brown           }
4034b7f5c055SJed Brown         }
4035b7f5c055SJed Brown       }
4036b7f5c055SJed Brown     }
4037b7f5c055SJed Brown     evalFunc   = TPSEvaluate_Gyroid;
40384663dae6SJed Brown     normalFunc = TPSExtrudeNormalFunc_Gyroid;
4039b7f5c055SJed Brown     break;
4040b7f5c055SJed Brown   }
4041b7f5c055SJed Brown 
40429566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(dm, topoDim));
4043c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat));
40449566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL));
40459566063dSJacob Faibussowitsch   PetscCall(PetscFree(cells_flat));
4046b7f5c055SJed Brown   {
4047b7f5c055SJed Brown     DM idm;
40489566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(dm, &idm));
404969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &idm));
4050b7f5c055SJed Brown   }
4051c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords));
40529566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL));
40539566063dSJacob Faibussowitsch   PetscCall(PetscFree(vtxCoords));
4054b7f5c055SJed Brown 
40559566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "Face Sets"));
40569566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
4057b7f5c055SJed Brown   for (PetscInt e = 0; e < numEdges; e++) {
4058b7f5c055SJed Brown     PetscInt        njoin;
4059b7f5c055SJed Brown     const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]};
40609566063dSJacob Faibussowitsch     PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join));
406163a3b9bcSJacob 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]);
40629566063dSJacob Faibussowitsch     PetscCall(DMLabelSetValue(label, join[0], edgeSets[e]));
40639566063dSJacob Faibussowitsch     PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join));
4064b7f5c055SJed Brown   }
40659566063dSJacob Faibussowitsch   PetscCall(PetscFree(edges));
40669566063dSJacob Faibussowitsch   PetscCall(PetscFree(edgeSets));
40671436d7faSJed Brown   if (tps_distribute) {
40681436d7faSJed Brown     DM               pdm = NULL;
40691436d7faSJed Brown     PetscPartitioner part;
40701436d7faSJed Brown 
40719566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
40729566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
40739566063dSJacob Faibussowitsch     PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm));
407448a46eb9SPierre Jolivet     if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm));
40751436d7faSJed Brown     // Do not auto-distribute again
40769566063dSJacob Faibussowitsch     PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE));
40771436d7faSJed Brown   }
4078b7f5c055SJed Brown 
40799566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
4080b7f5c055SJed Brown   for (PetscInt refine = 0; refine < refinements; refine++) {
4081b7f5c055SJed Brown     PetscInt     m;
4082b7f5c055SJed Brown     DM           dmf;
4083b7f5c055SJed Brown     Vec          X;
4084b7f5c055SJed Brown     PetscScalar *x;
40859566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf));
408669d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmf));
4087b7f5c055SJed Brown 
40889566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &X));
40899566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(X, &m));
40909566063dSJacob Faibussowitsch     PetscCall(VecGetArray(X, &x));
409148a46eb9SPierre Jolivet     for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i]));
40929566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(X, &x));
4093b7f5c055SJed Brown   }
4094b7f5c055SJed Brown 
4095b7f5c055SJed Brown   // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices.
40969566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "Face Sets", &label));
40979566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, label));
4098b7f5c055SJed Brown 
409946139095SJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0));
410046139095SJed Brown 
4101b7f5c055SJed Brown   if (thickness > 0) {
41024663dae6SJed Brown     DM              edm, cdm, ecdm;
41034663dae6SJed Brown     DMPlexTransform tr;
41044663dae6SJed Brown     const char     *prefix;
41054663dae6SJed Brown     PetscOptions    options;
41064663dae6SJed Brown     // Code from DMPlexExtrude
41074663dae6SJed Brown     PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr));
41084663dae6SJed Brown     PetscCall(DMPlexTransformSetDM(tr, dm));
41094663dae6SJed Brown     PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE));
41104663dae6SJed Brown     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix));
41114663dae6SJed Brown     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix));
41124663dae6SJed Brown     PetscCall(PetscObjectGetOptions((PetscObject)dm, &options));
41134663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, options));
41144663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers));
41154663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness));
41164663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE));
41174663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE));
41184663dae6SJed Brown     PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc));
41194663dae6SJed Brown     PetscCall(DMPlexTransformSetFromOptions(tr));
41204663dae6SJed Brown     PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL));
41214663dae6SJed Brown     PetscCall(DMPlexTransformSetUp(tr));
41224663dae6SJed Brown     PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view"));
41234663dae6SJed Brown     PetscCall(DMPlexTransformApply(tr, dm, &edm));
41244663dae6SJed Brown     PetscCall(DMCopyDisc(dm, edm));
41254663dae6SJed Brown     PetscCall(DMGetCoordinateDM(dm, &cdm));
41264663dae6SJed Brown     PetscCall(DMGetCoordinateDM(edm, &ecdm));
41274663dae6SJed Brown     PetscCall(DMCopyDisc(cdm, ecdm));
41284663dae6SJed Brown     PetscCall(DMPlexTransformCreateDiscLabels(tr, edm));
41294663dae6SJed Brown     PetscCall(DMPlexTransformDestroy(&tr));
4130a77a5016SMatthew G. Knepley     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, edm));
413169d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
4132b7f5c055SJed Brown   }
41333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4134b7f5c055SJed Brown }
4135b7f5c055SJed Brown 
4136b7f5c055SJed Brown /*@
4137b7f5c055SJed Brown   DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface
4138b7f5c055SJed Brown 
4139b7f5c055SJed Brown   Collective
4140b7f5c055SJed Brown 
4141b7f5c055SJed Brown   Input Parameters:
4142a1cb98faSBarry Smith + comm           - The communicator for the `DM` object
4143b7f5c055SJed Brown . tpstype        - Type of triply-periodic surface
4144b7f5c055SJed Brown . extent         - Array of length 3 containing number of periods in each direction
414520f4b53cSBarry Smith . periodic       - array of length 3 with periodicity, or `NULL` for non-periodic
41461436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable)
4147817da375SSatish Balay . refinements    - Number of factor-of-2 refinements of 2D manifold mesh
41481436d7faSJed Brown . layers         - Number of cell layers extruded in normal direction
4149817da375SSatish Balay - thickness      - Thickness in normal direction
4150b7f5c055SJed Brown 
4151b7f5c055SJed Brown   Output Parameter:
4152a1cb98faSBarry Smith . dm - The `DM` object
4153a1cb98faSBarry Smith 
4154a1cb98faSBarry Smith   Level: beginner
4155b7f5c055SJed Brown 
4156b7f5c055SJed Brown   Notes:
415715229ffcSPierre Jolivet   This meshes the surface of the Schwarz P or Gyroid surfaces.  Schwarz P is the simplest member of the triply-periodic minimal surfaces.
41581d27aa22SBarry Smith   <https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22)> and can be cut with "clean" boundaries.
41591d27aa22SBarry 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.
4160b7f5c055SJed Brown   Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested.
4161b7f5c055SJed Brown   On each refinement, all vertices are projected to their nearest point on the surface.
4162b7f5c055SJed Brown   This projection could readily be extended to related surfaces.
4163b7f5c055SJed Brown 
41641d27aa22SBarry Smith   See {cite}`maskery2018insights`
41651d27aa22SBarry Smith 
41661d27aa22SBarry Smith   The face (edge) sets for the Schwarz P surface are numbered $1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z)$.
41671d27aa22SBarry Smith   When the mesh is refined, "Face Sets" contain the new vertices (created during refinement).
41681d27aa22SBarry Smith   Use `DMPlexLabelComplete()` to propagate to coarse-level vertices.
4169b7f5c055SJed Brown 
417060225df5SJacob Faibussowitsch   Developer Notes:
4171b7f5c055SJed Brown   The Gyroid mesh does not currently mark boundary sets.
4172b7f5c055SJed Brown 
41731cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()`
4174b7f5c055SJed Brown @*/
4175d71ae5a4SJacob 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)
4176d71ae5a4SJacob Faibussowitsch {
4177b7f5c055SJed Brown   PetscFunctionBegin;
41789566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
41799566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
41809566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness));
41813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4182b7f5c055SJed Brown }
4183b7f5c055SJed Brown 
41849318fe57SMatthew G. Knepley /*@
41859318fe57SMatthew G. Knepley   DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d.
41869318fe57SMatthew G. Knepley 
41879318fe57SMatthew G. Knepley   Collective
41889318fe57SMatthew G. Knepley 
41899318fe57SMatthew G. Knepley   Input Parameters:
4190a1cb98faSBarry Smith + comm    - The communicator for the `DM` object
41919318fe57SMatthew G. Knepley . dim     - The dimension
41929318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells
41939318fe57SMatthew G. Knepley - R       - The radius
41949318fe57SMatthew G. Knepley 
41959318fe57SMatthew G. Knepley   Output Parameter:
4196a1cb98faSBarry Smith . dm - The `DM` object
41979318fe57SMatthew G. Knepley 
41989318fe57SMatthew G. Knepley   Level: beginner
41999318fe57SMatthew G. Knepley 
42001cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
42019318fe57SMatthew G. Knepley @*/
4202d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm)
4203d71ae5a4SJacob Faibussowitsch {
42049318fe57SMatthew G. Knepley   PetscFunctionBegin;
42054f572ea9SToby Isaac   PetscAssertPointer(dm, 5);
42069566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
42079566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
42089566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R));
42093ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42109318fe57SMatthew G. Knepley }
42119318fe57SMatthew G. Knepley 
4212d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R)
4213d71ae5a4SJacob Faibussowitsch {
42149318fe57SMatthew G. Knepley   DM          sdm, vol;
42159318fe57SMatthew G. Knepley   DMLabel     bdlabel;
4216dd2b43ebSStefano Zampini   const char *prefix;
42179318fe57SMatthew G. Knepley 
42189318fe57SMatthew G. Knepley   PetscFunctionBegin;
42199566063dSJacob Faibussowitsch   PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm));
42209566063dSJacob Faibussowitsch   PetscCall(DMSetType(sdm, DMPLEX));
4221dd2b43ebSStefano Zampini   PetscCall(DMGetOptionsPrefix(dm, &prefix));
4222dd2b43ebSStefano Zampini   PetscCall(DMSetOptionsPrefix(sdm, prefix));
4223dd2b43ebSStefano Zampini   PetscCall(DMAppendOptionsPrefix(sdm, "bd_"));
4224dd2b43ebSStefano Zampini   PetscCall(DMPlexDistributeSetDefault(sdm, PETSC_FALSE));
42259566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R));
42269566063dSJacob Faibussowitsch   PetscCall(DMSetFromOptions(sdm));
42279566063dSJacob Faibussowitsch   PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view"));
42289566063dSJacob Faibussowitsch   PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol));
42299566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&sdm));
423069d8a87bSksagiyam   PetscCall(DMPlexReplace_Internal(dm, &vol));
42319566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, "marker"));
42329566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, "marker", &bdlabel));
42339566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel));
42349566063dSJacob Faibussowitsch   PetscCall(DMPlexLabelComplete(dm, bdlabel));
42353ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
423651a74b61SMatthew G. Knepley }
423751a74b61SMatthew G. Knepley 
423851a74b61SMatthew G. Knepley /*@
423951a74b61SMatthew G. Knepley   DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d.
424051a74b61SMatthew G. Knepley 
424151a74b61SMatthew G. Knepley   Collective
424251a74b61SMatthew G. Knepley 
424351a74b61SMatthew G. Knepley   Input Parameters:
4244a1cb98faSBarry Smith + comm - The communicator for the `DM` object
424551a74b61SMatthew G. Knepley . dim  - The dimension
424651a74b61SMatthew G. Knepley - R    - The radius
424751a74b61SMatthew G. Knepley 
424851a74b61SMatthew G. Knepley   Output Parameter:
4249a1cb98faSBarry Smith . dm - The `DM` object
425051a74b61SMatthew G. Knepley 
4251a1cb98faSBarry Smith   Options Database Key:
425260225df5SJacob Faibussowitsch . bd_dm_refine - This will refine the surface mesh preserving the sphere geometry
425351a74b61SMatthew G. Knepley 
425451a74b61SMatthew G. Knepley   Level: beginner
425551a74b61SMatthew G. Knepley 
42561cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()`
425751a74b61SMatthew G. Knepley @*/
4258d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm)
4259d71ae5a4SJacob Faibussowitsch {
426051a74b61SMatthew G. Knepley   PetscFunctionBegin;
42619566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
42629566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
42639566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R));
42643ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
42652829fed8SMatthew G. Knepley }
42662829fed8SMatthew G. Knepley 
4267d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct)
4268d71ae5a4SJacob Faibussowitsch {
42690a6ba040SMatthew G. Knepley   PetscFunctionBegin;
42709318fe57SMatthew G. Knepley   switch (ct) {
42719371c9d4SSatish Balay   case DM_POLYTOPE_POINT: {
42729318fe57SMatthew G. Knepley     PetscInt    numPoints[1]        = {1};
42739318fe57SMatthew G. Knepley     PetscInt    coneSize[1]         = {0};
42749318fe57SMatthew G. Knepley     PetscInt    cones[1]            = {0};
42759318fe57SMatthew G. Knepley     PetscInt    coneOrientations[1] = {0};
42769318fe57SMatthew G. Knepley     PetscScalar vertexCoords[1]     = {0.0};
42779318fe57SMatthew G. Knepley 
42789566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 0));
42799566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords));
42809371c9d4SSatish Balay   } break;
42819371c9d4SSatish Balay   case DM_POLYTOPE_SEGMENT: {
42829318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
42839318fe57SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
42849318fe57SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
42859318fe57SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
42869318fe57SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
42879318fe57SMatthew G. Knepley 
42889566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
42899566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
42909371c9d4SSatish Balay   } break;
42919371c9d4SSatish Balay   case DM_POLYTOPE_POINT_PRISM_TENSOR: {
4292b5a892a1SMatthew G. Knepley     PetscInt    numPoints[2]        = {2, 1};
4293b5a892a1SMatthew G. Knepley     PetscInt    coneSize[3]         = {2, 0, 0};
4294b5a892a1SMatthew G. Knepley     PetscInt    cones[2]            = {1, 2};
4295b5a892a1SMatthew G. Knepley     PetscInt    coneOrientations[2] = {0, 0};
4296b5a892a1SMatthew G. Knepley     PetscScalar vertexCoords[2]     = {-1.0, 1.0};
4297b5a892a1SMatthew G. Knepley 
42989566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 1));
42999566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
43009371c9d4SSatish Balay   } break;
43019371c9d4SSatish Balay   case DM_POLYTOPE_TRIANGLE: {
43029318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {3, 1};
43039318fe57SMatthew G. Knepley     PetscInt    coneSize[4]         = {3, 0, 0, 0};
43049318fe57SMatthew G. Knepley     PetscInt    cones[3]            = {1, 2, 3};
43059318fe57SMatthew G. Knepley     PetscInt    coneOrientations[3] = {0, 0, 0};
43069318fe57SMatthew G. Knepley     PetscScalar vertexCoords[6]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0};
43079318fe57SMatthew G. Knepley 
43089566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
43099566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
43109371c9d4SSatish Balay   } break;
43119371c9d4SSatish Balay   case DM_POLYTOPE_QUADRILATERAL: {
43129318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
43139318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
43149318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
43159318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
43169318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0};
43179318fe57SMatthew G. Knepley 
43189566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
43199566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
43209371c9d4SSatish Balay   } break;
43219371c9d4SSatish Balay   case DM_POLYTOPE_SEG_PRISM_TENSOR: {
43229318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
43239318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
43249318fe57SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
43259318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
43269318fe57SMatthew G. Knepley     PetscScalar vertexCoords[8]     = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0};
43279318fe57SMatthew G. Knepley 
43289566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 2));
43299566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
43309371c9d4SSatish Balay   } break;
43319371c9d4SSatish Balay   case DM_POLYTOPE_TETRAHEDRON: {
43329318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {4, 1};
43339318fe57SMatthew G. Knepley     PetscInt    coneSize[5]         = {4, 0, 0, 0, 0};
4334f0edb160SMatthew G. Knepley     PetscInt    cones[4]            = {1, 2, 3, 4};
43359318fe57SMatthew G. Knepley     PetscInt    coneOrientations[4] = {0, 0, 0, 0};
4336f0edb160SMatthew 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};
43379318fe57SMatthew G. Knepley 
43389566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
43399566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
43409371c9d4SSatish Balay   } break;
43419371c9d4SSatish Balay   case DM_POLYTOPE_HEXAHEDRON: {
43429318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
43439318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
4344f0edb160SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
43459318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
43469371c9d4SSatish 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};
43479318fe57SMatthew G. Knepley 
43489566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
43499566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
43509371c9d4SSatish Balay   } break;
43519371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM: {
43529318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
43539318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
4354f0edb160SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
43559318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
43569371c9d4SSatish 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};
43579318fe57SMatthew G. Knepley 
43589566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
43599566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
43609371c9d4SSatish Balay   } break;
43619371c9d4SSatish Balay   case DM_POLYTOPE_TRI_PRISM_TENSOR: {
43629318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {6, 1};
43639318fe57SMatthew G. Knepley     PetscInt    coneSize[7]         = {6, 0, 0, 0, 0, 0, 0};
43649318fe57SMatthew G. Knepley     PetscInt    cones[6]            = {1, 2, 3, 4, 5, 6};
43659318fe57SMatthew G. Knepley     PetscInt    coneOrientations[6] = {0, 0, 0, 0, 0, 0};
43669371c9d4SSatish 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};
43679318fe57SMatthew G. Knepley 
43689566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
43699566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
43709371c9d4SSatish Balay   } break;
43719371c9d4SSatish Balay   case DM_POLYTOPE_QUAD_PRISM_TENSOR: {
43729318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {8, 1};
43739318fe57SMatthew G. Knepley     PetscInt    coneSize[9]         = {8, 0, 0, 0, 0, 0, 0, 0, 0};
43749318fe57SMatthew G. Knepley     PetscInt    cones[8]            = {1, 2, 3, 4, 5, 6, 7, 8};
43759318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
43769371c9d4SSatish 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};
43779318fe57SMatthew G. Knepley 
43789566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
43799566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
43809371c9d4SSatish Balay   } break;
43819371c9d4SSatish Balay   case DM_POLYTOPE_PYRAMID: {
43829318fe57SMatthew G. Knepley     PetscInt    numPoints[2]        = {5, 1};
43839318fe57SMatthew G. Knepley     PetscInt    coneSize[6]         = {5, 0, 0, 0, 0, 0};
4384f0edb160SMatthew G. Knepley     PetscInt    cones[5]            = {1, 2, 3, 4, 5};
43859318fe57SMatthew G. Knepley     PetscInt    coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0};
43869371c9d4SSatish 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};
43879318fe57SMatthew G. Knepley 
43889566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(rdm, 3));
43899566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords));
43909371c9d4SSatish Balay   } break;
4391d71ae5a4SJacob Faibussowitsch   default:
4392d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]);
43939318fe57SMatthew G. Knepley   }
43949318fe57SMatthew G. Knepley   {
43959318fe57SMatthew G. Knepley     PetscInt Nv, v;
43969318fe57SMatthew G. Knepley 
43979318fe57SMatthew G. Knepley     /* Must create the celltype label here so that we do not automatically try to compute the types */
43989566063dSJacob Faibussowitsch     PetscCall(DMCreateLabel(rdm, "celltype"));
43999566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCellType(rdm, 0, ct));
44009566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(rdm, NULL, &Nv));
44019566063dSJacob Faibussowitsch     for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT));
44029318fe57SMatthew G. Knepley   }
44039566063dSJacob Faibussowitsch   PetscCall(DMPlexInterpolateInPlace_Internal(rdm));
44049566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct]));
44053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44060a6ba040SMatthew G. Knepley }
44070a6ba040SMatthew G. Knepley 
44089318fe57SMatthew G. Knepley /*@
4409a1cb98faSBarry Smith   DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell
44109318fe57SMatthew G. Knepley 
44119318fe57SMatthew G. Knepley   Collective
44129318fe57SMatthew G. Knepley 
44139318fe57SMatthew G. Knepley   Input Parameters:
44149318fe57SMatthew G. Knepley + comm - The communicator
44159318fe57SMatthew G. Knepley - ct   - The cell type of the reference cell
44169318fe57SMatthew G. Knepley 
44179318fe57SMatthew G. Knepley   Output Parameter:
44189318fe57SMatthew G. Knepley . refdm - The reference cell
44199318fe57SMatthew G. Knepley 
44209318fe57SMatthew G. Knepley   Level: intermediate
44219318fe57SMatthew G. Knepley 
442242747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`
44239318fe57SMatthew G. Knepley @*/
4424d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm)
4425d71ae5a4SJacob Faibussowitsch {
44260a6ba040SMatthew G. Knepley   PetscFunctionBegin;
44279566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, refdm));
44289566063dSJacob Faibussowitsch   PetscCall(DMSetType(*refdm, DMPLEX));
44299566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct));
44303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44319318fe57SMatthew G. Knepley }
443279a015ccSMatthew G. Knepley 
4433d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[])
4434d71ae5a4SJacob Faibussowitsch {
44359318fe57SMatthew G. Knepley   DM        plex;
44369318fe57SMatthew G. Knepley   DMLabel   label;
44379318fe57SMatthew G. Knepley   PetscBool hasLabel;
44380a6ba040SMatthew G. Knepley 
4439c22d3578SMatthew G. Knepley   PetscFunctionBegin;
44409566063dSJacob Faibussowitsch   PetscCall(DMHasLabel(dm, name, &hasLabel));
44413ba16761SJacob Faibussowitsch   if (hasLabel) PetscFunctionReturn(PETSC_SUCCESS);
44429566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(dm, name));
44439566063dSJacob Faibussowitsch   PetscCall(DMGetLabel(dm, name, &label));
44449566063dSJacob Faibussowitsch   PetscCall(DMConvert(dm, DMPLEX, &plex));
44459566063dSJacob Faibussowitsch   PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label));
44461c8afea9SMatthew G. Knepley   PetscCall(DMPlexLabelComplete(plex, label));
44479566063dSJacob Faibussowitsch   PetscCall(DMDestroy(&plex));
44483ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
44499318fe57SMatthew G. Knepley }
4450acdc6f61SToby Isaac 
4451669647acSMatthew G. Knepley /*
4452669647acSMatthew 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.
4453669647acSMatthew G. Knepley 
4454669647acSMatthew G. Knepley     (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0]))
4455669647acSMatthew G. Knepley */
4456d71ae5a4SJacob 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[])
4457d71ae5a4SJacob Faibussowitsch {
4458669647acSMatthew G. Knepley   const PetscReal low = PetscRealPart(constants[0]);
4459669647acSMatthew G. Knepley   const PetscReal upp = PetscRealPart(constants[1]);
4460669647acSMatthew G. Knepley   const PetscReal r   = PetscRealPart(u[1]);
4461669647acSMatthew G. Knepley   const PetscReal th  = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low);
4462669647acSMatthew G. Knepley 
4463669647acSMatthew G. Knepley   f0[0] = r * PetscCosReal(th);
4464669647acSMatthew G. Knepley   f0[1] = r * PetscSinReal(th);
4465669647acSMatthew G. Knepley }
4466669647acSMatthew G. Knepley 
44675390be7dSMatthew G. Knepley // Insert vertices and their joins, marked by depth
44685390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Vertices(DM dm, DMLabel label, DMLabel vlabel, PetscInt val, PetscInt n, const PetscInt vertices[])
44695390be7dSMatthew G. Knepley {
44705390be7dSMatthew G. Knepley   PetscFunctionBegin;
44715390be7dSMatthew G. Knepley   PetscCall(DMPlexMarkSubmesh_Interpolated(dm, vlabel, val, PETSC_FALSE, PETSC_FALSE, label, NULL));
44725390be7dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
44735390be7dSMatthew G. Knepley }
44745390be7dSMatthew G. Knepley 
44755390be7dSMatthew G. Knepley // Insert faces and their closures, marked by depth
44765390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Faces(DM dm, DMLabel label, PetscInt n, const PetscInt faces[])
44775390be7dSMatthew G. Knepley {
44785390be7dSMatthew G. Knepley   PetscFunctionBegin;
44795390be7dSMatthew G. Knepley   for (PetscInt p = 0; p < n; ++p) {
44805390be7dSMatthew G. Knepley     const PetscInt point   = faces[p];
44815390be7dSMatthew G. Knepley     PetscInt      *closure = NULL;
44825390be7dSMatthew G. Knepley     PetscInt       clSize, pdepth;
44835390be7dSMatthew G. Knepley 
44845390be7dSMatthew G. Knepley     PetscCall(DMPlexGetPointDepth(dm, point, &pdepth));
44855390be7dSMatthew G. Knepley     PetscCall(DMLabelSetValue(label, point, pdepth));
44865390be7dSMatthew G. Knepley     PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure));
44875390be7dSMatthew G. Knepley     for (PetscInt cl = 0; cl < clSize * 2; cl += 2) {
44885390be7dSMatthew G. Knepley       PetscCall(DMPlexGetPointDepth(dm, closure[cl], &pdepth));
44895390be7dSMatthew G. Knepley       PetscCall(DMLabelSetValue(label, closure[cl], pdepth));
44905390be7dSMatthew G. Knepley     }
44915390be7dSMatthew G. Knepley     PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure));
44925390be7dSMatthew G. Knepley   }
44935390be7dSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
44945390be7dSMatthew G. Knepley }
44955390be7dSMatthew G. Knepley 
44964e22dd4cSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *flg);
44974e22dd4cSMatthew G. Knepley 
44985dca41c3SJed Brown const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "zbox", "unknown", "DMPlexShape", "DM_SHAPE_", NULL};
44999318fe57SMatthew G. Knepley 
4500d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm)
4501d71ae5a4SJacob Faibussowitsch {
45029318fe57SMatthew G. Knepley   DMPlexShape    shape   = DM_SHAPE_BOX;
45039318fe57SMatthew G. Knepley   DMPolytopeType cell    = DM_POLYTOPE_TRIANGLE;
45049318fe57SMatthew G. Knepley   PetscInt       dim     = 2;
4505b9da1bb3SMatthew G. Knepley   PetscBool      simplex = PETSC_TRUE, interpolate = PETSC_TRUE, orient = PETSC_FALSE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE;
4506d0812dedSMatthew G. Knepley   PetscBool      flg, flg2, fflg, strflg, bdfflg, nameflg;
45079318fe57SMatthew G. Knepley   MPI_Comm       comm;
4508ed5e4e85SVaclav Hapla   char           filename[PETSC_MAX_PATH_LEN]   = "<unspecified>";
4509ed5e4e85SVaclav Hapla   char           bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>";
4510ed5e4e85SVaclav Hapla   char           plexname[PETSC_MAX_PATH_LEN]   = "";
45114e22dd4cSMatthew G. Knepley   const char    *option;
45129318fe57SMatthew G. Knepley 
45139318fe57SMatthew G. Knepley   PetscFunctionBegin;
4514708be2fdSJed Brown   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromOptions, dm, 0, 0, 0));
45159566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
45169318fe57SMatthew G. Knepley   /* TODO Turn this into a registration interface */
45179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg));
4518d0812dedSMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_plex_file_contents", "Contents of a file format in a string", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &strflg));
45199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg));
45209566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg));
45219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL));
45229566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL));
45239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg));
45249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0));
45259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg));
45269566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg));
4527b9da1bb3SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_orient", "Orient the constructed mesh", "DMPlexOrient", orient, &orient, &flg));
45289566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg));
45299566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2));
45309566063dSJacob Faibussowitsch   if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure));
45313f3e541fSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_adj", "Debug output level all adjacency computations", "", 0, &((DM_Plex *)dm->data)->printAdj, NULL, 0));
45329318fe57SMatthew G. Knepley 
453361a622f3SMatthew G. Knepley   switch (cell) {
453461a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT:
453561a622f3SMatthew G. Knepley   case DM_POLYTOPE_SEGMENT:
453661a622f3SMatthew G. Knepley   case DM_POLYTOPE_POINT_PRISM_TENSOR:
453761a622f3SMatthew G. Knepley   case DM_POLYTOPE_TRIANGLE:
453861a622f3SMatthew G. Knepley   case DM_POLYTOPE_QUADRILATERAL:
453961a622f3SMatthew G. Knepley   case DM_POLYTOPE_TETRAHEDRON:
4540d71ae5a4SJacob Faibussowitsch   case DM_POLYTOPE_HEXAHEDRON:
4541d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_TRUE;
4542d71ae5a4SJacob Faibussowitsch     break;
4543d71ae5a4SJacob Faibussowitsch   default:
4544d71ae5a4SJacob Faibussowitsch     *useCoordSpace = PETSC_FALSE;
4545d71ae5a4SJacob Faibussowitsch     break;
454661a622f3SMatthew G. Knepley   }
454761a622f3SMatthew G. Knepley 
45489318fe57SMatthew G. Knepley   if (fflg) {
45499318fe57SMatthew G. Knepley     DM          dmnew;
45501e4a82c4SMatthew G. Knepley     const char *name;
45519318fe57SMatthew G. Knepley 
45521e4a82c4SMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
45531e4a82c4SMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, nameflg ? plexname : name, interpolate, &dmnew));
45545de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
455569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
45569318fe57SMatthew G. Knepley   } else if (refDomain) {
45579566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell));
45589318fe57SMatthew G. Knepley   } else if (bdfflg) {
45599318fe57SMatthew G. Knepley     DM          bdm, dmnew;
45601e4a82c4SMatthew G. Knepley     const char *name;
45619318fe57SMatthew G. Knepley 
45621e4a82c4SMatthew G. Knepley     PetscCall(PetscObjectGetName((PetscObject)dm, &name));
45631e4a82c4SMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, nameflg ? plexname : name, interpolate, &bdm));
45649566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_"));
45659566063dSJacob Faibussowitsch     PetscCall(DMSetFromOptions(bdm));
45669566063dSJacob Faibussowitsch     PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew));
45679566063dSJacob Faibussowitsch     PetscCall(DMDestroy(&bdm));
45685de52c6dSVaclav Hapla     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
456969d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
4570d0812dedSMatthew G. Knepley   } else if (strflg) {
4571d0812dedSMatthew G. Knepley     DM          dmnew;
4572d0812dedSMatthew G. Knepley     PetscViewer viewer;
4573d0812dedSMatthew G. Knepley     const char *contents;
4574d0812dedSMatthew G. Knepley     char       *strname;
4575d0812dedSMatthew G. Knepley     char        tmpdir[PETSC_MAX_PATH_LEN];
4576d0812dedSMatthew G. Knepley     char        tmpfilename[PETSC_MAX_PATH_LEN];
4577d0812dedSMatthew G. Knepley     char        name[PETSC_MAX_PATH_LEN];
4578d0812dedSMatthew G. Knepley     MPI_Comm    comm;
4579d0812dedSMatthew G. Knepley     PetscMPIInt rank;
4580d0812dedSMatthew G. Knepley 
4581d0812dedSMatthew G. Knepley     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
4582d0812dedSMatthew G. Knepley     PetscCallMPI(MPI_Comm_rank(comm, &rank));
4583d0812dedSMatthew G. Knepley     PetscCall(PetscStrchr(filename, ':', &strname));
4584d0812dedSMatthew G. Knepley     PetscCheck(strname, comm, PETSC_ERR_ARG_WRONG, "File contents must have the form \"ext:string_name\", not %s", filename);
4585d0812dedSMatthew G. Knepley     strname[0] = '\0';
4586d0812dedSMatthew G. Knepley     ++strname;
4587d0812dedSMatthew G. Knepley     PetscCall(PetscDLSym(NULL, strname, (void **)&contents));
4588d0812dedSMatthew G. Knepley     PetscCheck(contents, comm, PETSC_ERR_ARG_WRONG, "Could not locate mesh string %s", strname);
4589d0812dedSMatthew G. Knepley     PetscCall(PetscGetTmp(comm, tmpdir, PETSC_MAX_PATH_LEN));
4590ed32af8cSMatthew G. Knepley     PetscCall(PetscStrlcat(tmpdir, "/meshXXXXXX", PETSC_MAX_PATH_LEN));
4591ed32af8cSMatthew G. Knepley     PetscCall(PetscMkdtemp(tmpdir));
4592ed32af8cSMatthew G. Knepley     PetscCall(PetscSNPrintf(tmpfilename, PETSC_MAX_PATH_LEN, "%s/mesh.%s", tmpdir, filename));
4593d0812dedSMatthew G. Knepley     PetscCall(PetscViewerASCIIOpen(comm, tmpfilename, &viewer));
4594d0812dedSMatthew G. Knepley     PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", contents));
4595d0812dedSMatthew G. Knepley     PetscCall(PetscViewerDestroy(&viewer));
4596d0812dedSMatthew G. Knepley     PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), tmpfilename, plexname, interpolate, &dmnew));
4597ed32af8cSMatthew G. Knepley     PetscCall(PetscRMTree(tmpdir));
4598d0812dedSMatthew G. Knepley     PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%s Mesh", strname));
4599d0812dedSMatthew G. Knepley     PetscCall(PetscObjectSetName((PetscObject)dm, name));
4600d0812dedSMatthew G. Knepley     PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
4601d0812dedSMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &dmnew));
46029318fe57SMatthew G. Knepley   } else {
46039566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape]));
46049318fe57SMatthew G. Knepley     switch (shape) {
4605669647acSMatthew G. Knepley     case DM_SHAPE_BOX:
46065dca41c3SJed Brown     case DM_SHAPE_ZBOX:
4607669647acSMatthew G. Knepley     case DM_SHAPE_ANNULUS: {
46089318fe57SMatthew G. Knepley       PetscInt       faces[3]  = {0, 0, 0};
46099318fe57SMatthew G. Knepley       PetscReal      lower[3]  = {0, 0, 0};
46109318fe57SMatthew G. Knepley       PetscReal      upper[3]  = {1, 1, 1};
46119318fe57SMatthew G. Knepley       DMBoundaryType bdt[3]    = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
4612669647acSMatthew G. Knepley       PetscBool      isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE;
46139318fe57SMatthew G. Knepley       PetscInt       i, n;
46149318fe57SMatthew G. Knepley 
46159318fe57SMatthew G. Knepley       n = dim;
46169318fe57SMatthew G. Knepley       for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim);
46179566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
46189318fe57SMatthew G. Knepley       n = 3;
46199566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
462063a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
46219318fe57SMatthew G. Knepley       n = 3;
46229566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
462363a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
46249318fe57SMatthew G. Knepley       n = 3;
46259566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
462663a3b9bcSJacob Faibussowitsch       PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim);
4627669647acSMatthew G. Knepley 
4628669647acSMatthew G. Knepley       PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented");
4629669647acSMatthew G. Knepley       if (isAnnular)
4630669647acSMatthew G. Knepley         for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC;
4631669647acSMatthew G. Knepley 
46329318fe57SMatthew G. Knepley       switch (cell) {
463361a622f3SMatthew G. Knepley       case DM_POLYTOPE_TRI_PRISM_TENSOR:
46349566063dSJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt));
4635d410b0cfSMatthew G. Knepley         if (!interpolate) {
4636d410b0cfSMatthew G. Knepley           DM udm;
4637d410b0cfSMatthew G. Knepley 
46389566063dSJacob Faibussowitsch           PetscCall(DMPlexUninterpolate(dm, &udm));
463969d8a87bSksagiyam           PetscCall(DMPlexReplace_Internal(dm, &udm));
4640d410b0cfSMatthew G. Knepley         }
46419318fe57SMatthew G. Knepley         break;
4642d71ae5a4SJacob Faibussowitsch       default:
46435dca41c3SJed Brown         PetscCall(DMPlexCreateBoxMesh_Internal(dm, shape, dim, simplex, faces, lower, upper, bdt, interpolate));
4644d71ae5a4SJacob Faibussowitsch         break;
46459318fe57SMatthew G. Knepley       }
4646669647acSMatthew G. Knepley       if (isAnnular) {
4647669647acSMatthew G. Knepley         DM          cdm;
4648669647acSMatthew G. Knepley         PetscDS     cds;
4649669647acSMatthew G. Knepley         PetscScalar bounds[2] = {lower[0], upper[0]};
4650669647acSMatthew G. Knepley 
4651669647acSMatthew G. Knepley         // Fix coordinates for annular region
4652669647acSMatthew G. Knepley         PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL));
4653669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinatesLocal(dm, NULL));
4654669647acSMatthew G. Knepley         PetscCall(DMSetCellCoordinates(dm, NULL));
4655e44f6aebSMatthew G. Knepley         PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL));
4656669647acSMatthew G. Knepley         PetscCall(DMGetCoordinateDM(dm, &cdm));
4657669647acSMatthew G. Knepley         PetscCall(DMGetDS(cdm, &cds));
4658669647acSMatthew G. Knepley         PetscCall(PetscDSSetConstants(cds, 2, bounds));
4659669647acSMatthew G. Knepley         PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus));
4660669647acSMatthew G. Knepley       }
46619371c9d4SSatish Balay     } break;
46629371c9d4SSatish Balay     case DM_SHAPE_BOX_SURFACE: {
46639318fe57SMatthew G. Knepley       PetscInt  faces[3] = {0, 0, 0};
46649318fe57SMatthew G. Knepley       PetscReal lower[3] = {0, 0, 0};
46659318fe57SMatthew G. Knepley       PetscReal upper[3] = {1, 1, 1};
46669318fe57SMatthew G. Knepley       PetscInt  i, n;
46679318fe57SMatthew G. Knepley 
46689318fe57SMatthew G. Knepley       n = dim + 1;
46699318fe57SMatthew G. Knepley       for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1));
46709566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg));
46719318fe57SMatthew G. Knepley       n = 3;
46729566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
467363a3b9bcSJacob 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);
46749318fe57SMatthew G. Knepley       n = 3;
46759566063dSJacob Faibussowitsch       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
467663a3b9bcSJacob 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);
46779566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate));
46789371c9d4SSatish Balay     } break;
46799371c9d4SSatish Balay     case DM_SHAPE_SPHERE: {
46809318fe57SMatthew G. Knepley       PetscReal R = 1.0;
46819318fe57SMatthew G. Knepley 
46829566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg));
46839566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R));
46849371c9d4SSatish Balay     } break;
46859371c9d4SSatish Balay     case DM_SHAPE_BALL: {
46869318fe57SMatthew G. Knepley       PetscReal R = 1.0;
46879318fe57SMatthew G. Knepley 
46889566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg));
46899566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R));
46909371c9d4SSatish Balay     } break;
46919371c9d4SSatish Balay     case DM_SHAPE_CYLINDER: {
46929318fe57SMatthew G. Knepley       DMBoundaryType bdt = DM_BOUNDARY_NONE;
46939318fe57SMatthew G. Knepley       PetscInt       Nw  = 6;
469449704ca5SMatthew G. Knepley       PetscInt       Nr  = 0;
46959318fe57SMatthew G. Knepley 
46969566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL));
46979566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL));
469849704ca5SMatthew G. Knepley       PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_refine", "Number of refinements before projection", "", Nr, &Nr, NULL));
46999318fe57SMatthew G. Knepley       switch (cell) {
4700d71ae5a4SJacob Faibussowitsch       case DM_POLYTOPE_TRI_PRISM_TENSOR:
4701d71ae5a4SJacob Faibussowitsch         PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate));
4702d71ae5a4SJacob Faibussowitsch         break;
4703d71ae5a4SJacob Faibussowitsch       default:
470449704ca5SMatthew G. Knepley         PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt, Nr));
4705d71ae5a4SJacob Faibussowitsch         break;
47069318fe57SMatthew G. Knepley       }
47079371c9d4SSatish Balay     } break;
4708b7f5c055SJed Brown     case DM_SHAPE_SCHWARZ_P: // fallthrough
47099371c9d4SSatish Balay     case DM_SHAPE_GYROID: {
4710b7f5c055SJed Brown       PetscInt       extent[3] = {1, 1, 1}, refine = 0, layers = 0, three;
4711b7f5c055SJed Brown       PetscReal      thickness   = 0.;
4712b7f5c055SJed Brown       DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
4713b7f5c055SJed Brown       DMPlexTPSType  tps_type    = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID;
47141436d7faSJed Brown       PetscBool      tps_distribute;
47159566063dSJacob Faibussowitsch       PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL));
47169566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL));
47179566063dSJacob Faibussowitsch       PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL));
47189566063dSJacob Faibussowitsch       PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL));
47199566063dSJacob Faibussowitsch       PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL));
47209566063dSJacob Faibussowitsch       PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute));
47219566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL));
47229566063dSJacob Faibussowitsch       PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness));
47239371c9d4SSatish Balay     } break;
47249371c9d4SSatish Balay     case DM_SHAPE_DOUBLET: {
472505bd46c0SStefano Zampini       DM        dmnew;
472605bd46c0SStefano Zampini       PetscReal rl = 0.0;
472705bd46c0SStefano Zampini 
472805bd46c0SStefano Zampini       PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL));
472905bd46c0SStefano Zampini       PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew));
47305de52c6dSVaclav Hapla       PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew));
473169d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &dmnew));
47329371c9d4SSatish Balay     } break;
4733cfb853baSMatthew G. Knepley     case DM_SHAPE_HYPERCUBIC: {
47348d2ec52aSSatish Balay       PetscInt       *edges, overlap = 1;
4735cfb853baSMatthew G. Knepley       PetscReal      *lower, *upper;
4736cfb853baSMatthew G. Knepley       DMBoundaryType *bdt;
4737cfb853baSMatthew G. Knepley       PetscInt        n, d;
4738cfb853baSMatthew G. Knepley 
4739cfb853baSMatthew G. Knepley       *useCoordSpace = PETSC_FALSE;
4740cfb853baSMatthew G. Knepley       PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt));
4741cfb853baSMatthew G. Knepley       for (d = 0; d < dim; ++d) {
4742cfb853baSMatthew G. Knepley         edges[d] = 1;
4743cfb853baSMatthew G. Knepley         lower[d] = 0.;
4744cfb853baSMatthew G. Knepley         upper[d] = 1.;
4745cfb853baSMatthew G. Knepley         bdt[d]   = DM_BOUNDARY_PERIODIC;
4746cfb853baSMatthew G. Knepley       }
4747cfb853baSMatthew G. Knepley       n = dim;
4748cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg));
4749cfb853baSMatthew G. Knepley       n = dim;
4750cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg));
4751cfb853baSMatthew 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);
4752cfb853baSMatthew G. Knepley       n = dim;
4753cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg));
4754cfb853baSMatthew 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);
4755cfb853baSMatthew G. Knepley       n = dim;
4756cfb853baSMatthew G. Knepley       PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
4757cfb853baSMatthew 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);
47588d2ec52aSSatish Balay       PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", overlap, &overlap, NULL, 0));
47598d2ec52aSSatish Balay       PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, overlap, bdt));
4760cfb853baSMatthew G. Knepley       PetscCall(PetscFree4(edges, lower, upper, bdt));
4761cfb853baSMatthew G. Knepley     } break;
4762d71ae5a4SJacob Faibussowitsch     default:
4763d71ae5a4SJacob Faibussowitsch       SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]);
47649318fe57SMatthew G. Knepley     }
47659318fe57SMatthew G. Knepley   }
47669566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
476748a46eb9SPierre Jolivet   if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname));
4768b9da1bb3SMatthew G. Knepley   if (orient) PetscCall(DMPlexOrient(dm));
47694e22dd4cSMatthew G. Knepley   // Allow label creation
47704e22dd4cSMatthew G. Knepley   PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_label_", &option, NULL, &flg));
47714e22dd4cSMatthew G. Knepley   if (flg) {
47724e22dd4cSMatthew G. Knepley     DMLabel     label;
47734e22dd4cSMatthew G. Knepley     PetscInt    points[1024], n = 1024;
47744e22dd4cSMatthew G. Knepley     char        fulloption[PETSC_MAX_PATH_LEN];
47754e22dd4cSMatthew G. Knepley     const char *name = &option[14];
47764e22dd4cSMatthew G. Knepley 
47774e22dd4cSMatthew G. Knepley     PetscCall(DMCreateLabel(dm, name));
47784e22dd4cSMatthew G. Knepley     PetscCall(DMGetLabel(dm, name, &label));
47794e22dd4cSMatthew G. Knepley     fulloption[0] = '-';
47804e22dd4cSMatthew G. Knepley     fulloption[1] = 0;
47814e22dd4cSMatthew G. Knepley     PetscCall(PetscStrlcat(fulloption, option, PETSC_MAX_PATH_LEN));
47824e22dd4cSMatthew G. Knepley     PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, NULL));
47834e22dd4cSMatthew G. Knepley     for (PetscInt p = 0; p < n; ++p) PetscCall(DMLabelSetValue(label, points[p], 1));
47844e22dd4cSMatthew G. Knepley   }
4785dd0eeac9SMatthew G. Knepley   // Allow cohesive label creation
4786dd0eeac9SMatthew G. Knepley   //   Faces are input, completed, and all points are marked with their depth
4787dd0eeac9SMatthew G. Knepley   PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_cohesive_label_", &option, NULL, &flg));
4788dd0eeac9SMatthew G. Knepley   if (flg) {
4789dd0eeac9SMatthew G. Knepley     DMLabel   label;
4790dd0eeac9SMatthew G. Knepley     PetscInt  points[1024], n, pStart, pEnd, Nl = 1;
47915390be7dSMatthew G. Knepley     PetscBool noCreate = PETSC_FALSE;
4792dd0eeac9SMatthew G. Knepley     char      fulloption[PETSC_MAX_PATH_LEN];
4793dd0eeac9SMatthew G. Knepley     char      name[PETSC_MAX_PATH_LEN];
4794dd0eeac9SMatthew G. Knepley     size_t    len;
4795dd0eeac9SMatthew G. Knepley 
4796dd0eeac9SMatthew G. Knepley     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
4797dd0eeac9SMatthew G. Knepley     PetscCall(PetscStrncpy(name, &option[23], PETSC_MAX_PATH_LEN));
4798dd0eeac9SMatthew G. Knepley     PetscCall(PetscStrlen(name, &len));
4799dd0eeac9SMatthew G. Knepley     if (name[len - 1] == '0') Nl = 10;
4800dd0eeac9SMatthew G. Knepley     for (PetscInt l = 0; l < Nl; ++l) {
48016497c311SBarry Smith       if (l > 0) name[len - 1] = (char)('0' + l);
4802dd0eeac9SMatthew G. Knepley       fulloption[0] = 0;
4803dd0eeac9SMatthew G. Knepley       PetscCall(PetscStrlcat(fulloption, "-dm_plex_cohesive_label_", 32));
4804dd0eeac9SMatthew G. Knepley       PetscCall(PetscStrlcat(fulloption, name, PETSC_MAX_PATH_LEN - 32));
4805dd0eeac9SMatthew G. Knepley       n = 1024;
4806dd0eeac9SMatthew G. Knepley       PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, &flg));
4807dd0eeac9SMatthew G. Knepley       if (!flg) break;
48085390be7dSMatthew G. Knepley       PetscCall(DMHasLabel(dm, name, &noCreate));
48095390be7dSMatthew G. Knepley       if (noCreate) {
48105390be7dSMatthew G. Knepley         DMLabel         inlabel;
48115390be7dSMatthew G. Knepley         IS              pointIS;
48125390be7dSMatthew G. Knepley         const PetscInt *lpoints;
48135390be7dSMatthew G. Knepley         PetscInt        pdep, ln, inval = points[0];
48145390be7dSMatthew G. Knepley         char            newname[PETSC_MAX_PATH_LEN];
48155390be7dSMatthew G. Knepley 
48165390be7dSMatthew G. Knepley         PetscCheck(n == 1, comm, PETSC_ERR_ARG_WRONG, "Must specify a label value with this option");
48175390be7dSMatthew G. Knepley         PetscCall(DMGetLabel(dm, name, &inlabel));
48185390be7dSMatthew G. Knepley         PetscCall(DMLabelGetStratumIS(inlabel, inval, &pointIS));
48195390be7dSMatthew G. Knepley         PetscCall(ISGetLocalSize(pointIS, &ln));
48205390be7dSMatthew G. Knepley         PetscCall(ISGetIndices(pointIS, &lpoints));
48215390be7dSMatthew G. Knepley         PetscCall(DMPlexGetPointDepth(dm, lpoints[0], &pdep));
48225390be7dSMatthew G. Knepley         PetscCall(PetscSNPrintf(newname, PETSC_MAX_PATH_LEN, "%s%" PetscInt_FMT, name, points[0]));
48235390be7dSMatthew G. Knepley         PetscCall(DMCreateLabel(dm, newname));
48245390be7dSMatthew G. Knepley         PetscCall(DMGetLabel(dm, newname, &label));
48255390be7dSMatthew G. Knepley         if (!pdep) PetscCall(ProcessCohesiveLabel_Vertices(dm, label, inlabel, inval, ln, lpoints));
48265390be7dSMatthew G. Knepley         else PetscCall(ProcessCohesiveLabel_Faces(dm, label, ln, lpoints));
48275390be7dSMatthew G. Knepley         PetscCall(ISRestoreIndices(pointIS, &lpoints));
48285390be7dSMatthew G. Knepley         PetscCall(ISDestroy(&pointIS));
48295390be7dSMatthew G. Knepley       } else {
4830dd0eeac9SMatthew G. Knepley         PetscCall(DMCreateLabel(dm, name));
4831dd0eeac9SMatthew G. Knepley         PetscCall(DMGetLabel(dm, name, &label));
4832dd0eeac9SMatthew G. Knepley         if (pStart >= pEnd) n = 0;
48335390be7dSMatthew G. Knepley         PetscCall(ProcessCohesiveLabel_Faces(dm, label, n, points));
4834dd0eeac9SMatthew G. Knepley       }
4835dd0eeac9SMatthew G. Knepley       PetscCall(DMPlexOrientLabel(dm, label));
48360542aa8cSMatthew G. Knepley       PetscCall(DMPlexLabelCohesiveComplete(dm, label, NULL, 1, PETSC_FALSE, PETSC_FALSE, NULL));
4837dd0eeac9SMatthew G. Knepley     }
4838dd0eeac9SMatthew G. Knepley   }
48395390be7dSMatthew G. Knepley   PetscCall(DMViewFromOptions(dm, NULL, "-created_dm_view"));
4840708be2fdSJed Brown   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromOptions, dm, 0, 0, 0));
48413ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48420a6ba040SMatthew G. Knepley }
48430a6ba040SMatthew G. Knepley 
4844d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
4845d71ae5a4SJacob Faibussowitsch {
48460a6ba040SMatthew G. Knepley   DM_Plex  *mesh = (DM_Plex *)dm->data;
48477f9d8d6cSVaclav Hapla   PetscBool flg, flg2;
48489318fe57SMatthew G. Knepley   char      bdLabel[PETSC_MAX_PATH_LEN];
4849adc21957SMatthew G. Knepley   char      method[PETSC_MAX_PATH_LEN];
48500a6ba040SMatthew G. Knepley 
48510a6ba040SMatthew G. Knepley   PetscFunctionBegin;
48520a6ba040SMatthew G. Knepley   /* Handle viewing */
48539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL));
48545962854dSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level for all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0));
48555962854dSMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fvm", "Debug output level for all fvm computations", "DMPlexSNESComputeResidualFVM", 0, &mesh->printFVM, NULL, 0));
48569566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL));
48579566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0));
4858f5867de0SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0));
4859a77a5016SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_plex_print_project", "Debug output level all projection computations", "DMPlexProject", 0, &mesh->printProject, NULL, 0));
48609566063dSJacob Faibussowitsch   PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg));
48619566063dSJacob Faibussowitsch   if (flg) PetscCall(PetscLogDefaultBegin());
48625e2c5519SMatthew G. Knepley   // Interpolation
48635e2c5519SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_plex_interpolate_prefer_tensor", "When different orderings exist, prefer the tensor order", "DMPlexSetInterpolationPreferTensor", mesh->interpolatePreferTensor, &mesh->interpolatePreferTensor, NULL));
48649318fe57SMatthew G. Knepley   /* Labeling */
48659566063dSJacob Faibussowitsch   PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg));
48669566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel));
4867953fc75cSMatthew G. Knepley   /* Point Location */
48689566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL));
48690848f4b5SMatthew G. Knepley   /* Partitioning and distribution */
48709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL));
4871d02c7345SMatthew G. Knepley   /* Reordering */
4872adc21957SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_reorder_section", "Compute point permutation for local section", "DMReorderSectionSetDefault", PETSC_FALSE, &flg2, &flg));
4873adc21957SMatthew G. Knepley   if (flg) PetscCall(DMReorderSectionSetDefault(dm, flg2 ? DM_REORDER_DEFAULT_TRUE : DM_REORDER_DEFAULT_FALSE));
4874adc21957SMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_reorder_section_type", "Reordering method for local section", "DMReorderSectionSetType", method, method, PETSC_MAX_PATH_LEN, &flg));
4875adc21957SMatthew G. Knepley   if (flg) PetscCall(DMReorderSectionSetType(dm, method));
48762e62ab5aSMatthew G. Knepley   /* Generation and remeshing */
48779566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL));
4878b29cfa1cSToby Isaac   /* Projection behavior */
4879d5b43468SJose E. Roman   PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0));
48809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL));
4881f12cf164SMatthew G. Knepley   /* Checking structure */
4882f12cf164SMatthew G. Knepley   {
48837f9d8d6cSVaclav Hapla     PetscBool all = PETSC_FALSE;
4884f12cf164SMatthew G. Knepley 
48857f9d8d6cSVaclav Hapla     PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL));
48867f9d8d6cSVaclav Hapla     if (all) {
48877f9d8d6cSVaclav Hapla       PetscCall(DMPlexCheck(dm));
48887f9d8d6cSVaclav Hapla     } else {
48899566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2));
48907f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm));
48919566063dSJacob 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));
48927f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0));
48939566063dSJacob 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));
48947f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0));
48959566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2));
48967f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm));
48979566063dSJacob Faibussowitsch       PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2));
4898d7d32a9aSMatthew G. Knepley       if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE));
48999566063dSJacob 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));
49007f9d8d6cSVaclav Hapla       if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm));
49017f9d8d6cSVaclav Hapla     }
49029566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2));
49039566063dSJacob Faibussowitsch     if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE));
4904f12cf164SMatthew G. Knepley   }
49059318fe57SMatthew G. Knepley   {
49069318fe57SMatthew G. Knepley     PetscReal scale = 1.0;
49074f3833eaSMatthew G. Knepley 
49089566063dSJacob Faibussowitsch     PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg));
49099318fe57SMatthew G. Knepley     if (flg) {
49109318fe57SMatthew G. Knepley       Vec coordinates, coordinatesLocal;
49119318fe57SMatthew G. Knepley 
49129566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinates(dm, &coordinates));
49139566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal));
49149566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinates, scale));
49159566063dSJacob Faibussowitsch       PetscCall(VecScale(coordinatesLocal, scale));
49169318fe57SMatthew G. Knepley     }
49179318fe57SMatthew G. Knepley   }
49189566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner));
49193ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
492068d4fef7SMatthew G. Knepley }
492168d4fef7SMatthew G. Knepley 
4922d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap)
4923d71ae5a4SJacob Faibussowitsch {
4924c506a872SMatthew G. Knepley   PetscInt  numOvLabels = 16, numOvExLabels = 16;
4925c506a872SMatthew G. Knepley   char     *ovLabelNames[16], *ovExLabelNames[16];
4926c506a872SMatthew G. Knepley   PetscInt  numOvValues = 16, numOvExValues = 16, l;
4927c506a872SMatthew G. Knepley   PetscBool flg;
4928c506a872SMatthew G. Knepley 
4929c506a872SMatthew G. Knepley   PetscFunctionBegin;
4930c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0));
4931c506a872SMatthew G. Knepley   PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg));
4932c506a872SMatthew G. Knepley   if (!flg) numOvLabels = 0;
4933c506a872SMatthew G. Knepley   if (numOvLabels) {
4934c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvLabels = numOvLabels;
4935c506a872SMatthew G. Knepley     for (l = 0; l < numOvLabels; ++l) {
4936c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l]));
4937c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]);
4938c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovLabelNames[l]));
4939c506a872SMatthew G. Knepley     }
4940c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg));
4941c506a872SMatthew G. Knepley     if (!flg) numOvValues = 0;
4942c506a872SMatthew 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);
4943c506a872SMatthew G. Knepley 
4944c506a872SMatthew G. Knepley     PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg));
4945c506a872SMatthew G. Knepley     if (!flg) numOvExLabels = 0;
4946c506a872SMatthew G. Knepley     ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels;
4947c506a872SMatthew G. Knepley     for (l = 0; l < numOvExLabels; ++l) {
4948c506a872SMatthew G. Knepley       PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l]));
4949c506a872SMatthew G. Knepley       PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]);
4950c506a872SMatthew G. Knepley       PetscCall(PetscFree(ovExLabelNames[l]));
4951c506a872SMatthew G. Knepley     }
4952c506a872SMatthew G. Knepley     PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg));
4953c506a872SMatthew G. Knepley     if (!flg) numOvExValues = 0;
4954c506a872SMatthew 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);
4955c506a872SMatthew G. Knepley   }
49563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4957c506a872SMatthew G. Knepley }
4958c506a872SMatthew G. Knepley 
4959d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject)
4960d71ae5a4SJacob Faibussowitsch {
4961bdf63967SMatthew G. Knepley   PetscFunctionList    ordlist;
4962bdf63967SMatthew G. Knepley   char                 oname[256];
49634e22dd4cSMatthew G. Knepley   char                 sublabelname[PETSC_MAX_PATH_LEN] = "";
4964adc21957SMatthew G. Knepley   DMReorderDefaultFlag reorder;
4965d410b0cfSMatthew G. Knepley   PetscReal            volume    = -1.0;
49669318fe57SMatthew G. Knepley   PetscInt             prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim;
49671b742f01SMatthew 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;
496868d4fef7SMatthew G. Knepley 
496968d4fef7SMatthew G. Knepley   PetscFunctionBegin;
4970d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options");
4971dd4c3f67SMatthew G. Knepley   if (dm->cloneOpts) goto non_refine;
49729318fe57SMatthew G. Knepley   /* Handle automatic creation */
49739566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
49746bc1bd01Sksagiyam   if (dim < 0) {
49756bc1bd01Sksagiyam     PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm));
49766bc1bd01Sksagiyam     created = PETSC_TRUE;
49776bc1bd01Sksagiyam   }
49786bc1bd01Sksagiyam   PetscCall(DMGetDimension(dm, &dim));
4979d89e6e46SMatthew G. Knepley   /* Handle interpolation before distribution */
49809566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg));
4981d89e6e46SMatthew G. Knepley   if (flg) {
4982d89e6e46SMatthew G. Knepley     DMPlexInterpolatedFlag interpolated;
4983d89e6e46SMatthew G. Knepley 
49849566063dSJacob Faibussowitsch     PetscCall(DMPlexIsInterpolated(dm, &interpolated));
4985d89e6e46SMatthew G. Knepley     if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) {
4986d89e6e46SMatthew G. Knepley       DM udm;
4987d89e6e46SMatthew G. Knepley 
49889566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(dm, &udm));
498969d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &udm));
4990d89e6e46SMatthew G. Knepley     } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) {
4991d89e6e46SMatthew G. Knepley       DM idm;
4992d89e6e46SMatthew G. Knepley 
49939566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(dm, &idm));
499469d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &idm));
4995d89e6e46SMatthew G. Knepley     }
4996d89e6e46SMatthew G. Knepley   }
49974e22dd4cSMatthew G. Knepley   // Handle submesh selection before distribution
49984e22dd4cSMatthew G. Knepley   PetscCall(PetscOptionsString("-dm_plex_submesh", "Label to use for submesh selection", "", sublabelname, sublabelname, PETSC_MAX_PATH_LEN, &flg));
49994e22dd4cSMatthew G. Knepley   if (flg) {
50004e22dd4cSMatthew G. Knepley     DM              subdm;
50014e22dd4cSMatthew G. Knepley     DMLabel         label;
50024e22dd4cSMatthew G. Knepley     IS              valueIS, pointIS;
50034e22dd4cSMatthew G. Knepley     const PetscInt *values, *points;
50044e22dd4cSMatthew G. Knepley     PetscBool       markedFaces = PETSC_FALSE;
50054e22dd4cSMatthew G. Knepley     PetscInt        Nv, value, Np;
50064e22dd4cSMatthew G. Knepley 
50074e22dd4cSMatthew G. Knepley     PetscCall(DMGetLabel(dm, sublabelname, &label));
50084e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetNumValues(label, &Nv));
50094e22dd4cSMatthew 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);
50104e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetValueIS(label, &valueIS));
50114e22dd4cSMatthew G. Knepley     PetscCall(ISGetIndices(valueIS, &values));
50124e22dd4cSMatthew G. Knepley     value = values[0];
50134e22dd4cSMatthew G. Knepley     PetscCall(ISRestoreIndices(valueIS, &values));
50144e22dd4cSMatthew G. Knepley     PetscCall(ISDestroy(&valueIS));
50154e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetStratumSize(label, value, &Np));
50164e22dd4cSMatthew G. Knepley     PetscCall(DMLabelGetStratumIS(label, value, &pointIS));
50174e22dd4cSMatthew G. Knepley     PetscCall(ISGetIndices(pointIS, &points));
50184e22dd4cSMatthew G. Knepley     for (PetscInt p = 0; p < Np; ++p) {
50194e22dd4cSMatthew G. Knepley       PetscInt pdepth;
50204e22dd4cSMatthew G. Knepley 
50214e22dd4cSMatthew G. Knepley       PetscCall(DMPlexGetPointDepth(dm, points[p], &pdepth));
50224e22dd4cSMatthew G. Knepley       if (pdepth) {
50234e22dd4cSMatthew G. Knepley         markedFaces = PETSC_TRUE;
50244e22dd4cSMatthew G. Knepley         break;
50254e22dd4cSMatthew G. Knepley       }
50264e22dd4cSMatthew G. Knepley     }
50274e22dd4cSMatthew G. Knepley     PetscCall(ISRestoreIndices(pointIS, &points));
50284e22dd4cSMatthew G. Knepley     PetscCall(ISDestroy(&pointIS));
50294e22dd4cSMatthew G. Knepley     PetscCall(DMPlexCreateSubmesh(dm, label, value, markedFaces, &subdm));
50304e22dd4cSMatthew G. Knepley     PetscCall(DMPlexReplace_Internal(dm, &subdm));
50314e22dd4cSMatthew G. Knepley     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
50324e22dd4cSMatthew G. Knepley   }
50339b44eab4SMatthew G. Knepley   /* Handle DMPlex refinement before distribution */
50349566063dSJacob Faibussowitsch   PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig));
50359566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0));
50369566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
50379566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg));
50389566063dSJacob Faibussowitsch   if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform));
50399566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg));
50409318fe57SMatthew G. Knepley   if (flg) {
50419566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE));
50429566063dSJacob Faibussowitsch     PetscCall(DMPlexSetRefinementLimit(dm, volume));
50439318fe57SMatthew G. Knepley     prerefine = PetscMax(prerefine, 1);
50449318fe57SMatthew G. Knepley   }
5045b23db253SStefano Zampini   if (prerefine) PetscCall(DMLocalizeCoordinates(dm));
50469b44eab4SMatthew G. Knepley   for (r = 0; r < prerefine; ++r) {
50479b44eab4SMatthew G. Knepley     DM             rdm;
50489b44eab4SMatthew G. Knepley     PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
50499b44eab4SMatthew G. Knepley 
5050dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
50519566063dSJacob Faibussowitsch     PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
505269d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &rdm));
5053dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
505461a622f3SMatthew G. Knepley     if (coordFunc && remap) {
50559566063dSJacob Faibussowitsch       PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
50569b44eab4SMatthew G. Knepley       ((DM_Plex *)dm->data)->coordFunc = coordFunc;
50579b44eab4SMatthew G. Knepley     }
50589b44eab4SMatthew G. Knepley   }
50599566063dSJacob Faibussowitsch   PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig));
50609318fe57SMatthew G. Knepley   /* Handle DMPlex extrusion before distribution */
50619566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0));
50629318fe57SMatthew G. Knepley   if (extLayers) {
50639318fe57SMatthew G. Knepley     DM edm;
50649318fe57SMatthew G. Knepley 
50659566063dSJacob Faibussowitsch     PetscCall(DMExtrude(dm, extLayers, &edm));
506669d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &edm));
506748d16a33SMatthew G. Knepley     ((DM_Plex *)dm->data)->coordFunc = NULL;
5068dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
5069d410b0cfSMatthew G. Knepley     extLayers = 0;
50705e17fc22SAidan Hamilton     PetscCall(DMGetDimension(dm, &dim));
50719318fe57SMatthew G. Knepley   }
5072bdf63967SMatthew G. Knepley   /* Handle DMPlex reordering before distribution */
50736bc1bd01Sksagiyam   PetscCall(DMPlexReorderGetDefault(dm, &reorder));
50749566063dSJacob Faibussowitsch   PetscCall(MatGetOrderingList(&ordlist));
50756bc1bd01Sksagiyam   PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname)));
50769566063dSJacob Faibussowitsch   PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg));
5077adc21957SMatthew G. Knepley   if (reorder == DM_REORDER_DEFAULT_TRUE || flg) {
5078bdf63967SMatthew G. Knepley     DM pdm;
5079bdf63967SMatthew G. Knepley     IS perm;
5080bdf63967SMatthew G. Knepley 
50819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm));
50829566063dSJacob Faibussowitsch     PetscCall(DMPlexPermute(dm, perm, &pdm));
50839566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&perm));
508469d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &pdm));
5085dbbe0bcdSBarry Smith     PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
5086bdf63967SMatthew G. Knepley   }
50879b44eab4SMatthew G. Knepley   /* Handle DMPlex distribution */
50889566063dSJacob Faibussowitsch   PetscCall(DMPlexDistributeGetDefault(dm, &distribute));
5089c506a872SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL));
5090a286e215SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_distribute_save_sf", "Flag to save the migration SF", "DMPlexSetMigrationSF", saveSF, &saveSF, NULL));
5091dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap));
50929b44eab4SMatthew G. Knepley   if (distribute) {
50939b44eab4SMatthew G. Knepley     DM               pdm = NULL;
50949b44eab4SMatthew G. Knepley     PetscPartitioner part;
5095a286e215SMatthew G. Knepley     PetscSF          sfMigration;
50969b44eab4SMatthew G. Knepley 
50979566063dSJacob Faibussowitsch     PetscCall(DMPlexGetPartitioner(dm, &part));
50989566063dSJacob Faibussowitsch     PetscCall(PetscPartitionerSetFromOptions(part));
5099a286e215SMatthew G. Knepley     PetscCall(DMPlexDistribute(dm, overlap, &sfMigration, &pdm));
51005d2873a6SJames Wright     if (pdm) {
51015d2873a6SJames Wright       // Delete the local section to force the existing one to be rebuilt with the distributed DM
51025d2873a6SJames Wright       PetscCall(DMSetLocalSection(dm, pdm->localSection));
51035d2873a6SJames Wright       PetscCall(DMPlexReplace_Internal(dm, &pdm));
51045d2873a6SJames Wright     }
5105a286e215SMatthew G. Knepley     if (saveSF) PetscCall(DMPlexSetMigrationSF(dm, sfMigration));
5106a286e215SMatthew G. Knepley     PetscCall(PetscSFDestroy(&sfMigration));
51079b44eab4SMatthew G. Knepley   }
51084054ae39SJames Wright 
51094054ae39SJames Wright   {
51104054ae39SJames Wright     PetscBool useBoxLabel = PETSC_FALSE;
51114054ae39SJames Wright     PetscCall(PetscOptionsBool("-dm_plex_box_label", "Create 'Face Sets' assuming boundary faces align with cartesian directions", "DMCreate", useBoxLabel, &useBoxLabel, NULL));
5112d7d2d1d2SJames Wright     if (useBoxLabel) {
5113d7d2d1d2SJames Wright       PetscInt       n      = 3;
5114d7d2d1d2SJames Wright       DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE};
5115d7d2d1d2SJames Wright 
5116d7d2d1d2SJames Wright       PetscCall(PetscOptionsEnumArray("-dm_plex_box_label_bd", "Boundary type for each dimension when using -dm_plex_box_label", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg));
5117d7d2d1d2SJames 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);
5118d7d2d1d2SJames Wright       PetscCall(DMPlexSetBoxLabel_Internal(dm, bdt));
5119d7d2d1d2SJames Wright     }
51204054ae39SJames Wright   }
5121d2b2dc1eSMatthew G. Knepley   /* Must check CEED options before creating function space for coordinates */
5122d2b2dc1eSMatthew G. Knepley   {
5123d2b2dc1eSMatthew G. Knepley     PetscBool useCeed = PETSC_FALSE, flg;
5124d2b2dc1eSMatthew G. Knepley 
5125d2b2dc1eSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_plex_use_ceed", "Use LibCEED as the FEM backend", "DMPlexSetUseCeed", useCeed, &useCeed, &flg));
5126d2b2dc1eSMatthew G. Knepley     if (flg) PetscCall(DMPlexSetUseCeed(dm, useCeed));
5127d2b2dc1eSMatthew G. Knepley   }
51289318fe57SMatthew G. Knepley   /* Create coordinate space */
51299318fe57SMatthew G. Knepley   if (created) {
513061a622f3SMatthew G. Knepley     DM_Plex  *mesh   = (DM_Plex *)dm->data;
5131e44f6aebSMatthew G. Knepley     PetscInt  degree = 1, deg;
51325515ebd3SMatthew G. Knepley     PetscInt  height = 0;
51335515ebd3SMatthew G. Knepley     DM        cdm;
5134c3db174cSMatthew G. Knepley     PetscBool flg, localize = PETSC_TRUE, sparseLocalize = PETSC_TRUE;
51359318fe57SMatthew G. Knepley 
51369566063dSJacob Faibussowitsch     PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg));
51379566063dSJacob Faibussowitsch     PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, &degree, NULL));
5138e44f6aebSMatthew G. Knepley     PetscCall(DMGetCoordinateDegree_Internal(dm, &deg));
5139e44f6aebSMatthew G. Knepley     if (coordSpace && deg <= 1) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_TRUE, mesh->coordFunc));
51405515ebd3SMatthew G. Knepley     PetscCall(DMGetCoordinateDM(dm, &cdm));
514161a622f3SMatthew G. Knepley     if (flg && !coordSpace) {
514261a622f3SMatthew G. Knepley       PetscDS      cds;
514361a622f3SMatthew G. Knepley       PetscObject  obj;
514461a622f3SMatthew G. Knepley       PetscClassId id;
514561a622f3SMatthew G. Knepley 
51469566063dSJacob Faibussowitsch       PetscCall(DMGetDS(cdm, &cds));
51479566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
51489566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
514961a622f3SMatthew G. Knepley       if (id == PETSCFE_CLASSID) {
515061a622f3SMatthew G. Knepley         PetscContainer dummy;
515161a622f3SMatthew G. Knepley 
51529566063dSJacob Faibussowitsch         PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy));
51539566063dSJacob Faibussowitsch         PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates"));
51549566063dSJacob Faibussowitsch         PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy));
51559566063dSJacob Faibussowitsch         PetscCall(PetscContainerDestroy(&dummy));
51569566063dSJacob Faibussowitsch         PetscCall(DMClearDS(cdm));
515761a622f3SMatthew G. Knepley       }
515861a622f3SMatthew G. Knepley       mesh->coordFunc = NULL;
515961a622f3SMatthew G. Knepley     }
5160c3db174cSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_localize", "Localize mesh coordinates", "", localize, &localize, NULL));
5161c3db174cSMatthew G. Knepley     PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "DMSetSparseLocalize", sparseLocalize, &sparseLocalize, &flg));
5162c3db174cSMatthew G. Knepley     if (flg) PetscCall(DMSetSparseLocalize(dm, sparseLocalize));
51635515ebd3SMatthew G. Knepley     PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg));
51645515ebd3SMatthew G. Knepley     if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height));
5165c3db174cSMatthew G. Knepley     if (localize) PetscCall(DMLocalizeCoordinates(dm));
51669318fe57SMatthew G. Knepley   }
516768d4fef7SMatthew G. Knepley   /* Handle DMPlex refinement */
516861a622f3SMatthew G. Knepley   remap = PETSC_TRUE;
51699566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0));
51709566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL));
51719566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0));
51729566063dSJacob Faibussowitsch   if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE));
517368d4fef7SMatthew G. Knepley   if (refine && isHierarchy) {
5174acdc6f61SToby Isaac     DM *dms, coarseDM;
517568d4fef7SMatthew G. Knepley 
51769566063dSJacob Faibussowitsch     PetscCall(DMGetCoarseDM(dm, &coarseDM));
51779566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)coarseDM));
51789566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(refine, &dms));
51799566063dSJacob Faibussowitsch     PetscCall(DMRefineHierarchy(dm, refine, dms));
518068d4fef7SMatthew G. Knepley     /* Total hack since we do not pass in a pointer */
51819566063dSJacob Faibussowitsch     PetscCall(DMPlexSwap_Static(dm, dms[refine - 1]));
518268d4fef7SMatthew G. Knepley     if (refine == 1) {
51839566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[0]));
51849566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
518568d4fef7SMatthew G. Knepley     } else {
51869566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dm, dms[refine - 2]));
51879566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE));
51889566063dSJacob Faibussowitsch       PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1]));
51899566063dSJacob Faibussowitsch       PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE));
519068d4fef7SMatthew G. Knepley     }
51919566063dSJacob Faibussowitsch     PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM));
51929566063dSJacob Faibussowitsch     PetscCall(PetscObjectDereference((PetscObject)coarseDM));
519368d4fef7SMatthew G. Knepley     /* Free DMs */
519468d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
5195dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
51969566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
519768d4fef7SMatthew G. Knepley     }
51989566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
519968d4fef7SMatthew G. Knepley   } else {
520068d4fef7SMatthew G. Knepley     for (r = 0; r < refine; ++r) {
52019318fe57SMatthew G. Knepley       DM             rdm;
520251a74b61SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
520368d4fef7SMatthew G. Knepley 
5204dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
52059566063dSJacob Faibussowitsch       PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm));
520668d4fef7SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
520769d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
5208dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
520961a622f3SMatthew G. Knepley       if (coordFunc && remap) {
52109566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
521151a74b61SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
521251a74b61SMatthew G. Knepley       }
521368d4fef7SMatthew G. Knepley     }
521468d4fef7SMatthew G. Knepley   }
52153cf6fe12SMatthew G. Knepley   /* Handle DMPlex coarsening */
52169566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0));
52179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0));
5218b653a561SMatthew G. Knepley   if (coarsen && isHierarchy) {
5219b653a561SMatthew G. Knepley     DM *dms;
5220b653a561SMatthew G. Knepley 
52219566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(coarsen, &dms));
52229566063dSJacob Faibussowitsch     PetscCall(DMCoarsenHierarchy(dm, coarsen, dms));
5223b653a561SMatthew G. Knepley     /* Free DMs */
5224b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
5225dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject));
52269566063dSJacob Faibussowitsch       PetscCall(DMDestroy(&dms[r]));
5227b653a561SMatthew G. Knepley     }
52289566063dSJacob Faibussowitsch     PetscCall(PetscFree(dms));
5229b653a561SMatthew G. Knepley   } else {
5230b653a561SMatthew G. Knepley     for (r = 0; r < coarsen; ++r) {
52319318fe57SMatthew G. Knepley       DM             cdm;
52329318fe57SMatthew G. Knepley       PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc;
52333cf6fe12SMatthew G. Knepley 
5234dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
52359566063dSJacob Faibussowitsch       PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm));
52363cf6fe12SMatthew G. Knepley       /* Total hack since we do not pass in a pointer */
523769d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &cdm));
5238dbbe0bcdSBarry Smith       PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
52399318fe57SMatthew G. Knepley       if (coordFunc) {
52409566063dSJacob Faibussowitsch         PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc));
52419318fe57SMatthew G. Knepley         ((DM_Plex *)dm->data)->coordFunc = coordFunc;
52429318fe57SMatthew G. Knepley       }
52433cf6fe12SMatthew G. Knepley     }
5244b653a561SMatthew G. Knepley   }
5245be664eb1SMatthew G. Knepley   // Handle coordinate remapping
5246be664eb1SMatthew G. Knepley   remap = PETSC_FALSE;
5247be664eb1SMatthew G. Knepley   PetscCall(PetscOptionsBool("-dm_coord_remap", "Flag to control coordinate remapping", "", remap, &remap, NULL));
5248be664eb1SMatthew G. Knepley   if (remap) {
5249be664eb1SMatthew G. Knepley     DMPlexCoordMap map     = DM_COORD_MAP_NONE;
5250be664eb1SMatthew G. Knepley     PetscPointFunc mapFunc = NULL;
5251be664eb1SMatthew G. Knepley     PetscScalar    params[16];
5252f45b553cSPierre Jolivet     PetscInt       Np = PETSC_STATIC_ARRAY_LENGTH(params), cdim;
5253be664eb1SMatthew G. Knepley     MPI_Comm       comm;
5254be664eb1SMatthew G. Knepley 
5255be664eb1SMatthew G. Knepley     PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
5256be664eb1SMatthew G. Knepley     PetscCall(DMGetCoordinateDim(dm, &cdim));
5257be664eb1SMatthew G. Knepley     PetscCall(PetscOptionsScalarArray("-dm_coord_map_params", "Parameters for the coordinate remapping", "", params, &Np, &flg));
5258be664eb1SMatthew G. Knepley     if (!flg) Np = 0;
5259be664eb1SMatthew G. Knepley     // TODO Allow user to pass a map function by name
5260be664eb1SMatthew G. Knepley     PetscCall(PetscOptionsEnum("-dm_coord_map", "Coordinate mapping for built-in mesh", "", DMPlexCoordMaps, (PetscEnum)map, (PetscEnum *)&map, &flg));
5261be664eb1SMatthew G. Knepley     if (flg) {
5262be664eb1SMatthew G. Knepley       switch (map) {
5263be664eb1SMatthew G. Knepley       case DM_COORD_MAP_NONE:
5264be664eb1SMatthew G. Knepley         mapFunc = coordMap_identity;
5265be664eb1SMatthew G. Knepley         break;
5266be664eb1SMatthew G. Knepley       case DM_COORD_MAP_SHEAR:
5267be664eb1SMatthew G. Knepley         mapFunc = coordMap_shear;
5268be664eb1SMatthew G. Knepley         if (!Np) {
5269be664eb1SMatthew G. Knepley           Np        = cdim + 1;
5270be664eb1SMatthew G. Knepley           params[0] = 0;
5271be664eb1SMatthew G. Knepley           for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0;
5272be664eb1SMatthew G. Knepley         }
5273be664eb1SMatthew 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);
5274be664eb1SMatthew G. Knepley         break;
5275be664eb1SMatthew G. Knepley       case DM_COORD_MAP_FLARE:
5276be664eb1SMatthew G. Knepley         mapFunc = coordMap_flare;
5277be664eb1SMatthew G. Knepley         if (!Np) {
5278be664eb1SMatthew G. Knepley           Np        = cdim + 1;
5279be664eb1SMatthew G. Knepley           params[0] = 0;
5280be664eb1SMatthew G. Knepley           for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0;
5281be664eb1SMatthew G. Knepley         }
5282be664eb1SMatthew 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);
5283be664eb1SMatthew G. Knepley         break;
5284be664eb1SMatthew G. Knepley       case DM_COORD_MAP_ANNULUS:
5285be664eb1SMatthew G. Knepley         mapFunc = coordMap_annulus;
5286be664eb1SMatthew G. Knepley         if (!Np) {
5287be664eb1SMatthew G. Knepley           Np        = 2;
5288be664eb1SMatthew G. Knepley           params[0] = 1.;
5289be664eb1SMatthew G. Knepley           params[1] = 2.;
5290be664eb1SMatthew G. Knepley         }
5291be664eb1SMatthew G. Knepley         PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The annulus coordinate map must have 2 parameters, not %" PetscInt_FMT, Np);
5292be664eb1SMatthew G. Knepley         break;
5293be664eb1SMatthew G. Knepley       case DM_COORD_MAP_SHELL:
5294be664eb1SMatthew G. Knepley         mapFunc = coordMap_shell;
5295be664eb1SMatthew G. Knepley         if (!Np) {
5296be664eb1SMatthew G. Knepley           Np        = 2;
5297be664eb1SMatthew G. Knepley           params[0] = 1.;
5298be664eb1SMatthew G. Knepley           params[1] = 2.;
5299be664eb1SMatthew G. Knepley         }
5300be664eb1SMatthew G. Knepley         PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The spherical shell coordinate map must have 2 parameters, not %" PetscInt_FMT, Np);
5301be664eb1SMatthew G. Knepley         break;
5302be664eb1SMatthew G. Knepley       default:
5303be664eb1SMatthew G. Knepley         mapFunc = coordMap_identity;
5304be664eb1SMatthew G. Knepley       }
5305be664eb1SMatthew G. Knepley     }
5306be664eb1SMatthew G. Knepley     if (Np) {
5307be664eb1SMatthew G. Knepley       DM      cdm;
5308be664eb1SMatthew G. Knepley       PetscDS cds;
5309be664eb1SMatthew G. Knepley 
5310be664eb1SMatthew G. Knepley       PetscCall(DMGetCoordinateDM(dm, &cdm));
5311be664eb1SMatthew G. Knepley       PetscCall(DMGetDS(cdm, &cds));
5312be664eb1SMatthew G. Knepley       PetscCall(PetscDSSetConstants(cds, Np, params));
5313be664eb1SMatthew G. Knepley     }
5314be664eb1SMatthew G. Knepley     PetscCall(DMPlexRemapGeometry(dm, 0.0, mapFunc));
5315be664eb1SMatthew G. Knepley   }
5316909dfd52SMatthew G. Knepley   /* Handle ghost cells */
53179566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL));
5318909dfd52SMatthew G. Knepley   if (ghostCells) {
5319909dfd52SMatthew G. Knepley     DM   gdm;
5320909dfd52SMatthew G. Knepley     char lname[PETSC_MAX_PATH_LEN];
5321909dfd52SMatthew G. Knepley 
5322909dfd52SMatthew G. Knepley     lname[0] = '\0';
53239566063dSJacob Faibussowitsch     PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg));
53249566063dSJacob Faibussowitsch     PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm));
532569d8a87bSksagiyam     PetscCall(DMPlexReplace_Internal(dm, &gdm));
5326909dfd52SMatthew G. Knepley   }
53276913077dSMatthew G. Knepley   /* Handle 1D order */
5328adc21957SMatthew G. Knepley   if (reorder != DM_REORDER_DEFAULT_FALSE && dim == 1) {
53296913077dSMatthew G. Knepley     DM           cdm, rdm;
53306913077dSMatthew G. Knepley     PetscDS      cds;
53316913077dSMatthew G. Knepley     PetscObject  obj;
53326913077dSMatthew G. Knepley     PetscClassId id = PETSC_OBJECT_CLASSID;
53336913077dSMatthew G. Knepley     IS           perm;
53346bc1bd01Sksagiyam     PetscInt     Nf;
53356913077dSMatthew G. Knepley     PetscBool    distributed;
53366913077dSMatthew G. Knepley 
53379566063dSJacob Faibussowitsch     PetscCall(DMPlexIsDistributed(dm, &distributed));
53389566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
53399566063dSJacob Faibussowitsch     PetscCall(DMGetDS(cdm, &cds));
53409566063dSJacob Faibussowitsch     PetscCall(PetscDSGetNumFields(cds, &Nf));
53416913077dSMatthew G. Knepley     if (Nf) {
53429566063dSJacob Faibussowitsch       PetscCall(PetscDSGetDiscretization(cds, 0, &obj));
53439566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetClassId(obj, &id));
53446913077dSMatthew G. Knepley     }
53456bc1bd01Sksagiyam     if (!distributed && id != PETSCFE_CLASSID) {
53469566063dSJacob Faibussowitsch       PetscCall(DMPlexGetOrdering1D(dm, &perm));
53479566063dSJacob Faibussowitsch       PetscCall(DMPlexPermute(dm, perm, &rdm));
534869d8a87bSksagiyam       PetscCall(DMPlexReplace_Internal(dm, &rdm));
53499566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&perm));
53506913077dSMatthew G. Knepley     }
53516913077dSMatthew G. Knepley   }
53523cf6fe12SMatthew G. Knepley /* Handle */
5353dd4c3f67SMatthew G. Knepley non_refine:
5354dbbe0bcdSBarry Smith   PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject));
535522d6dc08SStefano Zampini   char    *phases[16];
535622d6dc08SStefano Zampini   PetscInt Nphases = 16;
535722d6dc08SStefano Zampini   PetscCall(PetscOptionsStringArray("-dm_plex_option_phases", "Option phase prefixes", "DMSetFromOptions", phases, &Nphases, &flg));
5358d0609cedSBarry Smith   PetscOptionsHeadEnd();
535922d6dc08SStefano Zampini 
536022d6dc08SStefano Zampini   // Phases
536122d6dc08SStefano Zampini   if (flg) {
536222d6dc08SStefano Zampini     const char *oldPrefix;
536322d6dc08SStefano Zampini 
536422d6dc08SStefano Zampini     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &oldPrefix));
536522d6dc08SStefano Zampini     for (PetscInt ph = 0; ph < Nphases; ++ph) {
536622d6dc08SStefano Zampini       PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, phases[ph]));
536722d6dc08SStefano Zampini       PetscCall(PetscInfo(dm, "Options phase %s for DM %s\n", phases[ph], dm->hdr.name));
536822d6dc08SStefano Zampini       PetscCall(DMSetFromOptions(dm));
536922d6dc08SStefano Zampini       PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix));
537022d6dc08SStefano Zampini       PetscCall(PetscFree(phases[ph]));
537122d6dc08SStefano Zampini     }
537222d6dc08SStefano Zampini   }
53733ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
53740a6ba040SMatthew G. Knepley }
53750a6ba040SMatthew G. Knepley 
5376d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec)
5377d71ae5a4SJacob Faibussowitsch {
5378552f7358SJed Brown   PetscFunctionBegin;
53799566063dSJacob Faibussowitsch   PetscCall(DMCreateGlobalVector_Section_Private(dm, vec));
53809566063dSJacob Faibussowitsch   /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */
53819566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex));
53829566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native));
53839566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex));
53849566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native));
53853ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5386552f7358SJed Brown }
5387552f7358SJed Brown 
5388d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec)
5389d71ae5a4SJacob Faibussowitsch {
5390552f7358SJed Brown   PetscFunctionBegin;
53919566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector_Section_Private(dm, vec));
53929566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local));
53939566063dSJacob Faibussowitsch   PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local));
53943ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5395552f7358SJed Brown }
5396552f7358SJed Brown 
5397d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd)
5398d71ae5a4SJacob Faibussowitsch {
5399793f3fe5SMatthew G. Knepley   PetscInt depth, d;
5400793f3fe5SMatthew G. Knepley 
5401793f3fe5SMatthew G. Knepley   PetscFunctionBegin;
54029566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepth(dm, &depth));
5403793f3fe5SMatthew G. Knepley   if (depth == 1) {
54049566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &d));
54059566063dSJacob Faibussowitsch     if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
54069566063dSJacob Faibussowitsch     else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd));
54079371c9d4SSatish Balay     else {
54089371c9d4SSatish Balay       *pStart = 0;
54099371c9d4SSatish Balay       *pEnd   = 0;
54109371c9d4SSatish Balay     }
5411793f3fe5SMatthew G. Knepley   } else {
54129566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd));
5413793f3fe5SMatthew G. Knepley   }
54143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5415793f3fe5SMatthew G. Knepley }
5416793f3fe5SMatthew G. Knepley 
5417d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[])
5418d71ae5a4SJacob Faibussowitsch {
5419502a2867SDave May   PetscSF            sf;
54206497c311SBarry Smith   PetscMPIInt        niranks, njranks;
54216497c311SBarry Smith   PetscInt           n;
54220a19bb7dSprj-   const PetscMPIInt *iranks, *jranks;
54230a19bb7dSprj-   DM_Plex           *data = (DM_Plex *)dm->data;
5424502a2867SDave May 
54252f356facSMatthew G. Knepley   PetscFunctionBegin;
54269566063dSJacob Faibussowitsch   PetscCall(DMGetPointSF(dm, &sf));
54270a19bb7dSprj-   if (!data->neighbors) {
54289566063dSJacob Faibussowitsch     PetscCall(PetscSFSetUp(sf));
54299566063dSJacob Faibussowitsch     PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL));
54309566063dSJacob Faibussowitsch     PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL));
54319566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors));
54329566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks));
54339566063dSJacob Faibussowitsch     PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks));
54340a19bb7dSprj-     n = njranks + niranks;
54359566063dSJacob Faibussowitsch     PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1));
54360a19bb7dSprj-     /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */
54379566063dSJacob Faibussowitsch     PetscCall(PetscMPIIntCast(n, data->neighbors));
54380a19bb7dSprj-   }
54390a19bb7dSprj-   if (nranks) *nranks = data->neighbors[0];
54400a19bb7dSprj-   if (ranks) {
54410a19bb7dSprj-     if (data->neighbors[0]) *ranks = data->neighbors + 1;
54420a19bb7dSprj-     else *ranks = NULL;
54430a19bb7dSprj-   }
54443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5445502a2867SDave May }
5446502a2867SDave May 
54471eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec);
54481eb70e55SToby Isaac 
5449d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm)
5450d71ae5a4SJacob Faibussowitsch {
5451552f7358SJed Brown   PetscFunctionBegin;
5452552f7358SJed Brown   dm->ops->view                      = DMView_Plex;
54532c40f234SMatthew G. Knepley   dm->ops->load                      = DMLoad_Plex;
5454552f7358SJed Brown   dm->ops->setfromoptions            = DMSetFromOptions_Plex;
545538221697SMatthew G. Knepley   dm->ops->clone                     = DMClone_Plex;
5456552f7358SJed Brown   dm->ops->setup                     = DMSetUp_Plex;
54571bb6d2a8SBarry Smith   dm->ops->createlocalsection        = DMCreateLocalSection_Plex;
5458adc21957SMatthew G. Knepley   dm->ops->createsectionpermutation  = DMCreateSectionPermutation_Plex;
545966ad2231SToby Isaac   dm->ops->createdefaultconstraints  = DMCreateDefaultConstraints_Plex;
5460552f7358SJed Brown   dm->ops->createglobalvector        = DMCreateGlobalVector_Plex;
5461552f7358SJed Brown   dm->ops->createlocalvector         = DMCreateLocalVector_Plex;
5462184d77edSJed Brown   dm->ops->getlocaltoglobalmapping   = NULL;
54630298fd71SBarry Smith   dm->ops->createfieldis             = NULL;
5464552f7358SJed Brown   dm->ops->createcoordinatedm        = DMCreateCoordinateDM_Plex;
5465f19dbd58SToby Isaac   dm->ops->createcoordinatefield     = DMCreateCoordinateField_Plex;
54660a6ba040SMatthew G. Knepley   dm->ops->getcoloring               = NULL;
5467552f7358SJed Brown   dm->ops->creatematrix              = DMCreateMatrix_Plex;
5468bceba477SMatthew G. Knepley   dm->ops->createinterpolation       = DMCreateInterpolation_Plex;
5469bd041c0cSMatthew G. Knepley   dm->ops->createmassmatrix          = DMCreateMassMatrix_Plex;
5470b4937a87SMatthew G. Knepley   dm->ops->createmassmatrixlumped    = DMCreateMassMatrixLumped_Plex;
54715a84ad33SLisandro Dalcin   dm->ops->createinjection           = DMCreateInjection_Plex;
5472552f7358SJed Brown   dm->ops->refine                    = DMRefine_Plex;
54730a6ba040SMatthew G. Knepley   dm->ops->coarsen                   = DMCoarsen_Plex;
54740a6ba040SMatthew G. Knepley   dm->ops->refinehierarchy           = DMRefineHierarchy_Plex;
5475b653a561SMatthew G. Knepley   dm->ops->coarsenhierarchy          = DMCoarsenHierarchy_Plex;
5476d410b0cfSMatthew G. Knepley   dm->ops->extrude                   = DMExtrude_Plex;
54770298fd71SBarry Smith   dm->ops->globaltolocalbegin        = NULL;
54780298fd71SBarry Smith   dm->ops->globaltolocalend          = NULL;
54790298fd71SBarry Smith   dm->ops->localtoglobalbegin        = NULL;
54800298fd71SBarry Smith   dm->ops->localtoglobalend          = NULL;
5481552f7358SJed Brown   dm->ops->destroy                   = DMDestroy_Plex;
5482552f7358SJed Brown   dm->ops->createsubdm               = DMCreateSubDM_Plex;
54832adcc780SMatthew G. Knepley   dm->ops->createsuperdm             = DMCreateSuperDM_Plex;
5484793f3fe5SMatthew G. Knepley   dm->ops->getdimpoints              = DMGetDimPoints_Plex;
5485552f7358SJed Brown   dm->ops->locatepoints              = DMLocatePoints_Plex;
54860709b2feSToby Isaac   dm->ops->projectfunctionlocal      = DMProjectFunctionLocal_Plex;
54870709b2feSToby Isaac   dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex;
5488bfc4295aSToby Isaac   dm->ops->projectfieldlocal         = DMProjectFieldLocal_Plex;
54898c6c5593SMatthew G. Knepley   dm->ops->projectfieldlabellocal    = DMProjectFieldLabelLocal_Plex;
5490ece3a9fcSMatthew G. Knepley   dm->ops->projectbdfieldlabellocal  = DMProjectBdFieldLabelLocal_Plex;
54910709b2feSToby Isaac   dm->ops->computel2diff             = DMComputeL2Diff_Plex;
5492b698f381SToby Isaac   dm->ops->computel2gradientdiff     = DMComputeL2GradientDiff_Plex;
54932a16baeaSToby Isaac   dm->ops->computel2fielddiff        = DMComputeL2FieldDiff_Plex;
549428d58a37SPierre Jolivet   dm->ops->getneighbors              = DMGetNeighbors_Plex;
54956c6a6b79SMatthew G. Knepley   dm->ops->getlocalboundingbox       = DMGetLocalBoundingBox_Coordinates;
5496907a3e9cSStefano Zampini   dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_Plex;
5497907a3e9cSStefano Zampini   dm->ops->createddscatters          = DMCreateDomainDecompositionScatters_Plex;
54989566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex));
54996c51210dSStefano Zampini   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex));
55009566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex));
55019566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex));
55029566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex));
55039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex));
55046bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex));
55056bc1bd01Sksagiyam   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex));
5506adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", DMReorderSectionGetDefault_Plex));
5507adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", DMReorderSectionSetDefault_Plex));
5508adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", DMReorderSectionGetType_Plex));
5509adc21957SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", DMReorderSectionSetType_Plex));
55109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex));
5511c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex));
5512c506a872SMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex));
5513d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", DMPlexGetUseCeed_Plex));
5514d2b2dc1eSMatthew G. Knepley   PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", DMPlexSetUseCeed_Plex));
55153ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5516552f7358SJed Brown }
5517552f7358SJed Brown 
5518d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm)
5519d71ae5a4SJacob Faibussowitsch {
552063a16f15SMatthew G. Knepley   DM_Plex       *mesh = (DM_Plex *)dm->data;
55211fca310dSJames Wright   const PetscSF *face_sfs;
55221fca310dSJames Wright   PetscInt       num_face_sfs;
552363a16f15SMatthew G. Knepley 
552463a16f15SMatthew G. Knepley   PetscFunctionBegin;
552563a16f15SMatthew G. Knepley   mesh->refct++;
552663a16f15SMatthew G. Knepley   (*newdm)->data = mesh;
55271fca310dSJames Wright   PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &face_sfs));
55281fca310dSJames Wright   PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, num_face_sfs, (PetscSF *)face_sfs));
55299566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX));
55309566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(*newdm));
55313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
553263a16f15SMatthew G. Knepley }
553363a16f15SMatthew G. Knepley 
55348818961aSMatthew G Knepley /*MC
55350b4b7b1cSBarry Smith   DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh (or grid), or CW Complex {cite}`cwcomplex`,
55360b4b7b1cSBarry Smith            which can be expressed using a Hasse Diagram {cite}`hassediagram`.
553720f4b53cSBarry Smith            In the local representation, `Vec`s contain all unknowns in the interior and shared boundary. This is
55380b4b7b1cSBarry Smith            specified by a `PetscSection` object. Ownership in the global representation is determined by
5539a1cb98faSBarry Smith            ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object.
55408818961aSMatthew G Knepley 
5541e5893cccSMatthew G. Knepley   Options Database Keys:
5542250712c9SMatthew G. Knepley + -dm_refine_pre                     - Refine mesh before distribution
5543250712c9SMatthew G. Knepley + -dm_refine_uniform_pre             - Choose uniform or generator-based refinement
5544250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre        - Cell volume limit after pre-refinement using generator
5545250712c9SMatthew G. Knepley . -dm_distribute                     - Distribute mesh across processes
5546250712c9SMatthew G. Knepley . -dm_distribute_overlap             - Number of cells to overlap for distribution
5547250712c9SMatthew G. Knepley . -dm_refine                         - Refine mesh after distribution
5548c3db174cSMatthew G. Knepley . -dm_localize <bool>                - Whether to localize coordinates for periodic meshes
5549c3db174cSMatthew G. Knepley . -dm_sparse_localize <bool>         - Whether to only localize cells on the periodic boundary
5550250712c9SMatthew G. Knepley . -dm_plex_hash_location             - Use grid hashing for point location
5551ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p>    - The number of divisions in each direction of the grid hash
5552f12cf164SMatthew G. Knepley . -dm_plex_partition_balance         - Attempt to evenly divide points on partition boundary between processes
5553f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd                 - Allow changes to the boundary on remeshing
5554d5b43468SJose E. Roman . -dm_plex_max_projection_height     - Maximum mesh point height used to project locally
5555f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement        - Use special nested projection algorithm for regular refinement
5556d02c7345SMatthew G. Knepley . -dm_plex_reorder_section           - Use specialized blocking if available
5557aaa8cc7dSPierre Jolivet . -dm_plex_check_all                 - Perform all checks below
5558f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry            - Check that the adjacency information in the mesh is symmetric
5559f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices
5560f12cf164SMatthew 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
5561f12cf164SMatthew G. Knepley . -dm_plex_check_geometry            - Check that cells have positive volume
5562f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex     - View the mesh in LaTeX/TikZ
5563e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num>          - Scale the TikZ
55645962854dSMatthew G. Knepley . -dm_plex_print_fem <num>           - View FEM assembly information, such as element vectors and matrices
55655962854dSMatthew G. Knepley - -dm_plex_print_fvm <num>           - View FVM assembly information, such as flux updates
5566e5893cccSMatthew G. Knepley 
55678818961aSMatthew G Knepley   Level: intermediate
55688818961aSMatthew G Knepley 
55691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection`
55708818961aSMatthew G Knepley M*/
55718818961aSMatthew G Knepley 
5572d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm)
5573d71ae5a4SJacob Faibussowitsch {
5574552f7358SJed Brown   DM_Plex *mesh;
5575412e9a14SMatthew G. Knepley   PetscInt unit;
5576552f7358SJed Brown 
5577552f7358SJed Brown   PetscFunctionBegin;
5578f39ec787SMatthew G. Knepley   PetscCall(PetscCitationsRegister(PlexCitation, &Plexcite));
5579552f7358SJed Brown   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
55804dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&mesh));
5581adc21957SMatthew G. Knepley   dm->reorderSection = DM_REORDER_DEFAULT_NOTSET;
5582552f7358SJed Brown   dm->data           = mesh;
5583552f7358SJed Brown 
5584552f7358SJed Brown   mesh->refct = 1;
55859566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection));
55869566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection));
5587552f7358SJed Brown   mesh->refinementUniform       = PETSC_TRUE;
5588552f7358SJed Brown   mesh->refinementLimit         = -1.0;
5589e600fa54SMatthew G. Knepley   mesh->distDefault             = PETSC_TRUE;
5590adc21957SMatthew G. Knepley   mesh->reorderDefault          = DM_REORDER_DEFAULT_NOTSET;
55911d1f2f2aSksagiyam   mesh->distributionName        = NULL;
55927d0f5628SVaclav Hapla   mesh->interpolated            = DMPLEX_INTERPOLATED_INVALID;
55937d0f5628SVaclav Hapla   mesh->interpolatedCollective  = DMPLEX_INTERPOLATED_INVALID;
55945e2c5519SMatthew G. Knepley   mesh->interpolatePreferTensor = PETSC_TRUE;
5595552f7358SJed Brown 
55969566063dSJacob Faibussowitsch   PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner));
55972e62ab5aSMatthew G. Knepley   mesh->remeshBd = PETSC_FALSE;
5598d9deefdfSMatthew G. Knepley 
55998865f1eaSKarl Rupp   for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0;
5600552f7358SJed Brown 
5601df0420ecSMatthew G. Knepley   mesh->depthState    = -1;
5602ba2698f1SMatthew G. Knepley   mesh->celltypeState = -1;
56036113b454SMatthew G. Knepley   mesh->printTol      = 1.0e-10;
5604c29ce622SStefano Zampini   mesh->nonempty_comm = MPI_COMM_SELF;
5605552f7358SJed Brown 
56069566063dSJacob Faibussowitsch   PetscCall(DMInitialize_Plex(dm));
56073ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5608552f7358SJed Brown }
5609552f7358SJed Brown 
5610552f7358SJed Brown /*@
5611a1cb98faSBarry Smith   DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram.
5612552f7358SJed Brown 
5613d083f849SBarry Smith   Collective
5614552f7358SJed Brown 
5615552f7358SJed Brown   Input Parameter:
5616a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object
5617552f7358SJed Brown 
5618552f7358SJed Brown   Output Parameter:
5619a1cb98faSBarry Smith . mesh - The `DMPLEX` object
5620552f7358SJed Brown 
5621552f7358SJed Brown   Level: beginner
5622552f7358SJed Brown 
562342747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMCreate()`, `DMSetType()`
5624552f7358SJed Brown @*/
5625d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh)
5626d71ae5a4SJacob Faibussowitsch {
5627552f7358SJed Brown   PetscFunctionBegin;
56284f572ea9SToby Isaac   PetscAssertPointer(mesh, 2);
56299566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, mesh));
56309566063dSJacob Faibussowitsch   PetscCall(DMSetType(*mesh, DMPLEX));
56313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5632552f7358SJed Brown }
5633552f7358SJed Brown 
5634b09969d6SVaclav Hapla /*@C
5635b0fe842aSMatthew 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
5636a1cb98faSBarry Smith 
563720f4b53cSBarry Smith   Collective; No Fortran Support
5638b09969d6SVaclav Hapla 
5639b09969d6SVaclav Hapla   Input Parameters:
5640a1cb98faSBarry Smith + dm          - The `DM`
5641b09969d6SVaclav Hapla . numCells    - The number of cells owned by this process
5642a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
5643a1cb98faSBarry Smith . NVertices   - The global number of vertices, or `PETSC_DETERMINE`
5644b09969d6SVaclav Hapla . numCorners  - The number of vertices for each cell
56455e488331SVaclav Hapla - cells       - An array of numCells*numCorners numbers, the global vertex numbers for each cell
5646b09969d6SVaclav Hapla 
5647be8c289dSNicolas Barral   Output Parameters:
5648a1cb98faSBarry Smith + vertexSF         - (Optional) `PetscSF` describing complete vertex ownership
5649be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array
5650b09969d6SVaclav Hapla 
5651b09969d6SVaclav Hapla   Level: advanced
5652b09969d6SVaclav Hapla 
5653a1cb98faSBarry Smith   Notes:
5654a1cb98faSBarry Smith   Two triangles sharing a face
5655a1cb98faSBarry Smith .vb
5656a1cb98faSBarry Smith 
5657a1cb98faSBarry Smith         2
5658a1cb98faSBarry Smith       / | \
5659a1cb98faSBarry Smith      /  |  \
5660a1cb98faSBarry Smith     /   |   \
5661a1cb98faSBarry Smith    0  0 | 1  3
5662a1cb98faSBarry Smith     \   |   /
5663a1cb98faSBarry Smith      \  |  /
5664a1cb98faSBarry Smith       \ | /
5665a1cb98faSBarry Smith         1
5666a1cb98faSBarry Smith .ve
5667a1cb98faSBarry Smith   would have input
5668a1cb98faSBarry Smith .vb
5669a1cb98faSBarry Smith   numCells = 2, numVertices = 4
5670a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
5671a1cb98faSBarry Smith .ve
5672a1cb98faSBarry Smith   which would result in the `DMPLEX`
5673a1cb98faSBarry Smith .vb
5674a1cb98faSBarry Smith 
5675a1cb98faSBarry Smith         4
5676a1cb98faSBarry Smith       / | \
5677a1cb98faSBarry Smith      /  |  \
5678a1cb98faSBarry Smith     /   |   \
5679a1cb98faSBarry Smith    2  0 | 1  5
5680a1cb98faSBarry Smith     \   |   /
5681a1cb98faSBarry Smith      \  |  /
5682a1cb98faSBarry Smith       \ | /
5683a1cb98faSBarry Smith         3
5684a1cb98faSBarry Smith .ve
5685a1cb98faSBarry Smith 
5686a1cb98faSBarry Smith   Vertices are implicitly numbered consecutively 0,...,NVertices.
5687a1cb98faSBarry Smith   Each rank owns a chunk of numVertices consecutive vertices.
5688a1cb98faSBarry Smith   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
5689a1cb98faSBarry Smith   If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1.
5690a1cb98faSBarry Smith   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
5691a1cb98faSBarry Smith 
5692a1cb98faSBarry Smith   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
5693a1cb98faSBarry Smith 
56941cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
5695a1cb98faSBarry Smith           `PetscSF`
5696b09969d6SVaclav Hapla @*/
5697d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved)
5698d71ae5a4SJacob Faibussowitsch {
56992464107aSksagiyam   PetscSF     sfPoint;
57002464107aSksagiyam   PetscLayout layout;
570182fb893eSVaclav Hapla   PetscInt    numVerticesAdj, *verticesAdj, *cones, c, p;
5702a47d0d45SMatthew G. Knepley 
5703a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
570425b6865aSVaclav Hapla   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
57059566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
570625b6865aSVaclav Hapla   /* Get/check global number of vertices */
570725b6865aSVaclav Hapla   {
570825b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
570925b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
571025b6865aSVaclav Hapla 
571125b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
57121690c2aeSBarry Smith     NVerticesInCells = PETSC_INT_MIN;
57139371c9d4SSatish Balay     for (i = 0; i < len; i++)
57149371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
571525b6865aSVaclav Hapla     ++NVerticesInCells;
5716462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
571725b6865aSVaclav Hapla 
571825b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
57199371c9d4SSatish Balay     else
57209371c9d4SSatish 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);
572125b6865aSVaclav Hapla   }
57229079aca8SVaclav Hapla   /* Count locally unique vertices */
57239079aca8SVaclav Hapla   {
57249079aca8SVaclav Hapla     PetscHSetI vhash;
57259079aca8SVaclav Hapla     PetscInt   off = 0;
57269079aca8SVaclav Hapla 
57279566063dSJacob Faibussowitsch     PetscCall(PetscHSetICreate(&vhash));
5728a47d0d45SMatthew G. Knepley     for (c = 0; c < numCells; ++c) {
572948a46eb9SPierre Jolivet       for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p]));
5730a47d0d45SMatthew G. Knepley     }
57319566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
57329566063dSJacob Faibussowitsch     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
5733ad540459SPierre Jolivet     else verticesAdj = *verticesAdjSaved;
57349566063dSJacob Faibussowitsch     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
57359566063dSJacob Faibussowitsch     PetscCall(PetscHSetIDestroy(&vhash));
573663a3b9bcSJacob Faibussowitsch     PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj);
5737a47d0d45SMatthew G. Knepley   }
57389566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
5739a47d0d45SMatthew G. Knepley   /* Create cones */
57409566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
57419566063dSJacob Faibussowitsch   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
57429566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
57439566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
5744a47d0d45SMatthew G. Knepley   for (c = 0; c < numCells; ++c) {
5745a47d0d45SMatthew G. Knepley     for (p = 0; p < numCorners; ++p) {
5746a47d0d45SMatthew G. Knepley       const PetscInt gv = cells[c * numCorners + p];
5747a47d0d45SMatthew G. Knepley       PetscInt       lv;
5748a47d0d45SMatthew G. Knepley 
57499079aca8SVaclav Hapla       /* Positions within verticesAdj form 0-based local vertex numbering;
57509079aca8SVaclav Hapla          we need to shift it by numCells to get correct DAG points (cells go first) */
57519566063dSJacob Faibussowitsch       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
575263a3b9bcSJacob Faibussowitsch       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
5753961cfab0SVaclav Hapla       cones[c * numCorners + p] = lv + numCells;
5754a47d0d45SMatthew G. Knepley     }
5755a47d0d45SMatthew G. Knepley   }
57562464107aSksagiyam   /* Build point sf */
57579566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
57589566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetSize(layout, NVertices));
57599566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
57609566063dSJacob Faibussowitsch   PetscCall(PetscLayoutSetBlockSize(layout, 1));
57619566063dSJacob Faibussowitsch   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
57629566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&layout));
57639566063dSJacob Faibussowitsch   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
57649566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
57652464107aSksagiyam   if (dm->sf) {
57662464107aSksagiyam     const char *prefix;
57672464107aSksagiyam 
57689566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
57699566063dSJacob Faibussowitsch     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
57702464107aSksagiyam   }
57719566063dSJacob Faibussowitsch   PetscCall(DMSetPointSF(dm, sfPoint));
57729566063dSJacob Faibussowitsch   PetscCall(PetscSFDestroy(&sfPoint));
5773f4f49eeaSPierre Jolivet   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF"));
5774a47d0d45SMatthew G. Knepley   /* Fill in the rest of the topology structure */
57759566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
57769566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
57779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
57783ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5779a47d0d45SMatthew G. Knepley }
5780a47d0d45SMatthew G. Knepley 
5781b0fe842aSMatthew G. Knepley /*@C
5782b0fe842aSMatthew G. Knepley   DMPlexBuildFromCellSectionParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) allowing multiple celltypes
5783b0fe842aSMatthew G. Knepley 
5784b0fe842aSMatthew G. Knepley   Collective; No Fortran Support
5785b0fe842aSMatthew G. Knepley 
5786b0fe842aSMatthew G. Knepley   Input Parameters:
5787b0fe842aSMatthew G. Knepley + dm          - The `DM`
5788b0fe842aSMatthew G. Knepley . numCells    - The number of cells owned by this process
5789b0fe842aSMatthew G. Knepley . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE`
5790b0fe842aSMatthew G. Knepley . NVertices   - The global number of vertices, or `PETSC_DETERMINE`
5791b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells)
5792b0fe842aSMatthew G. Knepley - cells       - An array of the global vertex numbers for each cell
5793b0fe842aSMatthew G. Knepley 
5794b0fe842aSMatthew G. Knepley   Output Parameters:
5795b0fe842aSMatthew G. Knepley + vertexSF         - (Optional) `PetscSF` describing complete vertex ownership
5796b0fe842aSMatthew G. Knepley - verticesAdjSaved - (Optional) vertex adjacency array
5797b0fe842aSMatthew G. Knepley 
5798b0fe842aSMatthew G. Knepley   Level: advanced
5799b0fe842aSMatthew G. Knepley 
5800b0fe842aSMatthew G. Knepley   Notes:
5801b0fe842aSMatthew G. Knepley   A triangle and quadrilateral sharing a face
5802b0fe842aSMatthew G. Knepley .vb
5803b0fe842aSMatthew G. Knepley         2----------3
5804b0fe842aSMatthew G. Knepley       / |          |
5805b0fe842aSMatthew G. Knepley      /  |          |
5806b0fe842aSMatthew G. Knepley     /   |          |
5807b0fe842aSMatthew G. Knepley    0  0 |     1    |
5808b0fe842aSMatthew G. Knepley     \   |          |
5809b0fe842aSMatthew G. Knepley      \  |          |
5810b0fe842aSMatthew G. Knepley       \ |          |
5811b0fe842aSMatthew G. Knepley         1----------4
5812b0fe842aSMatthew G. Knepley .ve
5813b0fe842aSMatthew G. Knepley   would have input
5814b0fe842aSMatthew G. Knepley .vb
5815b0fe842aSMatthew G. Knepley   numCells = 2, numVertices = 5
5816b0fe842aSMatthew G. Knepley   cells = [0 1 2  1 4 3 2]
5817b0fe842aSMatthew G. Knepley .ve
5818b0fe842aSMatthew G. Knepley   which would result in the `DMPLEX`
5819b0fe842aSMatthew G. Knepley .vb
5820b0fe842aSMatthew G. Knepley         4----------5
5821b0fe842aSMatthew G. Knepley       / |          |
5822b0fe842aSMatthew G. Knepley      /  |          |
5823b0fe842aSMatthew G. Knepley     /   |          |
5824b0fe842aSMatthew G. Knepley    2  0 |     1    |
5825b0fe842aSMatthew G. Knepley     \   |          |
5826b0fe842aSMatthew G. Knepley      \  |          |
5827b0fe842aSMatthew G. Knepley       \ |          |
5828b0fe842aSMatthew G. Knepley         3----------6
5829b0fe842aSMatthew G. Knepley .ve
5830b0fe842aSMatthew G. Knepley 
5831b0fe842aSMatthew G. Knepley   Vertices are implicitly numbered consecutively 0,...,NVertices.
5832b0fe842aSMatthew G. Knepley   Each rank owns a chunk of numVertices consecutive vertices.
5833b0fe842aSMatthew G. Knepley   If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout.
5834b0fe842aSMatthew 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.
5835b0fe842aSMatthew G. Knepley   If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks.
5836b0fe842aSMatthew G. Knepley 
5837b0fe842aSMatthew G. Knepley   The cell distribution is arbitrary non-overlapping, independent of the vertex distribution.
5838b0fe842aSMatthew G. Knepley 
5839b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexCreateFromCellSectionParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`,
5840b0fe842aSMatthew G. Knepley           `PetscSF`
5841b0fe842aSMatthew G. Knepley @*/
5842b0fe842aSMatthew G. Knepley PetscErrorCode DMPlexBuildFromCellSectionParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved)
5843b0fe842aSMatthew G. Knepley {
5844b0fe842aSMatthew G. Knepley   PetscSF     sfPoint;
5845b0fe842aSMatthew G. Knepley   PetscLayout layout;
5846b0fe842aSMatthew G. Knepley   PetscInt    numVerticesAdj, *verticesAdj, *cones, cStart, cEnd, len;
5847b0fe842aSMatthew G. Knepley 
5848b0fe842aSMatthew G. Knepley   PetscFunctionBegin;
5849b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(dm, NVertices, 4);
5850b0fe842aSMatthew G. Knepley   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
5851b0fe842aSMatthew G. Knepley   PetscCall(PetscSectionGetChart(cellSection, &cStart, &cEnd));
5852b0fe842aSMatthew G. Knepley   PetscCall(PetscSectionGetStorageSize(cellSection, &len));
5853b0fe842aSMatthew 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);
5854b0fe842aSMatthew G. Knepley   /* Get/check global number of vertices */
5855b0fe842aSMatthew G. Knepley   {
5856b0fe842aSMatthew G. Knepley     PetscInt NVerticesInCells;
5857b0fe842aSMatthew G. Knepley 
5858b0fe842aSMatthew G. Knepley     /* NVerticesInCells = max(cells) + 1 */
5859b0fe842aSMatthew G. Knepley     NVerticesInCells = PETSC_MIN_INT;
5860b0fe842aSMatthew G. Knepley     for (PetscInt i = 0; i < len; i++)
5861b0fe842aSMatthew G. Knepley       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
5862b0fe842aSMatthew G. Knepley     ++NVerticesInCells;
5863b0fe842aSMatthew G. Knepley     PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm)));
5864b0fe842aSMatthew G. Knepley 
5865b0fe842aSMatthew G. Knepley     if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells;
5866b0fe842aSMatthew G. Knepley     else
5867b0fe842aSMatthew 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);
5868b0fe842aSMatthew G. Knepley   }
5869b0fe842aSMatthew G. Knepley   /* Count locally unique vertices */
5870b0fe842aSMatthew G. Knepley   {
5871b0fe842aSMatthew G. Knepley     PetscHSetI vhash;
5872b0fe842aSMatthew G. Knepley     PetscInt   off = 0;
5873b0fe842aSMatthew G. Knepley 
5874b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetICreate(&vhash));
5875b0fe842aSMatthew G. Knepley     for (PetscInt i = 0; i < len; i++) PetscCall(PetscHSetIAdd(vhash, cells[i]));
5876b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj));
5877b0fe842aSMatthew G. Knepley     if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj));
5878b0fe842aSMatthew G. Knepley     else verticesAdj = *verticesAdjSaved;
5879b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj));
5880b0fe842aSMatthew G. Knepley     PetscCall(PetscHSetIDestroy(&vhash));
5881b0fe842aSMatthew 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);
5882b0fe842aSMatthew G. Knepley   }
5883b0fe842aSMatthew G. Knepley   PetscCall(PetscSortInt(numVerticesAdj, verticesAdj));
5884b0fe842aSMatthew G. Knepley   /* Create cones */
5885b0fe842aSMatthew G. Knepley   PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj));
5886b0fe842aSMatthew G. Knepley   for (PetscInt c = 0; c < numCells; ++c) {
5887b0fe842aSMatthew G. Knepley     PetscInt dof;
5888b0fe842aSMatthew G. Knepley 
5889b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetDof(cellSection, c, &dof));
5890b0fe842aSMatthew G. Knepley     PetscCall(DMPlexSetConeSize(dm, c, dof));
5891b0fe842aSMatthew G. Knepley   }
5892b0fe842aSMatthew G. Knepley   PetscCall(DMSetUp(dm));
5893b0fe842aSMatthew G. Knepley   PetscCall(DMPlexGetCones(dm, &cones));
5894b0fe842aSMatthew G. Knepley   for (PetscInt c = 0; c < numCells; ++c) {
5895b0fe842aSMatthew G. Knepley     PetscInt dof, off;
5896b0fe842aSMatthew G. Knepley 
5897b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetDof(cellSection, c, &dof));
5898b0fe842aSMatthew G. Knepley     PetscCall(PetscSectionGetOffset(cellSection, c, &off));
5899b0fe842aSMatthew G. Knepley     for (PetscInt p = off; p < off + dof; ++p) {
5900b0fe842aSMatthew G. Knepley       const PetscInt gv = cells[p];
5901b0fe842aSMatthew G. Knepley       PetscInt       lv;
5902b0fe842aSMatthew G. Knepley 
5903b0fe842aSMatthew G. Knepley       /* Positions within verticesAdj form 0-based local vertex numbering;
5904b0fe842aSMatthew G. Knepley          we need to shift it by numCells to get correct DAG points (cells go first) */
5905b0fe842aSMatthew G. Knepley       PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv));
5906b0fe842aSMatthew G. Knepley       PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv);
5907b0fe842aSMatthew G. Knepley       cones[p] = lv + numCells;
5908b0fe842aSMatthew G. Knepley     }
5909b0fe842aSMatthew G. Knepley   }
5910b0fe842aSMatthew G. Knepley   /* Build point sf */
5911b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout));
5912b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetSize(layout, NVertices));
5913b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetLocalSize(layout, numVertices));
5914b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutSetBlockSize(layout, 1));
5915b0fe842aSMatthew G. Knepley   PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint));
5916b0fe842aSMatthew G. Knepley   PetscCall(PetscLayoutDestroy(&layout));
5917b0fe842aSMatthew G. Knepley   if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj));
5918b0fe842aSMatthew G. Knepley   PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF"));
5919b0fe842aSMatthew G. Knepley   if (dm->sf) {
5920b0fe842aSMatthew G. Knepley     const char *prefix;
5921b0fe842aSMatthew G. Knepley 
5922b0fe842aSMatthew G. Knepley     PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix));
5923b0fe842aSMatthew G. Knepley     PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix));
5924b0fe842aSMatthew G. Knepley   }
5925b0fe842aSMatthew G. Knepley   PetscCall(DMSetPointSF(dm, sfPoint));
5926b0fe842aSMatthew G. Knepley   PetscCall(PetscSFDestroy(&sfPoint));
5927b0fe842aSMatthew G. Knepley   if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF"));
5928b0fe842aSMatthew G. Knepley   /* Fill in the rest of the topology structure */
5929b0fe842aSMatthew G. Knepley   PetscCall(DMPlexSymmetrize(dm));
5930b0fe842aSMatthew G. Knepley   PetscCall(DMPlexStratify(dm));
5931b0fe842aSMatthew G. Knepley   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
5932b0fe842aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
5933b0fe842aSMatthew G. Knepley }
5934b0fe842aSMatthew G. Knepley 
5935cc4c1da9SBarry Smith /*@
5936a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
5937a1cb98faSBarry Smith 
593820f4b53cSBarry Smith   Collective; No Fortran Support
5939b09969d6SVaclav Hapla 
5940b09969d6SVaclav Hapla   Input Parameters:
5941a1cb98faSBarry Smith + dm           - The `DM`
5942b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
5943a1cb98faSBarry Smith . sfVert       - `PetscSF` describing complete vertex ownership
5944b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
5945b09969d6SVaclav Hapla 
5946b09969d6SVaclav Hapla   Level: advanced
5947b09969d6SVaclav Hapla 
59481cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()`
5949b09969d6SVaclav Hapla @*/
5950d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[])
5951d71ae5a4SJacob Faibussowitsch {
5952a47d0d45SMatthew G. Knepley   PetscSection coordSection;
5953a47d0d45SMatthew G. Knepley   Vec          coordinates;
5954a47d0d45SMatthew G. Knepley   PetscScalar *coords;
59551edcf0b2SVaclav Hapla   PetscInt     numVertices, numVerticesAdj, coordSize, v, vStart, vEnd;
5956835f2295SStefano Zampini   PetscMPIInt  spaceDimi;
5957a47d0d45SMatthew G. Knepley 
5958a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
59599566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
59609566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
59611dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
59629566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
59639566063dSJacob Faibussowitsch   PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL));
59641dca8a05SBarry 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);
59659566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
59669566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
59679566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
59689566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
59691edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
59709566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
59719566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
5972a47d0d45SMatthew G. Knepley   }
59739566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
59749566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
59759566063dSJacob Faibussowitsch   PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates));
59769566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
59779566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
59789566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
59799566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
59809566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
5981a47d0d45SMatthew G. Knepley   {
5982a47d0d45SMatthew G. Knepley     MPI_Datatype coordtype;
5983a47d0d45SMatthew G. Knepley 
5984a47d0d45SMatthew G. Knepley     /* Need a temp buffer for coords if we have complex/single */
5985835f2295SStefano Zampini     PetscCall(PetscMPIIntCast(spaceDim, &spaceDimi));
5986835f2295SStefano Zampini     PetscCallMPI(MPI_Type_contiguous(spaceDimi, MPIU_SCALAR, &coordtype));
59879566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_commit(&coordtype));
598821016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX)
598921016a8bSBarry Smith     {
599021016a8bSBarry Smith       PetscScalar *svertexCoords;
599121016a8bSBarry Smith       PetscInt     i;
59929566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords));
59933612f820SVaclav Hapla       for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i];
59949566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
59959566063dSJacob Faibussowitsch       PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE));
59969566063dSJacob Faibussowitsch       PetscCall(PetscFree(svertexCoords));
599721016a8bSBarry Smith     }
599821016a8bSBarry Smith #else
59999566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
60009566063dSJacob Faibussowitsch     PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE));
600121016a8bSBarry Smith #endif
60029566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Type_free(&coordtype));
6003a47d0d45SMatthew G. Knepley   }
60049566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
60059566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
60069566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
60079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
60083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6009a47d0d45SMatthew G. Knepley }
6010a47d0d45SMatthew G. Knepley 
6011c3edce3dSSatish Balay /*@
6012b0fe842aSMatthew 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
6013a1cb98faSBarry Smith 
6014a1cb98faSBarry Smith   Collective
6015a47d0d45SMatthew G. Knepley 
6016a47d0d45SMatthew G. Knepley   Input Parameters:
6017a47d0d45SMatthew G. Knepley + comm         - The communicator
6018a47d0d45SMatthew G. Knepley . dim          - The topological dimension of the mesh
6019a47d0d45SMatthew G. Knepley . numCells     - The number of cells owned by this process
6020a1cb98faSBarry Smith . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`
6021a1cb98faSBarry Smith . NVertices    - The global number of vertices, or `PETSC_DECIDE`
6022a47d0d45SMatthew G. Knepley . numCorners   - The number of vertices for each cell
6023a47d0d45SMatthew G. Knepley . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
6024a47d0d45SMatthew G. Knepley . cells        - An array of numCells*numCorners numbers, the global vertex numbers for each cell
6025a47d0d45SMatthew G. Knepley . spaceDim     - The spatial dimension used for coordinates
6026a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6027a47d0d45SMatthew G. Knepley 
6028d8d19677SJose E. Roman   Output Parameters:
6029a1cb98faSBarry Smith + dm          - The `DM`
6030a1cb98faSBarry Smith . vertexSF    - (Optional) `PetscSF` describing complete vertex ownership
603160225df5SJacob Faibussowitsch - verticesAdj - (Optional) vertex adjacency array
6032a47d0d45SMatthew G. Knepley 
6033b09969d6SVaclav Hapla   Level: intermediate
6034a47d0d45SMatthew G. Knepley 
6035a1cb98faSBarry Smith   Notes:
6036a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
6037a1cb98faSBarry Smith   `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
6038a1cb98faSBarry Smith 
6039a1cb98faSBarry Smith   See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters.
6040a1cb98faSBarry Smith 
6041a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
6042a1cb98faSBarry Smith 
60431cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
6044a47d0d45SMatthew G. Knepley @*/
6045d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromCellListParallelPetsc(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PetscSF *vertexSF, PetscInt **verticesAdj, DM *dm)
6046d71ae5a4SJacob Faibussowitsch {
6047a47d0d45SMatthew G. Knepley   PetscSF sfVert;
6048a47d0d45SMatthew G. Knepley 
6049a47d0d45SMatthew G. Knepley   PetscFunctionBegin;
60509566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
60519566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
6052a47d0d45SMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
6053064a246eSJacob Faibussowitsch   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
60549566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
60559566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj));
6056a47d0d45SMatthew G. Knepley   if (interpolate) {
60575fd9971aSMatthew G. Knepley     DM idm;
6058a47d0d45SMatthew G. Knepley 
60599566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
60609566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
6061a47d0d45SMatthew G. Knepley     *dm = idm;
6062a47d0d45SMatthew G. Knepley   }
60639566063dSJacob Faibussowitsch   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
606418d54ad4SMichael Lange   if (vertexSF) *vertexSF = sfVert;
60659566063dSJacob Faibussowitsch   else PetscCall(PetscSFDestroy(&sfVert));
60663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6067a47d0d45SMatthew G. Knepley }
6068a47d0d45SMatthew G. Knepley 
6069cc4c1da9SBarry Smith /*@
6070b0fe842aSMatthew G. Knepley   DMPlexCreateFromCellSectionParallel - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) and supports multiple celltypes
6071b0fe842aSMatthew G. Knepley 
6072b0fe842aSMatthew G. Knepley   Collective
6073b0fe842aSMatthew G. Knepley 
6074b0fe842aSMatthew G. Knepley   Input Parameters:
6075b0fe842aSMatthew G. Knepley + comm         - The communicator
6076b0fe842aSMatthew G. Knepley . dim          - The topological dimension of the mesh
6077b0fe842aSMatthew G. Knepley . numCells     - The number of cells owned by this process
6078b0fe842aSMatthew G. Knepley . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`
6079b0fe842aSMatthew G. Knepley . NVertices    - The global number of vertices, or `PETSC_DECIDE`
6080b0fe842aSMatthew G. Knepley . cellSection  - The `PetscSection` giving the number of vertices for each cell (layout of cells)
6081b0fe842aSMatthew G. Knepley . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
6082b0fe842aSMatthew G. Knepley . cells        - An array of the global vertex numbers for each cell
6083b0fe842aSMatthew G. Knepley . spaceDim     - The spatial dimension used for coordinates
6084b0fe842aSMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6085b0fe842aSMatthew G. Knepley 
6086b0fe842aSMatthew G. Knepley   Output Parameters:
6087b0fe842aSMatthew G. Knepley + dm          - The `DM`
6088b0fe842aSMatthew G. Knepley . vertexSF    - (Optional) `PetscSF` describing complete vertex ownership
6089b0fe842aSMatthew G. Knepley - verticesAdj - (Optional) vertex adjacency array
6090b0fe842aSMatthew G. Knepley 
6091b0fe842aSMatthew G. Knepley   Level: intermediate
6092b0fe842aSMatthew G. Knepley 
6093b0fe842aSMatthew G. Knepley   Notes:
6094b0fe842aSMatthew G. Knepley   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`,
6095b0fe842aSMatthew G. Knepley   `DMPlexBuildFromCellSectionParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()`
6096b0fe842aSMatthew G. Knepley 
6097b0fe842aSMatthew G. Knepley   See `DMPlexBuildFromCellSectionParallel()` for an example and details about the topology-related parameters.
6098b0fe842aSMatthew G. Knepley 
6099b0fe842aSMatthew G. Knepley   See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters.
6100b0fe842aSMatthew G. Knepley 
6101b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
6102b0fe842aSMatthew G. Knepley @*/
6103b0fe842aSMatthew G. Knepley PetscErrorCode DMPlexCreateFromCellSectionParallel(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PetscSF *vertexSF, PetscInt **verticesAdj, DM *dm)
6104b0fe842aSMatthew G. Knepley {
6105b0fe842aSMatthew G. Knepley   PetscSF sfVert;
6106b0fe842aSMatthew G. Knepley 
6107b0fe842aSMatthew G. Knepley   PetscFunctionBegin;
6108b0fe842aSMatthew G. Knepley   PetscCall(DMCreate(comm, dm));
6109b0fe842aSMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
6110b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, dim, 2);
6111b0fe842aSMatthew G. Knepley   PetscValidLogicalCollectiveInt(*dm, spaceDim, 9);
6112b0fe842aSMatthew G. Knepley   PetscCall(DMSetDimension(*dm, dim));
6113b0fe842aSMatthew G. Knepley   PetscCall(DMPlexBuildFromCellSectionParallel(*dm, numCells, numVertices, NVertices, cellSection, cells, &sfVert, verticesAdj));
6114b0fe842aSMatthew G. Knepley   if (interpolate) {
6115b0fe842aSMatthew G. Knepley     DM idm;
6116b0fe842aSMatthew G. Knepley 
6117b0fe842aSMatthew G. Knepley     PetscCall(DMPlexInterpolate(*dm, &idm));
6118b0fe842aSMatthew G. Knepley     PetscCall(DMDestroy(dm));
6119b0fe842aSMatthew G. Knepley     *dm = idm;
6120b0fe842aSMatthew G. Knepley   }
6121b0fe842aSMatthew G. Knepley   PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords));
6122b0fe842aSMatthew G. Knepley   if (vertexSF) *vertexSF = sfVert;
6123b0fe842aSMatthew G. Knepley   else PetscCall(PetscSFDestroy(&sfVert));
6124b0fe842aSMatthew G. Knepley   PetscFunctionReturn(PETSC_SUCCESS);
6125b0fe842aSMatthew G. Knepley }
6126b0fe842aSMatthew G. Knepley 
6127b0fe842aSMatthew G. Knepley /*@
6128a1cb98faSBarry Smith   DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output)
6129a1cb98faSBarry Smith 
613020f4b53cSBarry Smith   Collective; No Fortran Support
61319298eaa6SMatthew G Knepley 
61329298eaa6SMatthew G Knepley   Input Parameters:
6133a1cb98faSBarry Smith + dm          - The `DM`
6134b09969d6SVaclav Hapla . numCells    - The number of cells owned by this process
6135a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE`
61369298eaa6SMatthew G Knepley . numCorners  - The number of vertices for each cell
6137a3b724e8SBarry Smith - cells       - An array of `numCells` x `numCorners` numbers, the global vertex numbers for each cell
61389298eaa6SMatthew G Knepley 
6139b09969d6SVaclav Hapla   Level: advanced
61409298eaa6SMatthew G Knepley 
6141b09969d6SVaclav Hapla   Notes:
6142b09969d6SVaclav Hapla   Two triangles sharing a face
6143a1cb98faSBarry Smith .vb
61449298eaa6SMatthew G Knepley 
6145a1cb98faSBarry Smith         2
6146a1cb98faSBarry Smith       / | \
6147a1cb98faSBarry Smith      /  |  \
6148a1cb98faSBarry Smith     /   |   \
6149a1cb98faSBarry Smith    0  0 | 1  3
6150a1cb98faSBarry Smith     \   |   /
6151a1cb98faSBarry Smith      \  |  /
6152a1cb98faSBarry Smith       \ | /
6153a1cb98faSBarry Smith         1
6154a1cb98faSBarry Smith .ve
6155a1cb98faSBarry Smith   would have input
6156a1cb98faSBarry Smith .vb
6157a1cb98faSBarry Smith   numCells = 2, numVertices = 4
6158a1cb98faSBarry Smith   cells = [0 1 2  1 3 2]
6159a1cb98faSBarry Smith .ve
6160a1cb98faSBarry Smith   which would result in the `DMPLEX`
6161a1cb98faSBarry Smith .vb
6162a1cb98faSBarry Smith 
6163a1cb98faSBarry Smith         4
6164a1cb98faSBarry Smith       / | \
6165a1cb98faSBarry Smith      /  |  \
6166a1cb98faSBarry Smith     /   |   \
6167a1cb98faSBarry Smith    2  0 | 1  5
6168a1cb98faSBarry Smith     \   |   /
6169a1cb98faSBarry Smith      \  |  /
6170a1cb98faSBarry Smith       \ | /
6171a1cb98faSBarry Smith         3
6172a1cb98faSBarry Smith .ve
6173a1cb98faSBarry Smith 
6174a1cb98faSBarry Smith   If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1.
617525b6865aSVaclav Hapla 
61761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()`
6177b09969d6SVaclav Hapla @*/
6178d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[])
6179d71ae5a4SJacob Faibussowitsch {
6180961cfab0SVaclav Hapla   PetscInt *cones, c, p, dim;
6181b09969d6SVaclav Hapla 
6182b09969d6SVaclav Hapla   PetscFunctionBegin;
61839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
61849566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
618525b6865aSVaclav Hapla   /* Get/check global number of vertices */
618625b6865aSVaclav Hapla   {
618725b6865aSVaclav Hapla     PetscInt       NVerticesInCells, i;
618825b6865aSVaclav Hapla     const PetscInt len = numCells * numCorners;
618925b6865aSVaclav Hapla 
619025b6865aSVaclav Hapla     /* NVerticesInCells = max(cells) + 1 */
61911690c2aeSBarry Smith     NVerticesInCells = PETSC_INT_MIN;
61929371c9d4SSatish Balay     for (i = 0; i < len; i++)
61939371c9d4SSatish Balay       if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i];
619425b6865aSVaclav Hapla     ++NVerticesInCells;
619525b6865aSVaclav Hapla 
619625b6865aSVaclav Hapla     if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells;
61979371c9d4SSatish Balay     else
61989371c9d4SSatish 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);
619925b6865aSVaclav Hapla   }
62009566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices));
620148a46eb9SPierre Jolivet   for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners));
62029566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm));
62039566063dSJacob Faibussowitsch   PetscCall(DMPlexGetCones(dm, &cones));
6204b09969d6SVaclav Hapla   for (c = 0; c < numCells; ++c) {
6205ad540459SPierre Jolivet     for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells;
6206b09969d6SVaclav Hapla   }
62079566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
62089566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
62099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0));
62103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6211b09969d6SVaclav Hapla }
6212b09969d6SVaclav Hapla 
6213cc4c1da9SBarry Smith /*@
6214a1cb98faSBarry Smith   DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output)
6215a1cb98faSBarry Smith 
6216cc4c1da9SBarry Smith   Collective
6217b09969d6SVaclav Hapla 
6218b09969d6SVaclav Hapla   Input Parameters:
6219a1cb98faSBarry Smith + dm           - The `DM`
6220b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
6221b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex
6222b09969d6SVaclav Hapla 
6223b09969d6SVaclav Hapla   Level: advanced
6224b09969d6SVaclav Hapla 
62251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()`
6226b09969d6SVaclav Hapla @*/
6227d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[])
6228d71ae5a4SJacob Faibussowitsch {
6229b09969d6SVaclav Hapla   PetscSection coordSection;
6230b09969d6SVaclav Hapla   Vec          coordinates;
6231b09969d6SVaclav Hapla   DM           cdm;
6232b09969d6SVaclav Hapla   PetscScalar *coords;
62331edcf0b2SVaclav Hapla   PetscInt     v, vStart, vEnd, d;
6234b09969d6SVaclav Hapla 
6235b09969d6SVaclav Hapla   PetscFunctionBegin;
62369566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
62379566063dSJacob Faibussowitsch   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
62381dca8a05SBarry Smith   PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first.");
62399566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(dm, spaceDim));
62409566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
62419566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
62429566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim));
62439566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd));
62441edcf0b2SVaclav Hapla   for (v = vStart; v < vEnd; ++v) {
62459566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, spaceDim));
62469566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim));
6247b09969d6SVaclav Hapla   }
62489566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
6249b09969d6SVaclav Hapla 
62509566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDM(dm, &cdm));
62519566063dSJacob Faibussowitsch   PetscCall(DMCreateLocalVector(cdm, &coordinates));
62529566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, spaceDim));
62539566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
62549566063dSJacob Faibussowitsch   PetscCall(VecGetArrayWrite(coordinates, &coords));
62551edcf0b2SVaclav Hapla   for (v = 0; v < vEnd - vStart; ++v) {
6256ad540459SPierre Jolivet     for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d];
6257b09969d6SVaclav Hapla   }
62589566063dSJacob Faibussowitsch   PetscCall(VecRestoreArrayWrite(coordinates, &coords));
62599566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
62609566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
62619566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0));
62623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6263b09969d6SVaclav Hapla }
6264b09969d6SVaclav Hapla 
6265b09969d6SVaclav Hapla /*@
6266a1cb98faSBarry Smith   DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input
62673df08285SMatthew G. Knepley 
6268a1cb98faSBarry Smith   Collective
6269b09969d6SVaclav Hapla 
6270b09969d6SVaclav Hapla   Input Parameters:
6271b09969d6SVaclav Hapla + comm         - The communicator
6272b09969d6SVaclav Hapla . dim          - The topological dimension of the mesh
62733df08285SMatthew G. Knepley . numCells     - The number of cells, only on process 0
6274a1cb98faSBarry Smith . numVertices  - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0
62753df08285SMatthew G. Knepley . numCorners   - The number of vertices for each cell, only on process 0
6276b09969d6SVaclav Hapla . interpolate  - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically
62773df08285SMatthew G. Knepley . cells        - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0
6278b09969d6SVaclav Hapla . spaceDim     - The spatial dimension used for coordinates
62793df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0
6280b09969d6SVaclav Hapla 
6281b09969d6SVaclav Hapla   Output Parameter:
6282a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0
628325b6865aSVaclav Hapla 
6284b09969d6SVaclav Hapla   Level: intermediate
6285b09969d6SVaclav Hapla 
6286a1cb98faSBarry Smith   Notes:
6287a1cb98faSBarry Smith   This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`,
6288a1cb98faSBarry Smith   `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()`
6289a1cb98faSBarry Smith 
6290a1cb98faSBarry Smith   See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters.
6291a1cb98faSBarry Smith   See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters.
6292a1cb98faSBarry Smith   See `DMPlexCreateFromCellListParallelPetsc()` for parallel input
6293a1cb98faSBarry Smith 
62941cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()`
62959298eaa6SMatthew G Knepley @*/
6296d71ae5a4SJacob 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)
6297d71ae5a4SJacob Faibussowitsch {
62983df08285SMatthew G. Knepley   PetscMPIInt rank;
62999298eaa6SMatthew G Knepley 
63009298eaa6SMatthew G Knepley   PetscFunctionBegin;
630128b400f6SJacob 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.");
63029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
63039566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
63049566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
63059566063dSJacob Faibussowitsch   PetscCall(DMSetDimension(*dm, dim));
6306c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells));
63079566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL));
63089298eaa6SMatthew G Knepley   if (interpolate) {
63095fd9971aSMatthew G. Knepley     DM idm;
63109298eaa6SMatthew G Knepley 
63119566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
63129566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
63139298eaa6SMatthew G Knepley     *dm = idm;
63149298eaa6SMatthew G Knepley   }
6315c5853193SPierre Jolivet   if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords));
63169566063dSJacob Faibussowitsch   else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL));
63173ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
63189298eaa6SMatthew G Knepley }
63199298eaa6SMatthew G Knepley 
6320939f6067SMatthew G. Knepley /*@
632120f4b53cSBarry Smith   DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a `DM`
6322939f6067SMatthew G. Knepley 
6323939f6067SMatthew G. Knepley   Input Parameters:
632420f4b53cSBarry Smith + dm               - The empty `DM` object, usually from `DMCreate()` and `DMSetDimension()`
6325939f6067SMatthew G. Knepley . depth            - The depth of the DAG
632620f4b53cSBarry Smith . numPoints        - Array of size depth + 1 containing the number of points at each `depth`
6327939f6067SMatthew G. Knepley . coneSize         - The cone size of each point
6328939f6067SMatthew G. Knepley . cones            - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point
6329939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point
633020f4b53cSBarry Smith - vertexCoords     - An array of `numPoints`[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via `DMSetCoordinateDim()`
6331939f6067SMatthew G. Knepley 
6332939f6067SMatthew G. Knepley   Output Parameter:
633320f4b53cSBarry Smith . dm - The `DM`
633420f4b53cSBarry Smith 
633520f4b53cSBarry Smith   Level: advanced
6336939f6067SMatthew G. Knepley 
6337a1cb98faSBarry Smith   Note:
6338a1cb98faSBarry Smith   Two triangles sharing a face would have input
6339a1cb98faSBarry Smith .vb
6340a1cb98faSBarry Smith   depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0]
6341a1cb98faSBarry Smith   cones = [2 3 4  3 5 4], coneOrientations = [0 0 0  0 0 0]
6342a1cb98faSBarry Smith  vertexCoords = [-1.0 0.0  0.0 -1.0  0.0 1.0  1.0 0.0]
6343a1cb98faSBarry Smith .ve
6344939f6067SMatthew G. Knepley   which would result in the DMPlex
6345a1cb98faSBarry Smith .vb
6346a1cb98faSBarry Smith         4
6347a1cb98faSBarry Smith       / | \
6348a1cb98faSBarry Smith      /  |  \
6349a1cb98faSBarry Smith     /   |   \
6350a1cb98faSBarry Smith    2  0 | 1  5
6351a1cb98faSBarry Smith     \   |   /
6352a1cb98faSBarry Smith      \  |  /
6353a1cb98faSBarry Smith       \ | /
6354a1cb98faSBarry Smith         3
6355a1cb98faSBarry Smith .ve
6356a1cb98faSBarry Smith   Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()`
6357939f6067SMatthew G. Knepley 
63581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
6359939f6067SMatthew G. Knepley @*/
6360d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[])
6361d71ae5a4SJacob Faibussowitsch {
63629298eaa6SMatthew G Knepley   Vec          coordinates;
63639298eaa6SMatthew G Knepley   PetscSection coordSection;
63649298eaa6SMatthew G Knepley   PetscScalar *coords;
6365811e8653SToby Isaac   PetscInt     coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off;
63669298eaa6SMatthew G Knepley 
63679298eaa6SMatthew G Knepley   PetscFunctionBegin;
63689566063dSJacob Faibussowitsch   PetscCall(DMGetDimension(dm, &dim));
63699566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateDim(dm, &dimEmbed));
637063a3b9bcSJacob Faibussowitsch   PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim);
63719298eaa6SMatthew G Knepley   for (d = 0; d <= depth; ++d) pEnd += numPoints[d];
63729566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(dm, pStart, pEnd));
63739298eaa6SMatthew G Knepley   for (p = pStart; p < pEnd; ++p) {
63749566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart]));
6375ad540459SPierre Jolivet     if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart;
637697e052ccSToby Isaac   }
63771dca8a05SBarry Smith   PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]);
63789566063dSJacob Faibussowitsch   PetscCall(DMSetUp(dm)); /* Allocate space for cones */
63799298eaa6SMatthew G Knepley   for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) {
63809566063dSJacob Faibussowitsch     PetscCall(DMPlexSetCone(dm, p, &cones[off]));
63819566063dSJacob Faibussowitsch     PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off]));
63829298eaa6SMatthew G Knepley   }
63839566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(dm));
63849566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(dm));
63859298eaa6SMatthew G Knepley   /* Build coordinates */
63869566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(dm, &coordSection));
63879566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
63889566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
63899566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0]));
63909298eaa6SMatthew G Knepley   for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) {
63919566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
63929566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
63939298eaa6SMatthew G Knepley   }
63949566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
63959566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
63969566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
63979566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
63989566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
63999566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, dimEmbed));
64009566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
64019318fe57SMatthew G. Knepley   if (vertexCoords) {
64029566063dSJacob Faibussowitsch     PetscCall(VecGetArray(coordinates, &coords));
64039298eaa6SMatthew G Knepley     for (v = 0; v < numPoints[0]; ++v) {
64049298eaa6SMatthew G Knepley       PetscInt off;
64059298eaa6SMatthew G Knepley 
64069566063dSJacob Faibussowitsch       PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off));
6407ad540459SPierre Jolivet       for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d];
64089298eaa6SMatthew G Knepley     }
64099318fe57SMatthew G. Knepley   }
64109566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
64119566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(dm, coordinates));
64129566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
64133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
64149298eaa6SMatthew G Knepley }
64158415267dSToby Isaac 
6416a4e35b19SJacob Faibussowitsch /*
6417a1cb98faSBarry Smith   DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file.
6418a1cb98faSBarry Smith 
6419a1cb98faSBarry Smith   Collective
64208ca92349SMatthew G. Knepley 
64218ca92349SMatthew G. Knepley + comm        - The MPI communicator
64228ca92349SMatthew G. Knepley . filename    - Name of the .dat file
64238ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh
64248ca92349SMatthew G. Knepley 
64258ca92349SMatthew G. Knepley   Output Parameter:
6426a1cb98faSBarry Smith . dm  - The `DM` object representing the mesh
64278ca92349SMatthew G. Knepley 
64288ca92349SMatthew G. Knepley   Level: beginner
64298ca92349SMatthew G. Knepley 
6430a1cb98faSBarry Smith   Note:
6431a1cb98faSBarry Smith   The format is the simplest possible:
6432a1cb98faSBarry Smith .vb
6433d0812dedSMatthew G. Knepley   dim Ne Nv Nc Nl
6434d0812dedSMatthew G. Knepley   v_1 v_2 ... v_Nc
6435d0812dedSMatthew G. Knepley   ...
6436d0812dedSMatthew G. Knepley   x y z marker_1 ... marker_Nl
6437a1cb98faSBarry Smith .ve
6438a1cb98faSBarry Smith 
6439a1cb98faSBarry Smith   Developer Note:
6440a1cb98faSBarry Smith   Should use a `PetscViewer` not a filename
6441a1cb98faSBarry Smith 
64426afe31f6SMartin Diehl .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()`
6443a4e35b19SJacob Faibussowitsch */
6444ff6a9541SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
6445d71ae5a4SJacob Faibussowitsch {
64468ca92349SMatthew G. Knepley   DMLabel      marker;
64478ca92349SMatthew G. Knepley   PetscViewer  viewer;
64488ca92349SMatthew G. Knepley   Vec          coordinates;
64498ca92349SMatthew G. Knepley   PetscSection coordSection;
64508ca92349SMatthew G. Knepley   PetscScalar *coords;
64518ca92349SMatthew G. Knepley   char         line[PETSC_MAX_PATH_LEN];
6452d0812dedSMatthew G. Knepley   PetscInt     cdim, coordSize, v, c, d;
64538ca92349SMatthew G. Knepley   PetscMPIInt  rank;
6454d0812dedSMatthew G. Knepley   int          snum, dim, Nv, Nc, Ncn, Nl;
64558ca92349SMatthew G. Knepley 
64568ca92349SMatthew G. Knepley   PetscFunctionBegin;
64579566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
64589566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, &viewer));
64599566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
64609566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
64619566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(viewer, filename));
6462dd400576SPatrick Sanan   if (rank == 0) {
6463d0812dedSMatthew G. Knepley     PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING));
6464d0812dedSMatthew G. Knepley     snum = sscanf(line, "%d %d %d %d %d", &dim, &Nc, &Nv, &Ncn, &Nl);
6465d0812dedSMatthew G. Knepley     PetscCheck(snum == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
646625ce1634SJed Brown   } else {
6467f8d5e320SMatthew G. Knepley     Nc = Nv = Ncn = Nl = 0;
64688ca92349SMatthew G. Knepley   }
6469d0812dedSMatthew G. Knepley   PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm));
6470835f2295SStefano Zampini   cdim = dim;
64719566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
64729566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
64739566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv));
6474835f2295SStefano Zampini   PetscCall(DMSetDimension(*dm, dim));
64759566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinateDim(*dm, cdim));
64768ca92349SMatthew G. Knepley   /* Read topology */
6477dd400576SPatrick Sanan   if (rank == 0) {
6478f8d5e320SMatthew G. Knepley     char     format[PETSC_MAX_PATH_LEN];
6479f8d5e320SMatthew G. Knepley     PetscInt cone[8];
64808ca92349SMatthew G. Knepley     int      vbuf[8], v;
64818ca92349SMatthew G. Knepley 
64829371c9d4SSatish Balay     for (c = 0; c < Ncn; ++c) {
64839371c9d4SSatish Balay       format[c * 3 + 0] = '%';
64849371c9d4SSatish Balay       format[c * 3 + 1] = 'd';
64859371c9d4SSatish Balay       format[c * 3 + 2] = ' ';
64869371c9d4SSatish Balay     }
6487f8d5e320SMatthew G. Knepley     format[Ncn * 3 - 1] = '\0';
64889566063dSJacob Faibussowitsch     for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn));
64899566063dSJacob Faibussowitsch     PetscCall(DMSetUp(*dm));
64908ca92349SMatthew G. Knepley     for (c = 0; c < Nc; ++c) {
64919566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING));
6492f8d5e320SMatthew G. Knepley       switch (Ncn) {
6493d71ae5a4SJacob Faibussowitsch       case 2:
6494d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1]);
6495d71ae5a4SJacob Faibussowitsch         break;
6496d71ae5a4SJacob Faibussowitsch       case 3:
6497d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]);
6498d71ae5a4SJacob Faibussowitsch         break;
6499d71ae5a4SJacob Faibussowitsch       case 4:
6500d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]);
6501d71ae5a4SJacob Faibussowitsch         break;
6502d71ae5a4SJacob Faibussowitsch       case 6:
6503d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]);
6504d71ae5a4SJacob Faibussowitsch         break;
6505d71ae5a4SJacob Faibussowitsch       case 8:
6506d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]);
6507d71ae5a4SJacob Faibussowitsch         break;
6508d71ae5a4SJacob Faibussowitsch       default:
6509d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn);
6510f8d5e320SMatthew G. Knepley       }
651108401ef6SPierre Jolivet       PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
6512f8d5e320SMatthew G. Knepley       for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc;
65138ca92349SMatthew G. Knepley       /* Hexahedra are inverted */
6514f8d5e320SMatthew G. Knepley       if (Ncn == 8) {
65158ca92349SMatthew G. Knepley         PetscInt tmp = cone[1];
65168ca92349SMatthew G. Knepley         cone[1]      = cone[3];
65178ca92349SMatthew G. Knepley         cone[3]      = tmp;
65188ca92349SMatthew G. Knepley       }
65199566063dSJacob Faibussowitsch       PetscCall(DMPlexSetCone(*dm, c, cone));
65208ca92349SMatthew G. Knepley     }
65218ca92349SMatthew G. Knepley   }
65229566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
65239566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
65248ca92349SMatthew G. Knepley   /* Read coordinates */
65259566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
65269566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
65279566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim));
65289566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv));
65298ca92349SMatthew G. Knepley   for (v = Nc; v < Nc + Nv; ++v) {
65309566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, cdim));
65319566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim));
65328ca92349SMatthew G. Knepley   }
65339566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
65349566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
65359566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
65369566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
65379566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
65389566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, cdim));
65399566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates, VECSTANDARD));
65409566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
6541dd400576SPatrick Sanan   if (rank == 0) {
6542f8d5e320SMatthew G. Knepley     char   format[PETSC_MAX_PATH_LEN];
65438ca92349SMatthew G. Knepley     double x[3];
6544f8d5e320SMatthew G. Knepley     int    l, val[3];
65458ca92349SMatthew G. Knepley 
6546f8d5e320SMatthew G. Knepley     if (Nl) {
65479371c9d4SSatish Balay       for (l = 0; l < Nl; ++l) {
65489371c9d4SSatish Balay         format[l * 3 + 0] = '%';
65499371c9d4SSatish Balay         format[l * 3 + 1] = 'd';
65509371c9d4SSatish Balay         format[l * 3 + 2] = ' ';
65519371c9d4SSatish Balay       }
6552f8d5e320SMatthew G. Knepley       format[Nl * 3 - 1] = '\0';
65539566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
65549566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &marker));
6555f8d5e320SMatthew G. Knepley     }
65568ca92349SMatthew G. Knepley     for (v = 0; v < Nv; ++v) {
65579566063dSJacob Faibussowitsch       PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING));
6558f8d5e320SMatthew G. Knepley       snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]);
655908401ef6SPierre Jolivet       PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
6560f8d5e320SMatthew G. Knepley       switch (Nl) {
6561d71ae5a4SJacob Faibussowitsch       case 0:
6562d71ae5a4SJacob Faibussowitsch         snum = 0;
6563d71ae5a4SJacob Faibussowitsch         break;
6564d71ae5a4SJacob Faibussowitsch       case 1:
6565d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0]);
6566d71ae5a4SJacob Faibussowitsch         break;
6567d71ae5a4SJacob Faibussowitsch       case 2:
6568d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1]);
6569d71ae5a4SJacob Faibussowitsch         break;
6570d71ae5a4SJacob Faibussowitsch       case 3:
6571d71ae5a4SJacob Faibussowitsch         snum = sscanf(line, format, &val[0], &val[1], &val[2]);
6572d71ae5a4SJacob Faibussowitsch         break;
6573d71ae5a4SJacob Faibussowitsch       default:
6574d71ae5a4SJacob Faibussowitsch         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl);
6575f8d5e320SMatthew G. Knepley       }
657608401ef6SPierre Jolivet       PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line);
65778ca92349SMatthew G. Knepley       for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d];
65789566063dSJacob Faibussowitsch       for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l]));
65798ca92349SMatthew G. Knepley     }
65808ca92349SMatthew G. Knepley   }
65819566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
65829566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
65839566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
65849566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&viewer));
65858ca92349SMatthew G. Knepley   if (interpolate) {
65868ca92349SMatthew G. Knepley     DM      idm;
65878ca92349SMatthew G. Knepley     DMLabel bdlabel;
65888ca92349SMatthew G. Knepley 
65899566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
65909566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
65918ca92349SMatthew G. Knepley     *dm = idm;
65928ca92349SMatthew G. Knepley 
6593f8d5e320SMatthew G. Knepley     if (!Nl) {
65949566063dSJacob Faibussowitsch       PetscCall(DMCreateLabel(*dm, "marker"));
65959566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(*dm, "marker", &bdlabel));
65969566063dSJacob Faibussowitsch       PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel));
65979566063dSJacob Faibussowitsch       PetscCall(DMPlexLabelComplete(*dm, bdlabel));
65988ca92349SMatthew G. Knepley     }
6599f8d5e320SMatthew G. Knepley   }
66003ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
66018ca92349SMatthew G. Knepley }
66028ca92349SMatthew G. Knepley 
6603cc4c1da9SBarry Smith /*@
6604a1cb98faSBarry Smith   DMPlexCreateFromFile - This takes a filename and produces a `DM`
6605a1cb98faSBarry Smith 
6606a1cb98faSBarry Smith   Collective
6607ca522641SMatthew G. Knepley 
6608ca522641SMatthew G. Knepley   Input Parameters:
6609ca522641SMatthew G. Knepley + comm        - The communicator
6610ca522641SMatthew G. Knepley . filename    - A file name
6611a1cb98faSBarry Smith . plexname    - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats
6612ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces)
6613ca522641SMatthew G. Knepley 
6614ca522641SMatthew G. Knepley   Output Parameter:
6615a1cb98faSBarry Smith . dm - The `DM`
6616ca522641SMatthew G. Knepley 
6617a1cb98faSBarry Smith   Options Database Key:
6618a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5
661902ef0d99SVaclav Hapla 
662037fdd005SBarry Smith   Use `-dm_plex_create_ prefix` to pass options to the internal `PetscViewer`, e.g.
6621bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective
6622bca97951SVaclav Hapla 
6623ca522641SMatthew G. Knepley   Level: beginner
6624ca522641SMatthew G. Knepley 
6625a1cb98faSBarry Smith   Notes:
6626a1cb98faSBarry Smith   Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX`
6627a1cb98faSBarry Smith   meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()`
6628a1cb98faSBarry Smith   before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object.
6629a1cb98faSBarry Smith   The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally
6630a1cb98faSBarry Smith   calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats.
6631a1cb98faSBarry Smith 
66321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()`
6633ca522641SMatthew G. Knepley @*/
6634d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm)
6635d71ae5a4SJacob Faibussowitsch {
6636ef3a5affSJacob Faibussowitsch   const char  extGmsh[]      = ".msh";
6637ef3a5affSJacob Faibussowitsch   const char  extGmsh2[]     = ".msh2";
6638ef3a5affSJacob Faibussowitsch   const char  extGmsh4[]     = ".msh4";
6639ef3a5affSJacob Faibussowitsch   const char  extCGNS[]      = ".cgns";
6640ef3a5affSJacob Faibussowitsch   const char  extExodus[]    = ".exo";
6641ef3a5affSJacob Faibussowitsch   const char  extExodus_e[]  = ".e";
6642ef3a5affSJacob Faibussowitsch   const char  extGenesis[]   = ".gen";
6643ef3a5affSJacob Faibussowitsch   const char  extFluent[]    = ".cas";
6644ef3a5affSJacob Faibussowitsch   const char  extHDF5[]      = ".h5";
66456f2c871aSStefano Zampini   const char  extXDMFHDF5[]  = ".xdmf.h5";
6646ef3a5affSJacob Faibussowitsch   const char  extPLY[]       = ".ply";
66475552b385SBrandon   const char  extEGADSlite[] = ".egadslite";
6648ef3a5affSJacob Faibussowitsch   const char  extEGADS[]     = ".egads";
6649ef3a5affSJacob Faibussowitsch   const char  extIGES[]      = ".igs";
66505552b385SBrandon   const char  extIGES2[]     = ".iges";
6651ef3a5affSJacob Faibussowitsch   const char  extSTEP[]      = ".stp";
66525552b385SBrandon   const char  extSTEP2[]     = ".step";
66535552b385SBrandon   const char  extBREP[]      = ".brep";
6654ef3a5affSJacob Faibussowitsch   const char  extCV[]        = ".dat";
6655ca522641SMatthew G. Knepley   size_t      len;
66565552b385SBrandon   PetscBool   isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isPLY, isEGADSlite, isEGADS, isIGES, isIGES2, isSTEP, isSTEP2, isBREP, isCV, isXDMFHDF5;
6657ca522641SMatthew G. Knepley   PetscMPIInt rank;
6658ca522641SMatthew G. Knepley 
6659ca522641SMatthew G. Knepley   PetscFunctionBegin;
66604f572ea9SToby Isaac   PetscAssertPointer(filename, 2);
66614f572ea9SToby Isaac   if (plexname) PetscAssertPointer(plexname, 3);
66624f572ea9SToby Isaac   PetscAssertPointer(dm, 5);
66639566063dSJacob Faibussowitsch   PetscCall(DMInitializePackage());
66649566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0));
66659566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
66669566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(filename, &len));
666728b400f6SJacob Faibussowitsch   PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path");
6668ef3a5affSJacob Faibussowitsch 
66699371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \
66709371c9d4SSatish Balay   do { \
6671274aaeaaSJacob Faibussowitsch     PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \
6672274aaeaaSJacob Faibussowitsch     /* don't count the null-terminator at the end */ \
6673274aaeaaSJacob Faibussowitsch     const size_t ext_len = sizeof(extension__) - 1; \
6674274aaeaaSJacob Faibussowitsch     if (len < ext_len) { \
6675ef3a5affSJacob Faibussowitsch       is_extension__ = PETSC_FALSE; \
6676ef3a5affSJacob Faibussowitsch     } else { \
6677274aaeaaSJacob Faibussowitsch       PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \
6678ef3a5affSJacob Faibussowitsch     } \
6679ef3a5affSJacob Faibussowitsch   } while (0)
6680ef3a5affSJacob Faibussowitsch 
6681ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh, isGmsh);
6682ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh2, isGmsh2);
6683ef3a5affSJacob Faibussowitsch   CheckExtension(extGmsh4, isGmsh4);
6684ef3a5affSJacob Faibussowitsch   CheckExtension(extCGNS, isCGNS);
6685ef3a5affSJacob Faibussowitsch   CheckExtension(extExodus, isExodus);
6686ef3a5affSJacob Faibussowitsch   if (!isExodus) CheckExtension(extExodus_e, isExodus);
6687ef3a5affSJacob Faibussowitsch   CheckExtension(extGenesis, isGenesis);
6688ef3a5affSJacob Faibussowitsch   CheckExtension(extFluent, isFluent);
6689ef3a5affSJacob Faibussowitsch   CheckExtension(extHDF5, isHDF5);
6690ef3a5affSJacob Faibussowitsch   CheckExtension(extPLY, isPLY);
66915552b385SBrandon   CheckExtension(extEGADSlite, isEGADSlite);
6692ef3a5affSJacob Faibussowitsch   CheckExtension(extEGADS, isEGADS);
6693ef3a5affSJacob Faibussowitsch   CheckExtension(extIGES, isIGES);
66945552b385SBrandon   CheckExtension(extIGES2, isIGES2);
6695ef3a5affSJacob Faibussowitsch   CheckExtension(extSTEP, isSTEP);
66965552b385SBrandon   CheckExtension(extSTEP2, isSTEP2);
66975552b385SBrandon   CheckExtension(extBREP, isBREP);
6698ef3a5affSJacob Faibussowitsch   CheckExtension(extCV, isCV);
66996f2c871aSStefano Zampini   CheckExtension(extXDMFHDF5, isXDMFHDF5);
6700ef3a5affSJacob Faibussowitsch 
6701ef3a5affSJacob Faibussowitsch #undef CheckExtension
6702ef3a5affSJacob Faibussowitsch 
6703de78e4feSLisandro Dalcin   if (isGmsh || isGmsh2 || isGmsh4) {
67049566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm));
6705ca522641SMatthew G. Knepley   } else if (isCGNS) {
67069566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm));
670790c68965SMatthew G. Knepley   } else if (isExodus || isGenesis) {
67089566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm));
67092f0bd6dcSMichael Lange   } else if (isFluent) {
67109566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm));
6711cc2f8f65SMatthew G. Knepley   } else if (isHDF5) {
6712cc2f8f65SMatthew G. Knepley     PetscViewer viewer;
6713cc2f8f65SMatthew G. Knepley 
671443b242b4SVaclav 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 */
67156f2c871aSStefano Zampini     PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &isXDMFHDF5, NULL));
67169566063dSJacob Faibussowitsch     PetscCall(PetscViewerCreate(comm, &viewer));
67179566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5));
67189566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_"));
67199566063dSJacob Faibussowitsch     PetscCall(PetscViewerSetFromOptions(viewer));
67209566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ));
67219566063dSJacob Faibussowitsch     PetscCall(PetscViewerFileSetName(viewer, filename));
6722cd7e8a5eSksagiyam 
67239566063dSJacob Faibussowitsch     PetscCall(DMCreate(comm, dm));
6724f4f49eeaSPierre Jolivet     PetscCall(PetscObjectSetName((PetscObject)*dm, plexname));
67259566063dSJacob Faibussowitsch     PetscCall(DMSetType(*dm, DMPLEX));
67266f2c871aSStefano Zampini     if (isXDMFHDF5) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF));
67279566063dSJacob Faibussowitsch     PetscCall(DMLoad(*dm, viewer));
67286f2c871aSStefano Zampini     if (isXDMFHDF5) PetscCall(PetscViewerPopFormat(viewer));
67299566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&viewer));
67305fd9971aSMatthew G. Knepley 
67315fd9971aSMatthew G. Knepley     if (interpolate) {
67325fd9971aSMatthew G. Knepley       DM idm;
67335fd9971aSMatthew G. Knepley 
67349566063dSJacob Faibussowitsch       PetscCall(DMPlexInterpolate(*dm, &idm));
67359566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
67365fd9971aSMatthew G. Knepley       *dm = idm;
67375fd9971aSMatthew G. Knepley     }
6738f2801cd6SMatthew G. Knepley   } else if (isPLY) {
67399566063dSJacob Faibussowitsch     PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm));
67405552b385SBrandon   } else if (isEGADSlite || isEGADS || isIGES || isIGES2 || isSTEP || isSTEP2 || isBREP) {
67415552b385SBrandon     PetscCall(DMPlexCreateGeomFromFile(comm, filename, dm, isEGADSlite));
67425552b385SBrandon 
67437bee2925SMatthew Knepley     if (!interpolate) {
67447bee2925SMatthew Knepley       DM udm;
67457bee2925SMatthew Knepley 
67469566063dSJacob Faibussowitsch       PetscCall(DMPlexUninterpolate(*dm, &udm));
67479566063dSJacob Faibussowitsch       PetscCall(DMDestroy(dm));
67487bee2925SMatthew Knepley       *dm = udm;
67497bee2925SMatthew Knepley     }
67508ca92349SMatthew G. Knepley   } else if (isCV) {
67519566063dSJacob Faibussowitsch     PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm));
675298921bdaSJacob Faibussowitsch   } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename);
67539566063dSJacob Faibussowitsch   PetscCall(PetscStrlen(plexname, &len));
6754f4f49eeaSPierre Jolivet   if (len) PetscCall(PetscObjectSetName((PetscObject)*dm, plexname));
67559566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0));
67563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6757ca522641SMatthew G. Knepley }
675812b8a6daSStefano Zampini 
6759cc4c1da9SBarry Smith /*@
67609f6c5813SMatthew 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.
67619f6c5813SMatthew G. Knepley 
67620528010dSStefano Zampini   Input Parameters:
67630528010dSStefano Zampini + tr     - The `DMPlexTransform`
67640528010dSStefano Zampini - prefix - An options prefix, or NULL
67659f6c5813SMatthew G. Knepley 
67669f6c5813SMatthew G. Knepley   Output Parameter:
67679f6c5813SMatthew G. Knepley . dm - The `DM`
67689f6c5813SMatthew G. Knepley 
67699f6c5813SMatthew G. Knepley   Level: beginner
67709f6c5813SMatthew G. Knepley 
677120f4b53cSBarry Smith   Notes:
677220f4b53cSBarry 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.
677320f4b53cSBarry Smith 
67749f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`
67759f6c5813SMatthew G. Knepley @*/
67760528010dSStefano Zampini PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, const char prefix[], DM *dm)
67779f6c5813SMatthew G. Knepley {
67780528010dSStefano Zampini   DM           bdm, bcdm, cdm;
67790528010dSStefano Zampini   Vec          coordinates, coordinatesNew;
67800528010dSStefano Zampini   PetscSection cs;
6781817b2c36SMatthew G. Knepley   PetscInt     cdim, Nl;
67829f6c5813SMatthew G. Knepley 
67839f6c5813SMatthew G. Knepley   PetscFunctionBegin;
67849f6c5813SMatthew G. Knepley   PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm));
67859f6c5813SMatthew G. Knepley   PetscCall(DMSetType(*dm, DMPLEX));
67860528010dSStefano Zampini   ((DM_Plex *)(*dm)->data)->interpolated = DMPLEX_INTERPOLATED_FULL;
67870528010dSStefano Zampini   // Handle coordinates
67880528010dSStefano Zampini   PetscCall(DMPlexTransformGetDM(tr, &bdm));
6789817b2c36SMatthew G. Knepley   PetscCall(DMPlexTransformSetDimensions(tr, bdm, *dm));
6790817b2c36SMatthew G. Knepley   PetscCall(DMGetCoordinateDim(*dm, &cdim));
67910528010dSStefano Zampini   PetscCall(DMGetCoordinateDM(bdm, &bcdm));
67920528010dSStefano Zampini   PetscCall(DMGetCoordinateDM(*dm, &cdm));
67930528010dSStefano Zampini   PetscCall(DMCopyDisc(bcdm, cdm));
67940528010dSStefano Zampini   PetscCall(DMGetLocalSection(cdm, &cs));
67950528010dSStefano Zampini   PetscCall(PetscSectionSetNumFields(cs, 1));
67960528010dSStefano Zampini   PetscCall(PetscSectionSetFieldComponents(cs, 0, cdim));
67970528010dSStefano Zampini   PetscCall(DMGetCoordinatesLocal(bdm, &coordinates));
67980528010dSStefano Zampini   PetscCall(VecDuplicate(coordinates, &coordinatesNew));
67990528010dSStefano Zampini   PetscCall(VecCopy(coordinates, coordinatesNew));
68000528010dSStefano Zampini   PetscCall(DMSetCoordinatesLocal(*dm, coordinatesNew));
68010528010dSStefano Zampini   PetscCall(VecDestroy(&coordinatesNew));
68029f6c5813SMatthew G. Knepley 
68039f6c5813SMatthew G. Knepley   PetscCall(PetscObjectReference((PetscObject)tr));
68049f6c5813SMatthew G. Knepley   PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr));
68059f6c5813SMatthew G. Knepley   ((DM_Plex *)(*dm)->data)->tr = tr;
68060528010dSStefano Zampini   PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE));
68070528010dSStefano Zampini   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix));
68080528010dSStefano Zampini   PetscCall(DMSetFromOptions(*dm));
68099f6c5813SMatthew G. Knepley 
68109f6c5813SMatthew G. Knepley   PetscCall(DMGetNumLabels(bdm, &Nl));
68119f6c5813SMatthew G. Knepley   for (PetscInt l = 0; l < Nl; ++l) {
68129f6c5813SMatthew G. Knepley     DMLabel     label, labelNew;
68139f6c5813SMatthew G. Knepley     const char *lname;
68149f6c5813SMatthew G. Knepley     PetscBool   isDepth, isCellType;
68159f6c5813SMatthew G. Knepley 
68169f6c5813SMatthew G. Knepley     PetscCall(DMGetLabelName(bdm, l, &lname));
68179f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "depth", &isDepth));
68189f6c5813SMatthew G. Knepley     if (isDepth) continue;
68199f6c5813SMatthew G. Knepley     PetscCall(PetscStrcmp(lname, "celltype", &isCellType));
68209f6c5813SMatthew G. Knepley     if (isCellType) continue;
68219f6c5813SMatthew G. Knepley     PetscCall(DMCreateLabel(*dm, lname));
68229f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(bdm, lname, &label));
68239f6c5813SMatthew G. Knepley     PetscCall(DMGetLabel(*dm, lname, &labelNew));
68249f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL));
68259f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetLabel(labelNew, label));
68269f6c5813SMatthew G. Knepley     PetscCall(DMLabelEphemeralSetTransform(labelNew, tr));
68279f6c5813SMatthew G. Knepley     PetscCall(DMLabelSetUp(labelNew));
68289f6c5813SMatthew G. Knepley   }
68293ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
68309f6c5813SMatthew G. Knepley }
6831