15e2c5519SMatthew G. Knepley #include "petscsystypes.h" 2552f7358SJed Brown #define PETSCDM_DLL 3af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 4cc4c1da9SBarry Smith #include <petsc/private/hashseti.h> 50c312b8eSJed Brown #include <petscsf.h> 6cc4c1da9SBarry Smith #include <petscdmplextransform.h> /*I "petscdmplextransform.h" I*/ 79f6c5813SMatthew G. Knepley #include <petscdmlabelephemeral.h> 8b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h> 9b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h> 10552f7358SJed Brown 11d0812dedSMatthew G. Knepley #ifdef PETSC_HAVE_UNISTD_H 12d0812dedSMatthew G. Knepley #include <unistd.h> 13d0812dedSMatthew G. Knepley #endif 14d0812dedSMatthew G. Knepley #include <errno.h> 15d0812dedSMatthew G. Knepley 16708be2fdSJed Brown PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_CreateFromOptions, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList; 1758cd63d5SVaclav Hapla 189318fe57SMatthew G. Knepley /* External function declarations here */ 199318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm); 209318fe57SMatthew G. Knepley 21*5552b385SBrandon PETSC_EXTERN PetscErrorCode DMPlexCheckEGADS_Private(DM dm) 22*5552b385SBrandon { 23*5552b385SBrandon PetscObject modelObj; 24*5552b385SBrandon 25*5552b385SBrandon PetscFunctionBegin; 26*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", &modelObj)); 27*5552b385SBrandon PetscCheck(modelObj, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Input DM must have attached EGADS Geometry Model"); 28*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 29*5552b385SBrandon } 30*5552b385SBrandon 31*5552b385SBrandon static PetscErrorCode DMPlexCopyContext_Private(DM dmin, const char name[], DM dmout) 32*5552b385SBrandon { 33*5552b385SBrandon PetscObject obj; 34*5552b385SBrandon 35*5552b385SBrandon PetscFunctionBegin; 36*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmin, name, &obj)); 37*5552b385SBrandon if (obj) PetscCall(PetscObjectCompose((PetscObject)dmout, name, obj)); 38*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 39*5552b385SBrandon } 40*5552b385SBrandon 41*5552b385SBrandon static PetscErrorCode DMPlexSwapContext_Private(DM dmA, const char name[], DM dmB) 42*5552b385SBrandon { 43*5552b385SBrandon PetscObject objA, objB; 44*5552b385SBrandon 45*5552b385SBrandon PetscFunctionBegin; 46*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmA, name, &objA)); 47*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmB, name, &objB)); 48*5552b385SBrandon PetscCall(PetscObjectReference(objA)); 49*5552b385SBrandon PetscCall(PetscObjectReference(objB)); 50*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dmA, name, objB)); 51*5552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dmB, name, objA)); 52*5552b385SBrandon PetscCall(PetscObjectDereference(objA)); 53*5552b385SBrandon PetscCall(PetscObjectDereference(objB)); 54*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 55*5552b385SBrandon } 56*5552b385SBrandon 57*5552b385SBrandon PetscErrorCode DMPlexCopyEGADSInfo_Internal(DM dmin, DM dmout) 58*5552b385SBrandon { 59*5552b385SBrandon PetscFunctionBegin; 60*5552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Model", dmout)); 61*5552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Context", dmout)); 62*5552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Model", dmout)); 63*5552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Context", dmout)); 64*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 65*5552b385SBrandon } 66*5552b385SBrandon 67*5552b385SBrandon static PetscErrorCode DMPlexSwapEGADSInfo_Private(DM dmA, DM dmB) 68*5552b385SBrandon { 69*5552b385SBrandon PetscFunctionBegin; 70*5552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Model", dmB)); 71*5552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Context", dmB)); 72*5552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Model", dmB)); 73*5552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Context", dmB)); 74*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 75*5552b385SBrandon } 76*5552b385SBrandon 77e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */ 78d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout) 79d71ae5a4SJacob Faibussowitsch { 804fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 8112a88998SMatthew G. Knepley VecType vecType; 8212a88998SMatthew G. Knepley MatType matType; 83129f447cSJames Wright PetscBool dist, useCeed, balance_partition; 84adc21957SMatthew G. Knepley DMReorderDefaultFlag reorder; 85e600fa54SMatthew G. Knepley 86e600fa54SMatthew G. Knepley PetscFunctionBegin; 87835f2295SStefano Zampini if (dmin == dmout) PetscFunctionReturn(PETSC_SUCCESS); 8812a88998SMatthew G. Knepley PetscCall(DMGetVecType(dmin, &vecType)); 8912a88998SMatthew G. Knepley PetscCall(DMSetVecType(dmout, vecType)); 9012a88998SMatthew G. Knepley PetscCall(DMGetMatType(dmin, &matType)); 9112a88998SMatthew G. Knepley PetscCall(DMSetMatType(dmout, matType)); 92e600fa54SMatthew G. Knepley if (copyPeriodicity) { 934fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L)); 944fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L)); 953d0e8ed9SDavid Salac PetscCall(DMLocalizeCoordinates(dmout)); 96e600fa54SMatthew G. Knepley } 979566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dmin, &dist)); 989566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dmout, dist)); 996bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dmin, &reorder)); 1006bc1bd01Sksagiyam PetscCall(DMPlexReorderSetDefault(dmout, reorder)); 1015962854dSMatthew G. Knepley PetscCall(DMPlexGetUseCeed(dmin, &useCeed)); 1025962854dSMatthew G. Knepley PetscCall(DMPlexSetUseCeed(dmout, useCeed)); 103129f447cSJames Wright PetscCall(DMPlexGetPartitionBalance(dmin, &balance_partition)); 104129f447cSJames Wright PetscCall(DMPlexSetPartitionBalance(dmout, balance_partition)); 105e600fa54SMatthew G. Knepley ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation; 1065962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printSetValues = ((DM_Plex *)dmin->data)->printSetValues; 1075962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printFEM = ((DM_Plex *)dmin->data)->printFEM; 1085962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printFVM = ((DM_Plex *)dmin->data)->printFVM; 1095962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printL2 = ((DM_Plex *)dmin->data)->printL2; 1105962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printLocate = ((DM_Plex *)dmin->data)->printLocate; 111a77a5016SMatthew G. Knepley ((DM_Plex *)dmout->data)->printProject = ((DM_Plex *)dmin->data)->printProject; 1125962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printTol = ((DM_Plex *)dmin->data)->printTol; 1131baa6e33SBarry Smith if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0)); 114*5552b385SBrandon PetscCall(DMPlexCopyEGADSInfo_Internal(dmin, dmout)); 1153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 116e600fa54SMatthew G. Knepley } 117e600fa54SMatthew G. Knepley 1189318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 1199318fe57SMatthew G. Knepley - Share the DM_Plex structure 1209318fe57SMatthew G. Knepley - Share the coordinates 1219318fe57SMatthew G. Knepley - Share the SF 1229318fe57SMatthew G. Knepley */ 123d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm) 124d71ae5a4SJacob Faibussowitsch { 1259318fe57SMatthew G. Knepley PetscSF sf; 1269318fe57SMatthew G. Knepley DM dmNew = *ndm, coordDM, coarseDM; 1279318fe57SMatthew G. Knepley Vec coords; 1284fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 1299318fe57SMatthew G. Knepley PetscInt dim, cdim; 130e535cce4SJames Wright PetscBool use_natural; 1319318fe57SMatthew G. Knepley 1329318fe57SMatthew G. Knepley PetscFunctionBegin; 1339318fe57SMatthew G. Knepley if (dm == dmNew) { 1349566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 1353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1369318fe57SMatthew G. Knepley } 1379318fe57SMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 138d0812dedSMatthew G. Knepley if (!dm->hdr.name) { 139d0812dedSMatthew G. Knepley const char *name; 140d0812dedSMatthew G. Knepley 141d0812dedSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)*ndm, &name)); 142d0812dedSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, name)); 143d0812dedSMatthew G. Knepley } 1449566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dmNew, &dim)); 1459566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 1469566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmNew, &cdim)); 1479566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 1489566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmNew, &sf)); 1499566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sf)); 1509566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmNew, &coordDM)); 1519566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmNew, &coords)); 1529566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dm, coordDM)); 1539566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 1546858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM)); 1556858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords)); 1566858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dm, coordDM)); 1576858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 1589318fe57SMatthew G. Knepley /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */ 1596858538eSMatthew G. Knepley PetscCall(DMFieldDestroy(&dm->coordinates[0].field)); 1606858538eSMatthew G. Knepley dm->coordinates[0].field = dmNew->coordinates[0].field; 16161a622f3SMatthew G. Knepley ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc; 1624fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L)); 1634fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 164e535cce4SJames Wright PetscCall(DMGetNaturalSF(dmNew, &sf)); 165e535cce4SJames Wright PetscCall(DMSetNaturalSF(dm, sf)); 166e535cce4SJames Wright PetscCall(DMGetUseNatural(dmNew, &use_natural)); 167e535cce4SJames Wright PetscCall(DMSetUseNatural(dm, use_natural)); 1689566063dSJacob Faibussowitsch PetscCall(DMDestroy_Plex(dm)); 1699566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 1709318fe57SMatthew G. Knepley dm->data = dmNew->data; 1719318fe57SMatthew G. Knepley ((DM_Plex *)dmNew->data)->refct++; 1721fca310dSJames Wright { 1731fca310dSJames Wright PetscInt num_face_sfs; 1741fca310dSJames Wright const PetscSF *sfs; 1751fca310dSJames Wright PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &sfs)); 1761fca310dSJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(dm, num_face_sfs, (PetscSF *)sfs)); // for the compose function effect on dm 1771fca310dSJames Wright } 1789566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 1799566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 1809566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmNew, &coarseDM)); 1819566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 182*5552b385SBrandon PetscCall(DMPlexCopyEGADSInfo_Internal(dmNew, dm)); 1839566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 1843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1859318fe57SMatthew G. Knepley } 1869318fe57SMatthew G. Knepley 1879318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew 1889318fe57SMatthew G. Knepley - Swap the DM_Plex structure 1899318fe57SMatthew G. Knepley - Swap the coordinates 1909318fe57SMatthew G. Knepley - Swap the point PetscSF 1919318fe57SMatthew G. Knepley */ 192d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) 193d71ae5a4SJacob Faibussowitsch { 1949318fe57SMatthew G. Knepley DM coordDMA, coordDMB; 1959318fe57SMatthew G. Knepley Vec coordsA, coordsB; 1969318fe57SMatthew G. Knepley PetscSF sfA, sfB; 1979318fe57SMatthew G. Knepley DMField fieldTmp; 1989318fe57SMatthew G. Knepley void *tmp; 1999318fe57SMatthew G. Knepley DMLabelLink listTmp; 2009318fe57SMatthew G. Knepley DMLabel depthTmp; 2019318fe57SMatthew G. Knepley PetscInt tmpI; 2029318fe57SMatthew G. Knepley 2039318fe57SMatthew G. Knepley PetscFunctionBegin; 2043ba16761SJacob Faibussowitsch if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS); 2059566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmA, &sfA)); 2069566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmB, &sfB)); 2079566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sfA)); 2089566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmA, sfB)); 2099566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmB, sfA)); 2109566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)sfA)); 2119318fe57SMatthew G. Knepley 2129566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &coordDMA)); 2139566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &coordDMB)); 2149566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordDMA)); 2159566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmA, coordDMB)); 2169566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmB, coordDMA)); 2179566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 2189318fe57SMatthew G. Knepley 2199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordsA)); 2209566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmB, &coordsB)); 2219566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordsA)); 2229566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmA, coordsB)); 2239566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordsA)); 2249566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordsA)); 2259318fe57SMatthew G. Knepley 2266858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA)); 2276858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB)); 2286858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordDMA)); 2296858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmA, coordDMB)); 2306858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmB, coordDMA)); 2316858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 2326858538eSMatthew G. Knepley 2336858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA)); 2346858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB)); 2356858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordsA)); 2366858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB)); 2376858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA)); 2386858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordsA)); 2396858538eSMatthew G. Knepley 240*5552b385SBrandon PetscCall(DMPlexSwapEGADSInfo_Private(dmA, dmB)); 241*5552b385SBrandon 2426858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[0].field; 2436858538eSMatthew G. Knepley dmA->coordinates[0].field = dmB->coordinates[0].field; 2446858538eSMatthew G. Knepley dmB->coordinates[0].field = fieldTmp; 2456858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[1].field; 2466858538eSMatthew G. Knepley dmA->coordinates[1].field = dmB->coordinates[1].field; 2476858538eSMatthew G. Knepley dmB->coordinates[1].field = fieldTmp; 2489318fe57SMatthew G. Knepley tmp = dmA->data; 2499318fe57SMatthew G. Knepley dmA->data = dmB->data; 2509318fe57SMatthew G. Knepley dmB->data = tmp; 2519318fe57SMatthew G. Knepley listTmp = dmA->labels; 2529318fe57SMatthew G. Knepley dmA->labels = dmB->labels; 2539318fe57SMatthew G. Knepley dmB->labels = listTmp; 2549318fe57SMatthew G. Knepley depthTmp = dmA->depthLabel; 2559318fe57SMatthew G. Knepley dmA->depthLabel = dmB->depthLabel; 2569318fe57SMatthew G. Knepley dmB->depthLabel = depthTmp; 2579318fe57SMatthew G. Knepley depthTmp = dmA->celltypeLabel; 2589318fe57SMatthew G. Knepley dmA->celltypeLabel = dmB->celltypeLabel; 2599318fe57SMatthew G. Knepley dmB->celltypeLabel = depthTmp; 2609318fe57SMatthew G. Knepley tmpI = dmA->levelup; 2619318fe57SMatthew G. Knepley dmA->levelup = dmB->levelup; 2629318fe57SMatthew G. Knepley dmB->levelup = tmpI; 2633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2649318fe57SMatthew G. Knepley } 2659318fe57SMatthew G. Knepley 2663431e603SJed Brown PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm) 267d71ae5a4SJacob Faibussowitsch { 2689318fe57SMatthew G. Knepley DM idm; 2699318fe57SMatthew G. Knepley 2709318fe57SMatthew G. Knepley PetscFunctionBegin; 2719566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 2729566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 27369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 2743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2759318fe57SMatthew G. Knepley } 2769318fe57SMatthew G. Knepley 2779318fe57SMatthew G. Knepley /*@C 2789318fe57SMatthew G. Knepley DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates 2799318fe57SMatthew G. Knepley 28020f4b53cSBarry Smith Collective 2819318fe57SMatthew G. Knepley 2829318fe57SMatthew G. Knepley Input Parameters: 28360225df5SJacob Faibussowitsch + dm - The `DMPLEX` 28420f4b53cSBarry Smith . degree - The degree of the finite element or `PETSC_DECIDE` 285e44f6aebSMatthew G. Knepley . project - Flag to project current coordinates into the space 2869318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface 2879318fe57SMatthew G. Knepley 2889318fe57SMatthew G. Knepley Level: advanced 2899318fe57SMatthew G. Knepley 2901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPointFunc`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()` 2919318fe57SMatthew G. Knepley @*/ 292e44f6aebSMatthew G. Knepley PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscBool project, PetscPointFunc coordFunc) 293d71ae5a4SJacob Faibussowitsch { 2949318fe57SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 295e44f6aebSMatthew G. Knepley PetscFE fe = NULL; 2969318fe57SMatthew G. Knepley DM cdm; 2971df12153SMatthew G. Knepley PetscInt dim, dE, qorder, height; 2989318fe57SMatthew G. Knepley 299e44f6aebSMatthew G. Knepley PetscFunctionBegin; 3009566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &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)); 306d0609cedSBarry Smith PetscOptionsEnd(); 3071df12153SMatthew G. Knepley PetscCall(DMPlexGetVTKCellHeight(dm, &height)); 308e44f6aebSMatthew G. Knepley if (degree >= 0) { 309e44f6aebSMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 310e44f6aebSMatthew G. Knepley PetscInt cStart, cEnd, gct; 311dc431b0cSMatthew G. Knepley 3121df12153SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd)); 313dc431b0cSMatthew G. Knepley if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 314e44f6aebSMatthew G. Knepley gct = (PetscInt)ct; 315462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &gct, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm))); 316e44f6aebSMatthew G. Knepley ct = (DMPolytopeType)gct; 317e44f6aebSMatthew G. Knepley // Work around current bug in PetscDualSpaceSetUp_Lagrange() 318e44f6aebSMatthew G. Knepley // Can be seen in plex_tutorials-ex10_1 319e44f6aebSMatthew 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)); 3204f9ab2b4SJed Brown } 321e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinateDisc(dm, fe, project)); 3229566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 3239318fe57SMatthew G. Knepley mesh->coordFunc = coordFunc; 3243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3259318fe57SMatthew G. Knepley } 3269318fe57SMatthew G. Knepley 3271df5d5c5SMatthew G. Knepley /*@ 3281df5d5c5SMatthew G. Knepley DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 3291df5d5c5SMatthew G. Knepley 330d083f849SBarry Smith Collective 3311df5d5c5SMatthew G. Knepley 3321df5d5c5SMatthew G. Knepley Input Parameters: 333a1cb98faSBarry Smith + comm - The communicator for the `DM` object 3341df5d5c5SMatthew G. Knepley . dim - The spatial dimension 3351df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells 3361df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces) 3371df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 3381df5d5c5SMatthew G. Knepley 3391df5d5c5SMatthew G. Knepley Output Parameter: 34060225df5SJacob Faibussowitsch . newdm - The `DM` object 3411df5d5c5SMatthew G. Knepley 3421df5d5c5SMatthew G. Knepley Level: beginner 3431df5d5c5SMatthew G. Knepley 3441cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()` 3451df5d5c5SMatthew G. Knepley @*/ 346d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) 347d71ae5a4SJacob Faibussowitsch { 3481df5d5c5SMatthew G. Knepley DM dm; 3491df5d5c5SMatthew G. Knepley PetscMPIInt rank; 3501df5d5c5SMatthew G. Knepley 3511df5d5c5SMatthew G. Knepley PetscFunctionBegin; 3529566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &dm)); 3539566063dSJacob Faibussowitsch PetscCall(DMSetType(dm, DMPLEX)); 3549566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 35546139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 3569566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 357ce78fa2fSMatthew G. Knepley switch (dim) { 358ce78fa2fSMatthew G. Knepley case 2: 3599566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular")); 3609566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral")); 361ce78fa2fSMatthew G. Knepley break; 362ce78fa2fSMatthew G. Knepley case 3: 3639566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral")); 3649566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral")); 365ce78fa2fSMatthew G. Knepley break; 366d71ae5a4SJacob Faibussowitsch default: 367d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 368ce78fa2fSMatthew G. Knepley } 3691df5d5c5SMatthew G. Knepley if (rank) { 3701df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {0, 0}; 3719566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL)); 3721df5d5c5SMatthew G. Knepley } else { 3731df5d5c5SMatthew G. Knepley switch (dim) { 3741df5d5c5SMatthew G. Knepley case 2: 3751df5d5c5SMatthew G. Knepley if (simplex) { 3761df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {4, 2}; 3771df5d5c5SMatthew G. Knepley PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 3781df5d5c5SMatthew G. Knepley PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 3791df5d5c5SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 3801df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 3811df5d5c5SMatthew G. Knepley 3829566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 3831df5d5c5SMatthew G. Knepley } else { 3841df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {6, 2}; 3851df5d5c5SMatthew G. Knepley PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 3861df5d5c5SMatthew G. Knepley PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 3871df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 3881df5d5c5SMatthew 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}; 3891df5d5c5SMatthew G. Knepley 3909566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 3911df5d5c5SMatthew G. Knepley } 3921df5d5c5SMatthew G. Knepley break; 3931df5d5c5SMatthew G. Knepley case 3: 3941df5d5c5SMatthew G. Knepley if (simplex) { 3951df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {5, 2}; 3961df5d5c5SMatthew G. Knepley PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 3971df5d5c5SMatthew G. Knepley PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 3981df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 3991df5d5c5SMatthew 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}; 4001df5d5c5SMatthew G. Knepley 4019566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4021df5d5c5SMatthew G. Knepley } else { 4031df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {12, 2}; 4041df5d5c5SMatthew G. Knepley PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 4051df5d5c5SMatthew G. Knepley PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 4061df5d5c5SMatthew G. Knepley PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 4079371c9d4SSatish 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}; 4081df5d5c5SMatthew G. Knepley 4099566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4101df5d5c5SMatthew G. Knepley } 4111df5d5c5SMatthew G. Knepley break; 412d71ae5a4SJacob Faibussowitsch default: 413d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 4141df5d5c5SMatthew G. Knepley } 4151df5d5c5SMatthew G. Knepley } 41646139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 4171df5d5c5SMatthew G. Knepley *newdm = dm; 4181df5d5c5SMatthew G. Knepley if (refinementLimit > 0.0) { 4191df5d5c5SMatthew G. Knepley DM rdm; 4201df5d5c5SMatthew G. Knepley const char *name; 4211df5d5c5SMatthew G. Knepley 4229566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 4239566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 4249566063dSJacob Faibussowitsch PetscCall(DMRefine(*newdm, comm, &rdm)); 4259566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)*newdm, &name)); 4269566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, name)); 4279566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 4281df5d5c5SMatthew G. Knepley *newdm = rdm; 4291df5d5c5SMatthew G. Knepley } 4301df5d5c5SMatthew G. Knepley if (interpolate) { 4315fd9971aSMatthew G. Knepley DM idm; 4321df5d5c5SMatthew G. Knepley 4339566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*newdm, &idm)); 4349566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 4351df5d5c5SMatthew G. Knepley *newdm = idm; 4361df5d5c5SMatthew G. Knepley } 4373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4381df5d5c5SMatthew G. Knepley } 4391df5d5c5SMatthew G. Knepley 440d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 441d71ae5a4SJacob Faibussowitsch { 4429318fe57SMatthew G. Knepley const PetscInt numVertices = 2; 4439318fe57SMatthew G. Knepley PetscInt markerRight = 1; 4449318fe57SMatthew G. Knepley PetscInt markerLeft = 1; 4459318fe57SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 4469318fe57SMatthew G. Knepley Vec coordinates; 4479318fe57SMatthew G. Knepley PetscSection coordSection; 4489318fe57SMatthew G. Knepley PetscScalar *coords; 4499318fe57SMatthew G. Knepley PetscInt coordSize; 4509318fe57SMatthew G. Knepley PetscMPIInt rank; 4519318fe57SMatthew G. Knepley PetscInt cdim = 1, v; 452552f7358SJed Brown 4539318fe57SMatthew G. Knepley PetscFunctionBegin; 4549566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 4559318fe57SMatthew G. Knepley if (markerSeparate) { 4569318fe57SMatthew G. Knepley markerRight = 2; 4579318fe57SMatthew G. Knepley markerLeft = 1; 4589318fe57SMatthew G. Knepley } 4599566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 460c5853193SPierre Jolivet if (rank == 0) { 4619566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numVertices)); 4629566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 4639566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft)); 4649566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight)); 4659318fe57SMatthew G. Knepley } 4669566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 4679566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 4689318fe57SMatthew G. Knepley /* Build coordinates */ 4699566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 4709566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 4719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 4729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, 0, numVertices)); 4739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 4749318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 4759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 4769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 4779318fe57SMatthew G. Knepley } 4789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 4799566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 4809566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 4819566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 4829566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 4839566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 4849566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 4859566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 4869318fe57SMatthew G. Knepley coords[0] = lower[0]; 4879318fe57SMatthew G. Knepley coords[1] = upper[0]; 4889566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 4899566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 4909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 4913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4929318fe57SMatthew G. Knepley } 49326492d91SMatthew G. Knepley 494d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 495d71ae5a4SJacob Faibussowitsch { 4961df21d24SMatthew G. Knepley const PetscInt numVertices = (edges[0] + 1) * (edges[1] + 1); 4971df21d24SMatthew G. Knepley const PetscInt numEdges = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1]; 498552f7358SJed Brown PetscInt markerTop = 1; 499552f7358SJed Brown PetscInt markerBottom = 1; 500552f7358SJed Brown PetscInt markerRight = 1; 501552f7358SJed Brown PetscInt markerLeft = 1; 502552f7358SJed Brown PetscBool markerSeparate = PETSC_FALSE; 503552f7358SJed Brown Vec coordinates; 504552f7358SJed Brown PetscSection coordSection; 505552f7358SJed Brown PetscScalar *coords; 506552f7358SJed Brown PetscInt coordSize; 507552f7358SJed Brown PetscMPIInt rank; 508552f7358SJed Brown PetscInt v, vx, vy; 509552f7358SJed Brown 510552f7358SJed Brown PetscFunctionBegin; 5119566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 512552f7358SJed Brown if (markerSeparate) { 5131df21d24SMatthew G. Knepley markerTop = 3; 5141df21d24SMatthew G. Knepley markerBottom = 1; 5151df21d24SMatthew G. Knepley markerRight = 2; 5161df21d24SMatthew G. Knepley markerLeft = 4; 517552f7358SJed Brown } 5189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 519dd400576SPatrick Sanan if (rank == 0) { 520552f7358SJed Brown PetscInt e, ex, ey; 521552f7358SJed Brown 5229566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices)); 52348a46eb9SPierre Jolivet for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 5249566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 525552f7358SJed Brown for (vx = 0; vx <= edges[0]; vx++) { 526552f7358SJed Brown for (ey = 0; ey < edges[1]; ey++) { 527552f7358SJed Brown PetscInt edge = vx * edges[1] + ey + edges[0] * (edges[1] + 1); 528552f7358SJed Brown PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges; 529da80777bSKarl Rupp PetscInt cone[2]; 530552f7358SJed Brown 5319371c9d4SSatish Balay cone[0] = vertex; 5329371c9d4SSatish Balay cone[1] = vertex + edges[0] + 1; 5339566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 534552f7358SJed Brown if (vx == edges[0]) { 5359566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 5369566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 537552f7358SJed Brown if (ey == edges[1] - 1) { 5389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 5399566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 540552f7358SJed Brown } 541552f7358SJed Brown } else if (vx == 0) { 5429566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 5439566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 544552f7358SJed Brown if (ey == edges[1] - 1) { 5459566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 5469566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft)); 547552f7358SJed Brown } 548552f7358SJed Brown } 549552f7358SJed Brown } 550552f7358SJed Brown } 551552f7358SJed Brown for (vy = 0; vy <= edges[1]; vy++) { 552552f7358SJed Brown for (ex = 0; ex < edges[0]; ex++) { 553552f7358SJed Brown PetscInt edge = vy * edges[0] + ex; 554552f7358SJed Brown PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges; 555da80777bSKarl Rupp PetscInt cone[2]; 556552f7358SJed Brown 5579371c9d4SSatish Balay cone[0] = vertex; 5589371c9d4SSatish Balay cone[1] = vertex + 1; 5599566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 560552f7358SJed Brown if (vy == edges[1]) { 5619566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 5629566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 563552f7358SJed Brown if (ex == edges[0] - 1) { 5649566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 5659566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 566552f7358SJed Brown } 567552f7358SJed Brown } else if (vy == 0) { 5689566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 5699566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 570552f7358SJed Brown if (ex == edges[0] - 1) { 5719566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 5729566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 573552f7358SJed Brown } 574552f7358SJed Brown } 575552f7358SJed Brown } 576552f7358SJed Brown } 577552f7358SJed Brown } 5789566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 5799566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 580552f7358SJed Brown /* Build coordinates */ 5819566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 2)); 5829566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 5839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 5849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 5859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 586552f7358SJed Brown for (v = numEdges; v < numEdges + numVertices; ++v) { 5879566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 2)); 5889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 589552f7358SJed Brown } 5909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 5919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 5929566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 5939566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 5949566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 5959566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 2)); 5969566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 5979566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 598552f7358SJed Brown for (vy = 0; vy <= edges[1]; ++vy) { 599552f7358SJed Brown for (vx = 0; vx <= edges[0]; ++vx) { 600552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx; 601552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy; 602552f7358SJed Brown } 603552f7358SJed Brown } 6049566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 6059566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 6069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 6073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 608552f7358SJed Brown } 609552f7358SJed Brown 610d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 611d71ae5a4SJacob Faibussowitsch { 6129e8abbc3SMichael Lange PetscInt vertices[3], numVertices; 6137b59f5a9SMichael Lange PetscInt numFaces = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2]; 614c2df9bbfSMatthew G. Knepley PetscInt markerTop = 1; 615c2df9bbfSMatthew G. Knepley PetscInt markerBottom = 1; 616c2df9bbfSMatthew G. Knepley PetscInt markerFront = 1; 617c2df9bbfSMatthew G. Knepley PetscInt markerBack = 1; 618c2df9bbfSMatthew G. Knepley PetscInt markerRight = 1; 619c2df9bbfSMatthew G. Knepley PetscInt markerLeft = 1; 620c2df9bbfSMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 621552f7358SJed Brown Vec coordinates; 622552f7358SJed Brown PetscSection coordSection; 623552f7358SJed Brown PetscScalar *coords; 624552f7358SJed Brown PetscInt coordSize; 625552f7358SJed Brown PetscMPIInt rank; 626552f7358SJed Brown PetscInt v, vx, vy, vz; 6277b59f5a9SMichael Lange PetscInt voffset, iface = 0, cone[4]; 628552f7358SJed Brown 629552f7358SJed Brown PetscFunctionBegin; 6301dca8a05SBarry 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"); 6319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 632c2df9bbfSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 633c2df9bbfSMatthew G. Knepley if (markerSeparate) { 634c2df9bbfSMatthew G. Knepley markerBottom = 1; 635c2df9bbfSMatthew G. Knepley markerTop = 2; 636c2df9bbfSMatthew G. Knepley markerFront = 3; 637c2df9bbfSMatthew G. Knepley markerBack = 4; 638c2df9bbfSMatthew G. Knepley markerRight = 5; 639c2df9bbfSMatthew G. Knepley markerLeft = 6; 640c2df9bbfSMatthew G. Knepley } 6419371c9d4SSatish Balay vertices[0] = faces[0] + 1; 6429371c9d4SSatish Balay vertices[1] = faces[1] + 1; 6439371c9d4SSatish Balay vertices[2] = faces[2] + 1; 6449e8abbc3SMichael Lange numVertices = vertices[0] * vertices[1] * vertices[2]; 645dd400576SPatrick Sanan if (rank == 0) { 646552f7358SJed Brown PetscInt f; 647552f7358SJed Brown 6489566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices)); 64948a46eb9SPierre Jolivet for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 6509566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 6517b59f5a9SMichael Lange 6527b59f5a9SMichael Lange /* Side 0 (Top) */ 6537b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 6547b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 6557b59f5a9SMichael Lange voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx; 6569371c9d4SSatish Balay cone[0] = voffset; 6579371c9d4SSatish Balay cone[1] = voffset + 1; 6589371c9d4SSatish Balay cone[2] = voffset + vertices[0] + 1; 6599371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 6609566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 661c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop)); 662c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop)); 663c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop)); 664c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop)); 665c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop)); 6667b59f5a9SMichael Lange iface++; 667552f7358SJed Brown } 668552f7358SJed Brown } 6697b59f5a9SMichael Lange 6707b59f5a9SMichael Lange /* Side 1 (Bottom) */ 6717b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 6727b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 6737b59f5a9SMichael Lange voffset = numFaces + vy * (faces[0] + 1) + vx; 6749371c9d4SSatish Balay cone[0] = voffset + 1; 6759371c9d4SSatish Balay cone[1] = voffset; 6769371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 6779371c9d4SSatish Balay cone[3] = voffset + vertices[0] + 1; 6789566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 679c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom)); 680c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom)); 681c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom)); 682c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom)); 683c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom)); 6847b59f5a9SMichael Lange iface++; 685552f7358SJed Brown } 686552f7358SJed Brown } 6877b59f5a9SMichael Lange 6887b59f5a9SMichael Lange /* Side 2 (Front) */ 6897b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 6907b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 6917b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vx; 6929371c9d4SSatish Balay cone[0] = voffset; 6939371c9d4SSatish Balay cone[1] = voffset + 1; 6949371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + 1; 6959371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1]; 6969566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 697c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront)); 698c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront)); 699c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront)); 700c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront)); 701c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront)); 7027b59f5a9SMichael Lange iface++; 703552f7358SJed Brown } 7047b59f5a9SMichael Lange } 7057b59f5a9SMichael Lange 7067b59f5a9SMichael Lange /* Side 3 (Back) */ 7077b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 7087b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7097b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx; 7109371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 7119371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1] + 1; 7129371c9d4SSatish Balay cone[2] = voffset + 1; 7139371c9d4SSatish Balay cone[3] = voffset; 7149566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 715c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack)); 716c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack)); 717c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack)); 718c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack)); 719c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack)); 7207b59f5a9SMichael Lange iface++; 7217b59f5a9SMichael Lange } 7227b59f5a9SMichael Lange } 7237b59f5a9SMichael Lange 7247b59f5a9SMichael Lange /* Side 4 (Left) */ 7257b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 7267b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7277b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0]; 7289371c9d4SSatish Balay cone[0] = voffset; 7299371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1]; 7309371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + vertices[0]; 7319371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 7329566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 733c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft)); 734c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft)); 735c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft)); 736c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft)); 737c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft)); 7387b59f5a9SMichael Lange iface++; 7397b59f5a9SMichael Lange } 7407b59f5a9SMichael Lange } 7417b59f5a9SMichael Lange 7427b59f5a9SMichael Lange /* Side 5 (Right) */ 7437b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 7447b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 745aab5bcd8SJed Brown voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0]; 7469371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 7479371c9d4SSatish Balay cone[1] = voffset; 7489371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 7499371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1] + vertices[0]; 7509566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 751c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight)); 752c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight)); 753c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight)); 754c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight)); 755c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight)); 7567b59f5a9SMichael Lange iface++; 7577b59f5a9SMichael Lange } 758552f7358SJed Brown } 759552f7358SJed Brown } 7609566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 7619566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 762552f7358SJed Brown /* Build coordinates */ 7639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 3)); 7649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 7659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 7669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 7679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 768552f7358SJed Brown for (v = numFaces; v < numFaces + numVertices; ++v) { 7699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 3)); 7709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 771552f7358SJed Brown } 7729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 7739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 7749566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 7759566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 7769566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 7779566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 3)); 7789566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 7799566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 780552f7358SJed Brown for (vz = 0; vz <= faces[2]; ++vz) { 781552f7358SJed Brown for (vy = 0; vy <= faces[1]; ++vy) { 782552f7358SJed Brown for (vx = 0; vx <= faces[0]; ++vx) { 783552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx; 784552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy; 785552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz; 786552f7358SJed Brown } 787552f7358SJed Brown } 788552f7358SJed Brown } 7899566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 7909566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 7919566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 7923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 793552f7358SJed Brown } 794552f7358SJed Brown 795d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) 796d71ae5a4SJacob Faibussowitsch { 7979318fe57SMatthew G. Knepley PetscFunctionBegin; 7989318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 79946139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 8009566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim - 1)); 8019566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim)); 8029318fe57SMatthew G. Knepley switch (dim) { 803d71ae5a4SJacob Faibussowitsch case 1: 804d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces)); 805d71ae5a4SJacob Faibussowitsch break; 806d71ae5a4SJacob Faibussowitsch case 2: 807d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces)); 808d71ae5a4SJacob Faibussowitsch break; 809d71ae5a4SJacob Faibussowitsch case 3: 810d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces)); 811d71ae5a4SJacob Faibussowitsch break; 812d71ae5a4SJacob Faibussowitsch default: 813d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim); 8149318fe57SMatthew G. Knepley } 81546139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 8169566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 8173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8189318fe57SMatthew G. Knepley } 8199318fe57SMatthew G. Knepley 8209318fe57SMatthew G. Knepley /*@C 8219318fe57SMatthew G. Knepley DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra). 8229318fe57SMatthew G. Knepley 8239318fe57SMatthew G. Knepley Collective 8249318fe57SMatthew G. Knepley 8259318fe57SMatthew G. Knepley Input Parameters: 826a1cb98faSBarry Smith + comm - The communicator for the `DM` object 82720f4b53cSBarry Smith . dim - The spatial dimension of the box, so the resulting mesh is has dimension `dim`-1 82820f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 82920f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 83020f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 8319318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 8329318fe57SMatthew G. Knepley 8339318fe57SMatthew G. Knepley Output Parameter: 834a1cb98faSBarry Smith . dm - The `DM` object 8359318fe57SMatthew G. Knepley 8369318fe57SMatthew G. Knepley Level: beginner 8379318fe57SMatthew G. Knepley 8381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()` 8399318fe57SMatthew G. Knepley @*/ 840d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) 841d71ae5a4SJacob Faibussowitsch { 8429318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 8439318fe57SMatthew G. Knepley PetscReal low[3] = {0, 0, 0}; 8449318fe57SMatthew G. Knepley PetscReal upp[3] = {1, 1, 1}; 8459318fe57SMatthew G. Knepley 8469318fe57SMatthew G. Knepley PetscFunctionBegin; 8479566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 8489566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 8499566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate)); 8503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8519318fe57SMatthew G. Knepley } 8529318fe57SMatthew G. Knepley 853d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd) 854d71ae5a4SJacob Faibussowitsch { 855fdbf62faSLisandro Dalcin PetscInt i, fStart, fEnd, numCells = 0, numVerts = 0; 856fdbf62faSLisandro Dalcin PetscInt numPoints[2], *coneSize, *cones, *coneOrientations; 857fdbf62faSLisandro Dalcin PetscScalar *vertexCoords; 858fdbf62faSLisandro Dalcin PetscReal L, maxCell; 859fdbf62faSLisandro Dalcin PetscBool markerSeparate = PETSC_FALSE; 860fdbf62faSLisandro Dalcin PetscInt markerLeft = 1, faceMarkerLeft = 1; 861fdbf62faSLisandro Dalcin PetscInt markerRight = 1, faceMarkerRight = 2; 862fdbf62faSLisandro Dalcin PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 863fdbf62faSLisandro Dalcin PetscMPIInt rank; 864fdbf62faSLisandro Dalcin 865fdbf62faSLisandro Dalcin PetscFunctionBegin; 8664f572ea9SToby Isaac PetscAssertPointer(dm, 1); 867fdbf62faSLisandro Dalcin 8689566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, 1)); 8699566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 8709566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 871fdbf62faSLisandro Dalcin 8729566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 873dd400576SPatrick Sanan if (rank == 0) numCells = segments; 874dd400576SPatrick Sanan if (rank == 0) numVerts = segments + (wrap ? 0 : 1); 875fdbf62faSLisandro Dalcin 8769371c9d4SSatish Balay numPoints[0] = numVerts; 8779371c9d4SSatish Balay numPoints[1] = numCells; 8789566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords)); 8799566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts)); 880ad540459SPierre Jolivet for (i = 0; i < numCells; ++i) coneSize[i] = 2; 881ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0; 8829371c9d4SSatish Balay for (i = 0; i < numCells; ++i) { 8839371c9d4SSatish Balay cones[2 * i] = numCells + i % numVerts; 8849371c9d4SSatish Balay cones[2 * i + 1] = numCells + (i + 1) % numVerts; 8859371c9d4SSatish Balay } 886ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells); 8879566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 8889566063dSJacob Faibussowitsch PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords)); 889fdbf62faSLisandro Dalcin 8909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 8919371c9d4SSatish Balay if (markerSeparate) { 8929371c9d4SSatish Balay markerLeft = faceMarkerLeft; 8939371c9d4SSatish Balay markerRight = faceMarkerRight; 8949371c9d4SSatish Balay } 895dd400576SPatrick Sanan if (!wrap && rank == 0) { 8969566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 8979566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft)); 8989566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight)); 8999566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft)); 9009566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight)); 901fdbf62faSLisandro Dalcin } 902fdbf62faSLisandro Dalcin if (wrap) { 903fdbf62faSLisandro Dalcin L = upper - lower; 904fdbf62faSLisandro Dalcin maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments)); 9054fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L)); 906fdbf62faSLisandro Dalcin } 9079566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 9083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 909fdbf62faSLisandro Dalcin } 910fdbf62faSLisandro Dalcin 9114054ae39SJames Wright // Creates "Face Sets" label based on the standard box labeling conventions 912d7d2d1d2SJames Wright static PetscErrorCode DMPlexSetBoxLabel_Internal(DM dm, const DMBoundaryType periodicity[]) 9134054ae39SJames Wright { 9146ff49feeSJames Wright DM cdm; 9156ff49feeSJames Wright PetscSection csection; 9166ff49feeSJames Wright Vec coordinates; 9174054ae39SJames Wright DMLabel label; 9186ff49feeSJames Wright IS faces_is; 9192b4f33d9SJames Wright PetscInt dim, num_face = 0; 9204054ae39SJames Wright const PetscInt *faces; 9214054ae39SJames Wright PetscInt faceMarkerBottom, faceMarkerTop, faceMarkerFront, faceMarkerBack, faceMarkerRight, faceMarkerLeft; 9224054ae39SJames Wright 9234054ae39SJames Wright PetscFunctionBeginUser; 9244054ae39SJames Wright PetscCall(DMGetDimension(dm, &dim)); 925d7c1f440SPierre 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); 9264054ae39SJames Wright // Get Face Sets label 9274054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 9284054ae39SJames Wright if (label) { 9294054ae39SJames Wright PetscCall(DMLabelReset(label)); 9304054ae39SJames Wright } else { 9314054ae39SJames Wright PetscCall(DMCreateLabel(dm, "Face Sets")); 9324054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 9334054ae39SJames Wright } 9344054ae39SJames Wright PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label)); 9356ff49feeSJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", 1, &faces_is)); 9364054ae39SJames Wright 9374054ae39SJames Wright switch (dim) { 9384054ae39SJames Wright case 2: 9394054ae39SJames Wright faceMarkerTop = 3; 9404054ae39SJames Wright faceMarkerBottom = 1; 9414054ae39SJames Wright faceMarkerRight = 2; 9424054ae39SJames Wright faceMarkerLeft = 4; 9434054ae39SJames Wright break; 9444054ae39SJames Wright case 3: 9454054ae39SJames Wright faceMarkerBottom = 1; 9464054ae39SJames Wright faceMarkerTop = 2; 9474054ae39SJames Wright faceMarkerFront = 3; 9484054ae39SJames Wright faceMarkerBack = 4; 9494054ae39SJames Wright faceMarkerRight = 5; 9504054ae39SJames Wright faceMarkerLeft = 6; 9514054ae39SJames Wright break; 9524054ae39SJames Wright default: 9534054ae39SJames Wright SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 9544054ae39SJames Wright } 9554054ae39SJames Wright 9562b4f33d9SJames Wright if (faces_is) PetscCall(ISGetLocalSize(faces_is, &num_face)); 9572b4f33d9SJames Wright if (faces_is) PetscCall(ISGetIndices(faces_is, &faces)); 9586ff49feeSJames Wright PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 9596ff49feeSJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 9606ff49feeSJames Wright PetscCall(DMGetLocalSection(cdm, &csection)); 9614054ae39SJames Wright for (PetscInt f = 0; f < num_face; ++f) { 9626ff49feeSJames Wright PetscScalar *coords = NULL; 9636ff49feeSJames Wright PetscInt face = faces[f], flip = 1, label_value = -1, coords_size; 9644054ae39SJames Wright 9654054ae39SJames Wright { // Determine if orientation of face is flipped 9664054ae39SJames Wright PetscInt num_cells_support, num_faces, start = -1; 9674054ae39SJames Wright const PetscInt *orients, *cell_faces, *cells; 9684054ae39SJames Wright 9694054ae39SJames Wright PetscCall(DMPlexGetSupport(dm, face, &cells)); 9704054ae39SJames Wright PetscCall(DMPlexGetSupportSize(dm, face, &num_cells_support)); 9714054ae39SJames 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); 9724054ae39SJames Wright PetscCall(DMPlexGetCone(dm, cells[0], &cell_faces)); 9734054ae39SJames Wright PetscCall(DMPlexGetConeSize(dm, cells[0], &num_faces)); 9744054ae39SJames Wright for (PetscInt i = 0; i < num_faces; i++) { 9754054ae39SJames Wright if (cell_faces[i] == face) start = i; 9764054ae39SJames Wright } 9774054ae39SJames Wright PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Could not find face %" PetscInt_FMT " in cone of its support", face); 9784054ae39SJames Wright PetscCall(DMPlexGetConeOrientation(dm, cells[0], &orients)); 9794054ae39SJames Wright if (orients[start] < 0) flip = -1; 9804054ae39SJames Wright } 9814054ae39SJames Wright 9826ff49feeSJames Wright // Cannot use DMPlexComputeCellGeometryFVM() for high-order geometry, so must calculate normal vectors manually 9836ff49feeSJames Wright // Use the vertices (depth 0) of coordinate DM to calculate normal vector 9846ff49feeSJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 9854054ae39SJames Wright switch (dim) { 9864054ae39SJames Wright case 2: { 9876ff49feeSJames Wright PetscScalar vec[2]; 9886ff49feeSJames Wright 9896ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) vec[d] = flip * (PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d])); 9906ff49feeSJames Wright PetscScalar normal[] = {vec[1], -vec[0]}; 9916ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 9926ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 9934054ae39SJames Wright } else { 9946ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerTop : faceMarkerBottom; 9954054ae39SJames Wright } 9964054ae39SJames Wright } break; 9974054ae39SJames Wright case 3: { 9986ff49feeSJames Wright PetscScalar vec1[3], vec2[3], normal[3]; 9996ff49feeSJames Wright 10006ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) { 10016ff49feeSJames Wright vec1[d] = PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]); 10026ff49feeSJames Wright vec2[d] = PetscRealPart(coords[2 * dim + d]) - PetscRealPart(coords[1 * dim + d]); 10036ff49feeSJames Wright } 10046ff49feeSJames Wright 10056ff49feeSJames Wright // Calculate normal vector via cross-product 10066ff49feeSJames Wright normal[0] = flip * ((vec1[1] * vec2[2]) - (vec1[2] * vec2[1])); 10076ff49feeSJames Wright normal[1] = flip * ((vec1[2] * vec2[0]) - (vec1[0] * vec2[2])); 10086ff49feeSJames Wright normal[2] = flip * ((vec1[0] * vec2[1]) - (vec1[1] * vec2[0])); 10096ff49feeSJames Wright 10106ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 10116ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[2])) { 10126ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 10134054ae39SJames Wright } else { 10146ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 10154054ae39SJames Wright } 10164054ae39SJames Wright } else { 10176ff49feeSJames Wright if (PetscAbsScalar(normal[1]) > PetscAbsScalar(normal[2])) { 10186ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerBack : faceMarkerFront; 10194054ae39SJames Wright } else { 10206ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 10214054ae39SJames Wright } 10224054ae39SJames Wright } 10234054ae39SJames Wright } break; 10244054ae39SJames Wright } 10254054ae39SJames Wright 10264054ae39SJames Wright PetscInt previous_label_value; // always 1 due to DMPlexMarkBoundaryFaces call above 10274054ae39SJames Wright PetscCall(DMGetLabelValue(dm, "Face Sets", face, &previous_label_value)); 10284054ae39SJames Wright PetscCall(DMClearLabelValue(dm, "Face Sets", face, previous_label_value)); 10294054ae39SJames Wright PetscCall(DMSetLabelValue(dm, "Face Sets", face, label_value)); 10306ff49feeSJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 10314054ae39SJames Wright } 10322b4f33d9SJames Wright if (faces_is) PetscCall(ISRestoreIndices(faces_is, &faces)); 10336ff49feeSJames Wright PetscCall(ISDestroy(&faces_is)); 1034d7d2d1d2SJames Wright 1035d7d2d1d2SJames Wright // Create Isoperiodic SF from newly-created face labels 1036d7d2d1d2SJames Wright PetscSF periodicsfs[3]; 1037d7d2d1d2SJames Wright PetscInt periodic_sf_index = 0; 1038d7d2d1d2SJames Wright PetscScalar transform[3][4][4] = {{{0.}}}; 1039d7d2d1d2SJames Wright for (PetscInt d = 0; d < dim; d++) { 1040d7d2d1d2SJames Wright IS donor_is, periodic_is; 1041d7d2d1d2SJames Wright const PetscInt *donor_faces = NULL, *periodic_faces = NULL; 1042d7d2d1d2SJames Wright PetscInt num_donor = 0, num_periodic = 0; 1043d7d2d1d2SJames Wright PetscSF centroidsf; 1044d7d2d1d2SJames Wright PetscReal donor_to_periodic_distance; 1045d7d2d1d2SJames Wright const PetscInt face_pairings[2][3][2] = { 1046d7d2d1d2SJames Wright // 2D face pairings, {donor, periodic} 1047d7d2d1d2SJames Wright {{4, 2}, {1, 3}}, 1048d7d2d1d2SJames Wright // 3D face pairings 1049d7d2d1d2SJames Wright {{5, 6}, {3, 4}, {1, 2}} 1050d7d2d1d2SJames Wright }; 1051d7d2d1d2SJames Wright 1052d7d2d1d2SJames Wright if (periodicity[d] != DM_BOUNDARY_PERIODIC) continue; 1053d7d2d1d2SJames Wright { 1054d7d2d1d2SJames Wright // Compute centroidsf, which is the mapping from donor faces to periodic faces 1055d7d2d1d2SJames Wright // Matches the centroid of the faces together, ignoring the periodic direction component (which should not match between donor and periodic face) 1056d7d2d1d2SJames Wright PetscInt coords_size, centroid_comps = dim - 1; 1057d7d2d1d2SJames Wright PetscScalar *coords = NULL; 1058d7d2d1d2SJames Wright PetscReal *donor_centroids, *periodic_centroids; 1059d7d2d1d2SJames 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 1060d7d2d1d2SJames Wright 1061d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][0], &donor_is)); 1062d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][1], &periodic_is)); 1063d7d2d1d2SJames Wright if (donor_is) { 1064d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(donor_is, &num_donor)); 1065d7d2d1d2SJames Wright PetscCall(ISGetIndices(donor_is, &donor_faces)); 1066d7d2d1d2SJames Wright } 1067d7d2d1d2SJames Wright if (periodic_is) { 1068d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(periodic_is, &num_periodic)); 1069d7d2d1d2SJames Wright PetscCall(ISGetIndices(periodic_is, &periodic_faces)); 1070d7d2d1d2SJames Wright } 1071d7d2d1d2SJames Wright PetscCall(PetscCalloc2(num_donor * centroid_comps, &donor_centroids, num_periodic * centroid_comps, &periodic_centroids)); 1072d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_donor; f++) { 1073d7d2d1d2SJames Wright PetscInt face = donor_faces[f], num_coords; 1074d7d2d1d2SJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 1075d7d2d1d2SJames Wright num_coords = coords_size / dim; 1076d7d2d1d2SJames Wright for (PetscInt c = 0; c < num_coords; c++) { 1077d7d2d1d2SJames Wright PetscInt comp_index = 0; 1078d7d2d1d2SJames Wright loc_periodic[0] = PetscRealPart(coords[c * dim + d]); 1079d7d2d1d2SJames Wright for (PetscInt i = 0; i < dim; i++) { 1080d7d2d1d2SJames Wright if (i == d) continue; // Periodic direction not used for centroid calculation 1081d7d2d1d2SJames Wright donor_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords; 1082d7d2d1d2SJames Wright comp_index++; 1083d7d2d1d2SJames Wright } 1084d7d2d1d2SJames Wright } 1085d7d2d1d2SJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 1086d7d2d1d2SJames Wright } 1087d7d2d1d2SJames Wright 1088d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_periodic; f++) { 1089d7d2d1d2SJames Wright PetscInt face = periodic_faces[f], num_coords; 1090d7d2d1d2SJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 1091d7d2d1d2SJames Wright num_coords = coords_size / dim; 1092d7d2d1d2SJames Wright for (PetscInt c = 0; c < num_coords; c++) { 1093d7d2d1d2SJames Wright PetscInt comp_index = 0; 1094d7d2d1d2SJames Wright loc_periodic[1] = PetscRealPart(coords[c * dim + d]); 1095d7d2d1d2SJames Wright for (PetscInt i = 0; i < dim; i++) { 1096d7d2d1d2SJames Wright if (i == d) continue; // Periodic direction not used for centroid calculation 1097d7d2d1d2SJames Wright periodic_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords; 1098d7d2d1d2SJames Wright comp_index++; 1099d7d2d1d2SJames Wright } 1100d7d2d1d2SJames Wright } 1101d7d2d1d2SJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 1102d7d2d1d2SJames Wright } 1103d7d2d1d2SJames Wright PetscCallMPI(MPIU_Allreduce(loc_periodic, loc_periodic_global, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm))); 1104d7d2d1d2SJames Wright donor_to_periodic_distance = loc_periodic_global[1] - loc_periodic_global[0]; 1105d7d2d1d2SJames Wright 1106d7d2d1d2SJames Wright PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), ¢roidsf)); 1107d7d2d1d2SJames Wright PetscCall(PetscSFSetGraphFromCoordinates(centroidsf, num_donor, num_periodic, centroid_comps, 1e-10, donor_centroids, periodic_centroids)); 1108d7d2d1d2SJames Wright PetscCall(PetscSFViewFromOptions(centroidsf, NULL, "-dm_plex_box_label_centroid_sf_view")); 1109d7d2d1d2SJames Wright PetscCall(PetscFree2(donor_centroids, periodic_centroids)); 1110d7d2d1d2SJames Wright } 1111d7d2d1d2SJames Wright 1112d7d2d1d2SJames Wright { // Create Isoperiodic SF using centroidsSF 1113d7d2d1d2SJames Wright PetscInt pStart, pEnd; 1114d7d2d1d2SJames Wright PetscInt *leaf_faces; 1115d7d2d1d2SJames Wright const PetscSFNode *firemote; 1116d7d2d1d2SJames Wright PetscSFNode *isoperiodic_leaves; 1117d7d2d1d2SJames Wright 1118d7d2d1d2SJames Wright PetscCall(PetscMalloc1(num_periodic, &leaf_faces)); 1119d7d2d1d2SJames Wright PetscCall(PetscSFBcastBegin(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE)); 1120d7d2d1d2SJames Wright PetscCall(PetscSFBcastEnd(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE)); 1121d7d2d1d2SJames Wright 1122d7d2d1d2SJames Wright PetscCall(PetscMalloc1(num_periodic, &isoperiodic_leaves)); 1123d7d2d1d2SJames Wright PetscCall(PetscSFGetGraph(centroidsf, NULL, NULL, NULL, &firemote)); 1124d7d2d1d2SJames Wright for (PetscInt l = 0; l < num_periodic; ++l) { 1125d7d2d1d2SJames Wright isoperiodic_leaves[l].index = leaf_faces[l]; 1126d7d2d1d2SJames Wright isoperiodic_leaves[l].rank = firemote[l].rank; 1127d7d2d1d2SJames Wright } 1128d7d2d1d2SJames Wright 1129d7d2d1d2SJames Wright PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 1130d7d2d1d2SJames Wright PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &periodicsfs[periodic_sf_index])); 1131d7d2d1d2SJames Wright PetscCall(PetscSFSetGraph(periodicsfs[periodic_sf_index], pEnd - pStart, num_periodic, (PetscInt *)periodic_faces, PETSC_COPY_VALUES, isoperiodic_leaves, PETSC_OWN_POINTER)); 1132d7d2d1d2SJames Wright PetscCall(PetscSFViewFromOptions(periodicsfs[periodic_sf_index], NULL, "-dm_plex_box_label_periodic_sf_view")); 1133d7d2d1d2SJames Wright PetscCall(PetscFree(leaf_faces)); 1134d7d2d1d2SJames Wright } 1135d7d2d1d2SJames Wright 1136d7d2d1d2SJames Wright transform[periodic_sf_index][0][0] = 1; 1137d7d2d1d2SJames Wright transform[periodic_sf_index][1][1] = 1; 1138d7d2d1d2SJames Wright transform[periodic_sf_index][2][2] = 1; 1139d7d2d1d2SJames Wright transform[periodic_sf_index][3][3] = 1; 1140d7d2d1d2SJames Wright transform[periodic_sf_index][d][3] = donor_to_periodic_distance; 1141d7d2d1d2SJames Wright 1142d7d2d1d2SJames Wright periodic_sf_index++; 1143d7d2d1d2SJames Wright PetscCall(PetscSFDestroy(¢roidsf)); 1144d7d2d1d2SJames Wright if (donor_is) { 1145d7d2d1d2SJames Wright PetscCall(ISRestoreIndices(donor_is, &donor_faces)); 1146d7d2d1d2SJames Wright PetscCall(ISDestroy(&donor_is)); 1147d7d2d1d2SJames Wright } 1148d7d2d1d2SJames Wright if (periodic_is) { 1149d7d2d1d2SJames Wright PetscCall(ISRestoreIndices(periodic_is, &periodic_faces)); 1150d7d2d1d2SJames Wright PetscCall(ISDestroy(&periodic_is)); 1151d7d2d1d2SJames Wright } 1152d7d2d1d2SJames Wright PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][0])); 1153d7d2d1d2SJames Wright PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][1])); 1154d7d2d1d2SJames Wright } 1155d7d2d1d2SJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(dm, periodic_sf_index, periodicsfs)); 1156d7d2d1d2SJames Wright PetscCall(DMPlexSetIsoperiodicFaceTransform(dm, periodic_sf_index, (const PetscScalar *)transform)); 1157d7d2d1d2SJames Wright for (PetscInt p = 0; p < periodic_sf_index; p++) PetscCall(PetscSFDestroy(&periodicsfs[p])); 1158d7d2d1d2SJames Wright 1159d7d2d1d2SJames Wright { // Update coordinate DM with new Face Sets label 1160d7d2d1d2SJames Wright DM cdm; 1161d7d2d1d2SJames Wright DMLabel oldFaceSets, newFaceSets; 1162d7d2d1d2SJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 1163d7d2d1d2SJames Wright PetscCall(DMGetLabel(cdm, "Face Sets", &oldFaceSets)); 1164d7d2d1d2SJames Wright if (oldFaceSets) PetscCall(DMRemoveLabelBySelf(cdm, &oldFaceSets, PETSC_FALSE)); 1165d7d2d1d2SJames Wright PetscCall(DMLabelDuplicate(label, &newFaceSets)); 1166d7d2d1d2SJames Wright PetscCall(DMAddLabel(cdm, newFaceSets)); 1167d7d2d1d2SJames Wright PetscCall(DMLabelDestroy(&newFaceSets)); 1168d7d2d1d2SJames Wright } 11694054ae39SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 11704054ae39SJames Wright } 11714054ae39SJames Wright 1172d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 1173d71ae5a4SJacob Faibussowitsch { 11749318fe57SMatthew G. Knepley DM boundary, vol; 1175c22d3578SMatthew G. Knepley DMLabel bdlabel; 1176d6218766SMatthew G. Knepley 1177d6218766SMatthew G. Knepley PetscFunctionBegin; 11784f572ea9SToby Isaac PetscAssertPointer(dm, 1); 1179c22d3578SMatthew 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"); 11809566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary)); 11819566063dSJacob Faibussowitsch PetscCall(DMSetType(boundary, DMPLEX)); 11829566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 11839566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 1184c22d3578SMatthew G. Knepley PetscCall(DMGetLabel(vol, "marker", &bdlabel)); 1185c22d3578SMatthew G. Knepley if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel)); 11865de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol)); 118769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 11884054ae39SJames Wright if (interpolate) { 11894054ae39SJames Wright PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 1190d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, periodicity)); 11914054ae39SJames Wright } 11929566063dSJacob Faibussowitsch PetscCall(DMDestroy(&boundary)); 11933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1194d6218766SMatthew G. Knepley } 1195d6218766SMatthew G. Knepley 1196d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 1197d71ae5a4SJacob Faibussowitsch { 1198ed0e4b50SMatthew G. Knepley DMLabel cutLabel = NULL; 1199f4eb4c5dSMatthew G. Knepley PetscInt markerTop = 1, faceMarkerTop = 1; 1200f4eb4c5dSMatthew G. Knepley PetscInt markerBottom = 1, faceMarkerBottom = 1; 1201f4eb4c5dSMatthew G. Knepley PetscInt markerFront = 1, faceMarkerFront = 1; 1202f4eb4c5dSMatthew G. Knepley PetscInt markerBack = 1, faceMarkerBack = 1; 1203f4eb4c5dSMatthew G. Knepley PetscInt markerRight = 1, faceMarkerRight = 1; 1204f4eb4c5dSMatthew G. Knepley PetscInt markerLeft = 1, faceMarkerLeft = 1; 12053dfda0b1SToby Isaac PetscInt dim; 1206d8211ee3SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 12073dfda0b1SToby Isaac PetscMPIInt rank; 12083dfda0b1SToby Isaac 12093dfda0b1SToby Isaac PetscFunctionBegin; 12109566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 12119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 12129566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 12139566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 12149566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 12159371c9d4SSatish 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) { 12169371c9d4SSatish Balay if (cutMarker) { 12179371c9d4SSatish Balay PetscCall(DMCreateLabel(dm, "periodic_cut")); 12189371c9d4SSatish Balay PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 12199371c9d4SSatish Balay } 1220d8211ee3SMatthew G. Knepley } 12213dfda0b1SToby Isaac switch (dim) { 12223dfda0b1SToby Isaac case 2: 1223f4eb4c5dSMatthew G. Knepley faceMarkerTop = 3; 1224f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1225f4eb4c5dSMatthew G. Knepley faceMarkerRight = 2; 1226f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 4; 12273dfda0b1SToby Isaac break; 12283dfda0b1SToby Isaac case 3: 1229f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1230f4eb4c5dSMatthew G. Knepley faceMarkerTop = 2; 1231f4eb4c5dSMatthew G. Knepley faceMarkerFront = 3; 1232f4eb4c5dSMatthew G. Knepley faceMarkerBack = 4; 1233f4eb4c5dSMatthew G. Knepley faceMarkerRight = 5; 1234f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 6; 12353dfda0b1SToby Isaac break; 1236d71ae5a4SJacob Faibussowitsch default: 1237d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 12383dfda0b1SToby Isaac } 12399566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 1240f4eb4c5dSMatthew G. Knepley if (markerSeparate) { 1241f4eb4c5dSMatthew G. Knepley markerBottom = faceMarkerBottom; 1242f4eb4c5dSMatthew G. Knepley markerTop = faceMarkerTop; 1243f4eb4c5dSMatthew G. Knepley markerFront = faceMarkerFront; 1244f4eb4c5dSMatthew G. Knepley markerBack = faceMarkerBack; 1245f4eb4c5dSMatthew G. Knepley markerRight = faceMarkerRight; 1246f4eb4c5dSMatthew G. Knepley markerLeft = faceMarkerLeft; 12473dfda0b1SToby Isaac } 12483dfda0b1SToby Isaac { 1249dd400576SPatrick Sanan const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 1250dd400576SPatrick Sanan const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 1251dd400576SPatrick Sanan const PetscInt numZEdges = rank == 0 ? edges[2] : 0; 1252dd400576SPatrick Sanan const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0; 1253dd400576SPatrick Sanan const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0; 1254dd400576SPatrick Sanan const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0; 12553dfda0b1SToby Isaac const PetscInt numCells = numXEdges * numYEdges * numZEdges; 12563dfda0b1SToby Isaac const PetscInt numXFaces = numYEdges * numZEdges; 12573dfda0b1SToby Isaac const PetscInt numYFaces = numXEdges * numZEdges; 12583dfda0b1SToby Isaac const PetscInt numZFaces = numXEdges * numYEdges; 12593dfda0b1SToby Isaac const PetscInt numTotXFaces = numXVertices * numXFaces; 12603dfda0b1SToby Isaac const PetscInt numTotYFaces = numYVertices * numYFaces; 12613dfda0b1SToby Isaac const PetscInt numTotZFaces = numZVertices * numZFaces; 12623dfda0b1SToby Isaac const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 12633dfda0b1SToby Isaac const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices; 12643dfda0b1SToby Isaac const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices; 12653dfda0b1SToby Isaac const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices; 12663dfda0b1SToby Isaac const PetscInt numVertices = numXVertices * numYVertices * numZVertices; 12673dfda0b1SToby Isaac const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 12683dfda0b1SToby Isaac const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 12693dfda0b1SToby Isaac const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 12703dfda0b1SToby Isaac const PetscInt firstYFace = firstXFace + numTotXFaces; 12713dfda0b1SToby Isaac const PetscInt firstZFace = firstYFace + numTotYFaces; 12723dfda0b1SToby Isaac const PetscInt firstXEdge = numCells + numFaces + numVertices; 12733dfda0b1SToby Isaac const PetscInt firstYEdge = firstXEdge + numTotXEdges; 12743dfda0b1SToby Isaac const PetscInt firstZEdge = firstYEdge + numTotYEdges; 12753dfda0b1SToby Isaac Vec coordinates; 12763dfda0b1SToby Isaac PetscSection coordSection; 12773dfda0b1SToby Isaac PetscScalar *coords; 12783dfda0b1SToby Isaac PetscInt coordSize; 12793dfda0b1SToby Isaac PetscInt v, vx, vy, vz; 12803dfda0b1SToby Isaac PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 12813dfda0b1SToby Isaac 12829566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices)); 128348a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 128448a46eb9SPierre Jolivet for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 128548a46eb9SPierre Jolivet for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 12869566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 12873dfda0b1SToby Isaac /* Build cells */ 12883dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 12893dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 12903dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 12913dfda0b1SToby Isaac PetscInt cell = (fz * numYEdges + fy) * numXEdges + fx; 12923dfda0b1SToby Isaac PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 12933dfda0b1SToby Isaac PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices); 12943dfda0b1SToby Isaac PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 12953dfda0b1SToby Isaac PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices); 12963dfda0b1SToby Isaac PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 12973dfda0b1SToby Isaac PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices); 12983dfda0b1SToby Isaac /* B, T, F, K, R, L */ 1299b5a892a1SMatthew G. Knepley PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */ 130042206facSLisandro Dalcin PetscInt cone[6]; 13013dfda0b1SToby Isaac 13023dfda0b1SToby Isaac /* no boundary twisting in 3D */ 13039371c9d4SSatish Balay cone[0] = faceB; 13049371c9d4SSatish Balay cone[1] = faceT; 13059371c9d4SSatish Balay cone[2] = faceF; 13069371c9d4SSatish Balay cone[3] = faceK; 13079371c9d4SSatish Balay cone[4] = faceR; 13089371c9d4SSatish Balay cone[5] = faceL; 13099566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, cell, cone)); 13109566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, cell, ornt)); 13119566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 13129566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 13139566063dSJacob Faibussowitsch if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 13143dfda0b1SToby Isaac } 13153dfda0b1SToby Isaac } 13163dfda0b1SToby Isaac } 13173dfda0b1SToby Isaac /* Build x faces */ 13183dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 13193dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 13203dfda0b1SToby Isaac for (fx = 0; fx < numXVertices; ++fx) { 13213dfda0b1SToby Isaac PetscInt face = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 13223dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 13233dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz; 13243dfda0b1SToby Isaac PetscInt edgeB = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 13253dfda0b1SToby Isaac PetscInt edgeT = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy; 1326b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 13273dfda0b1SToby Isaac PetscInt cone[4]; 13283dfda0b1SToby Isaac 13293dfda0b1SToby Isaac if (dim == 3) { 13303dfda0b1SToby Isaac /* markers */ 13313dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 13323dfda0b1SToby Isaac if (fx == numXVertices - 1) { 13339566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 13349566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerRight)); 13359371c9d4SSatish Balay } else if (fx == 0) { 13369566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 13379566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft)); 13383dfda0b1SToby Isaac } 13393dfda0b1SToby Isaac } 13403dfda0b1SToby Isaac } 13419371c9d4SSatish Balay cone[0] = edgeB; 13429371c9d4SSatish Balay cone[1] = edgeR; 13439371c9d4SSatish Balay cone[2] = edgeT; 13449371c9d4SSatish Balay cone[3] = edgeL; 13459566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 13469566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 13473dfda0b1SToby Isaac } 13483dfda0b1SToby Isaac } 13493dfda0b1SToby Isaac } 13503dfda0b1SToby Isaac /* Build y faces */ 13513dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 135242206facSLisandro Dalcin for (fx = 0; fx < numXEdges; ++fx) { 13533dfda0b1SToby Isaac for (fy = 0; fy < numYVertices; ++fy) { 13543dfda0b1SToby Isaac PetscInt face = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 13553dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 13563dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz; 13573dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 13583dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx; 1359b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 13603dfda0b1SToby Isaac PetscInt cone[4]; 13613dfda0b1SToby Isaac 13623dfda0b1SToby Isaac if (dim == 3) { 13633dfda0b1SToby Isaac /* markers */ 13643dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 13653dfda0b1SToby Isaac if (fy == numYVertices - 1) { 13669566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 13679566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBack)); 13689371c9d4SSatish Balay } else if (fy == 0) { 13699566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 13709566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerFront)); 13713dfda0b1SToby Isaac } 13723dfda0b1SToby Isaac } 13733dfda0b1SToby Isaac } 13749371c9d4SSatish Balay cone[0] = edgeB; 13759371c9d4SSatish Balay cone[1] = edgeR; 13769371c9d4SSatish Balay cone[2] = edgeT; 13779371c9d4SSatish Balay cone[3] = edgeL; 13789566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 13799566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 13803dfda0b1SToby Isaac } 13813dfda0b1SToby Isaac } 13823dfda0b1SToby Isaac } 13833dfda0b1SToby Isaac /* Build z faces */ 13843dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 13853dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 13863dfda0b1SToby Isaac for (fz = 0; fz < numZVertices; fz++) { 13873dfda0b1SToby Isaac PetscInt face = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 13883dfda0b1SToby Isaac PetscInt edgeL = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 13893dfda0b1SToby Isaac PetscInt edgeR = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy; 13903dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 13913dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx; 1392b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 13933dfda0b1SToby Isaac PetscInt cone[4]; 13943dfda0b1SToby Isaac 13953dfda0b1SToby Isaac if (dim == 2) { 13969371c9d4SSatish Balay if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) { 13979371c9d4SSatish Balay edgeR += numYEdges - 1 - 2 * fy; 13989371c9d4SSatish Balay ornt[1] = -1; 13999371c9d4SSatish Balay } 14009371c9d4SSatish Balay if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) { 14019371c9d4SSatish Balay edgeT += numXEdges - 1 - 2 * fx; 14029371c9d4SSatish Balay ornt[2] = 0; 14039371c9d4SSatish Balay } 14049566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 14059566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 1406d1c88043SMatthew G. Knepley } else { 14073dfda0b1SToby Isaac /* markers */ 14083dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 14093dfda0b1SToby Isaac if (fz == numZVertices - 1) { 14109566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 14119566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerTop)); 14129371c9d4SSatish Balay } else if (fz == 0) { 14139566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 14149566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom)); 14153dfda0b1SToby Isaac } 14163dfda0b1SToby Isaac } 14173dfda0b1SToby Isaac } 14189371c9d4SSatish Balay cone[0] = edgeB; 14199371c9d4SSatish Balay cone[1] = edgeR; 14209371c9d4SSatish Balay cone[2] = edgeT; 14219371c9d4SSatish Balay cone[3] = edgeL; 14229566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 14239566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 14243dfda0b1SToby Isaac } 14253dfda0b1SToby Isaac } 14263dfda0b1SToby Isaac } 14273dfda0b1SToby Isaac /* Build Z edges*/ 14283dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 14293dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 14303dfda0b1SToby Isaac for (ez = 0; ez < numZEdges; ez++) { 14313dfda0b1SToby Isaac const PetscInt edge = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez; 14323dfda0b1SToby Isaac const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx; 14333dfda0b1SToby Isaac const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx; 14343dfda0b1SToby Isaac PetscInt cone[2]; 14353dfda0b1SToby Isaac 14369371c9d4SSatish Balay cone[0] = vertexB; 14379371c9d4SSatish Balay cone[1] = vertexT; 1438c2df9bbfSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, edge, cone)); 14393dfda0b1SToby Isaac if (dim == 3) { 14403dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 14413dfda0b1SToby Isaac if (vx == numXVertices - 1) { 14429566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1443c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1444c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1445c2df9bbfSMatthew G. Knepley } else if (vx == 0) { 14469566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1447c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1448c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 14493dfda0b1SToby Isaac } 14503dfda0b1SToby Isaac } 14513dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 14523dfda0b1SToby Isaac if (vy == numYVertices - 1) { 14539566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1454c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1455c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1456c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 14579566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1458c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1459c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 14603dfda0b1SToby Isaac } 14613dfda0b1SToby Isaac } 14623dfda0b1SToby Isaac } 14633dfda0b1SToby Isaac } 14643dfda0b1SToby Isaac } 14653dfda0b1SToby Isaac } 14663dfda0b1SToby Isaac /* Build Y edges*/ 14673dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 14683dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 14693dfda0b1SToby Isaac for (ey = 0; ey < numYEdges; ey++) { 14703dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx; 14713dfda0b1SToby Isaac const PetscInt edge = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey; 14723dfda0b1SToby Isaac const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx; 14733dfda0b1SToby Isaac const PetscInt vertexK = firstVertex + nextv; 14743dfda0b1SToby Isaac PetscInt cone[2]; 14753dfda0b1SToby Isaac 14769371c9d4SSatish Balay cone[0] = vertexF; 14779371c9d4SSatish Balay cone[1] = vertexK; 14789566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 14793dfda0b1SToby Isaac if (dim == 2) { 14803dfda0b1SToby Isaac if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 14813dfda0b1SToby Isaac if (vx == numXVertices - 1) { 14829566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 14839566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 14849566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1485c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1486d8211ee3SMatthew G. Knepley } else if (vx == 0) { 14879566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 14889566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 14899566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1490c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 14913dfda0b1SToby Isaac } 1492d8211ee3SMatthew G. Knepley } else { 14934c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 14949566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 14959566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1496c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 14973dfda0b1SToby Isaac } 1498d8211ee3SMatthew G. Knepley } 1499d8211ee3SMatthew G. Knepley } else { 15003dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 15013dfda0b1SToby Isaac if (vx == numXVertices - 1) { 15029566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1503c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1504c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1505d8211ee3SMatthew G. Knepley } else if (vx == 0) { 15069566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1507c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1508c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 15093dfda0b1SToby Isaac } 15103dfda0b1SToby Isaac } 15113dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 15123dfda0b1SToby Isaac if (vz == numZVertices - 1) { 15139566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1514c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1515c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1516d8211ee3SMatthew G. Knepley } else if (vz == 0) { 15179566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1518c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1519c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 15203dfda0b1SToby Isaac } 15213dfda0b1SToby Isaac } 15223dfda0b1SToby Isaac } 15233dfda0b1SToby Isaac } 15243dfda0b1SToby Isaac } 15253dfda0b1SToby Isaac } 15263dfda0b1SToby Isaac /* Build X edges*/ 15273dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 15283dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 15293dfda0b1SToby Isaac for (ex = 0; ex < numXEdges; ex++) { 15303dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices; 15313dfda0b1SToby Isaac const PetscInt edge = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex; 15323dfda0b1SToby Isaac const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex; 15333dfda0b1SToby Isaac const PetscInt vertexR = firstVertex + nextv; 15343dfda0b1SToby Isaac PetscInt cone[2]; 15353dfda0b1SToby Isaac 15369371c9d4SSatish Balay cone[0] = vertexL; 15379371c9d4SSatish Balay cone[1] = vertexR; 15389566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 15393dfda0b1SToby Isaac if (dim == 2) { 15403dfda0b1SToby Isaac if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 15413dfda0b1SToby Isaac if (vy == numYVertices - 1) { 15429566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 15439566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 15449566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1545c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1546d8211ee3SMatthew G. Knepley } else if (vy == 0) { 15479566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 15489566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 15499566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1550c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 15513dfda0b1SToby Isaac } 1552d8211ee3SMatthew G. Knepley } else { 15534c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 15549566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 15559566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1556c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 15573dfda0b1SToby Isaac } 1558d8211ee3SMatthew G. Knepley } 1559d8211ee3SMatthew G. Knepley } else { 15603dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 15613dfda0b1SToby Isaac if (vy == numYVertices - 1) { 15629566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1563c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1564c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1565c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 15669566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1567c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1568c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 15693dfda0b1SToby Isaac } 15703dfda0b1SToby Isaac } 15713dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 15723dfda0b1SToby Isaac if (vz == numZVertices - 1) { 15739566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1574c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1575c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1576c2df9bbfSMatthew G. Knepley } else if (vz == 0) { 15779566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1578c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1579c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 15803dfda0b1SToby Isaac } 15813dfda0b1SToby Isaac } 15823dfda0b1SToby Isaac } 15833dfda0b1SToby Isaac } 15843dfda0b1SToby Isaac } 15853dfda0b1SToby Isaac } 15869566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 15879566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 15883dfda0b1SToby Isaac /* Build coordinates */ 15899566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 15909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 15919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 15929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 15933dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex + numVertices; ++v) { 15949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 15959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 15963dfda0b1SToby Isaac } 15979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 15989566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 15999566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 16009566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 16019566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 16029566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 16039566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 16049566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 16053dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; ++vz) { 16063dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; ++vy) { 16073dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; ++vx) { 16083dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 16093dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1610ad540459SPierre Jolivet if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz; 16113dfda0b1SToby Isaac } 16123dfda0b1SToby Isaac } 16133dfda0b1SToby Isaac } 16149566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 16159566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 16169566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 16173dfda0b1SToby Isaac } 16183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16193dfda0b1SToby Isaac } 16203dfda0b1SToby Isaac 1621d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1622d71ae5a4SJacob Faibussowitsch { 16239318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 16249318fe57SMatthew G. Knepley PetscInt fac[3] = {0, 0, 0}, d; 1625552f7358SJed Brown 1626552f7358SJed Brown PetscFunctionBegin; 16274f572ea9SToby Isaac PetscAssertPointer(dm, 1); 16289318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 16299566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 16309371c9d4SSatish Balay for (d = 0; d < dim; ++d) { 16319371c9d4SSatish Balay fac[d] = faces[d]; 16329371c9d4SSatish Balay bdt[d] = periodicity[d]; 16339371c9d4SSatish Balay } 16349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2])); 16359371c9d4SSatish 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))) { 16366858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 16376858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1638552f7358SJed Brown 16399318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 16406858538eSMatthew G. Knepley if (periodicity[d] != DM_BOUNDARY_NONE) { 16419318fe57SMatthew G. Knepley L[d] = upper[d] - lower[d]; 16429318fe57SMatthew G. Knepley maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d])); 1643768d5fceSMatthew G. Knepley } 16446858538eSMatthew G. Knepley } 16454fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1646768d5fceSMatthew G. Knepley } 16479566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 16483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16499318fe57SMatthew G. Knepley } 16509318fe57SMatthew G. Knepley 16515dca41c3SJed 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) 1652d71ae5a4SJacob Faibussowitsch { 16539318fe57SMatthew G. Knepley PetscFunctionBegin; 165446139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 16555dca41c3SJed Brown if (shape == DM_SHAPE_ZBOX) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 16566725e60dSJed Brown else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 16579566063dSJacob Faibussowitsch else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 16589566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity)); 16599318fe57SMatthew G. Knepley if (!interpolate && dim > 1 && !simplex) { 1660768d5fceSMatthew G. Knepley DM udm; 1661768d5fceSMatthew G. Knepley 16629566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 16639566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, udm)); 166469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 1665768d5fceSMatthew G. Knepley } 166646139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 16673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1668c8c68bd8SToby Isaac } 1669c8c68bd8SToby Isaac 16705d83a8b1SBarry Smith /*@ 1671768d5fceSMatthew G. Knepley DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 1672768d5fceSMatthew G. Knepley 1673d083f849SBarry Smith Collective 1674768d5fceSMatthew G. Knepley 1675768d5fceSMatthew G. Knepley Input Parameters: 1676a1cb98faSBarry Smith + comm - The communicator for the `DM` object 1677768d5fceSMatthew G. Knepley . dim - The spatial dimension 1678a1cb98faSBarry Smith . simplex - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells 167920f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 168020f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 168120f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 168220f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 168342108689Sksagiyam . interpolate - Flag to create intermediate mesh pieces (edges, faces) 168442108689Sksagiyam . localizationHeight - Flag to localize edges and faces in addition to cells; only significant for periodic meshes 168542108689Sksagiyam - sparseLocalize - Flag to localize coordinates only for cells near the periodic boundary; only significant for periodic meshes 1686768d5fceSMatthew G. Knepley 1687768d5fceSMatthew G. Knepley Output Parameter: 1688a1cb98faSBarry Smith . dm - The `DM` object 1689768d5fceSMatthew G. Knepley 1690768d5fceSMatthew G. Knepley Level: beginner 1691768d5fceSMatthew G. Knepley 1692a1cb98faSBarry Smith Note: 1693a1cb98faSBarry Smith To customize this mesh using options, use 1694a1cb98faSBarry Smith .vb 1695a1cb98faSBarry Smith DMCreate(comm, &dm); 1696a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 1697a1cb98faSBarry Smith DMSetFromOptions(dm); 1698a1cb98faSBarry Smith .ve 1699a1cb98faSBarry Smith and use the options in `DMSetFromOptions()`. 1700a1cb98faSBarry Smith 1701a4e35b19SJacob Faibussowitsch Here is the numbering returned for 2 faces in each direction for tensor cells\: 1702a1cb98faSBarry Smith .vb 1703a1cb98faSBarry Smith 10---17---11---18----12 1704a1cb98faSBarry Smith | | | 1705a1cb98faSBarry Smith | | | 1706a1cb98faSBarry Smith 20 2 22 3 24 1707a1cb98faSBarry Smith | | | 1708a1cb98faSBarry Smith | | | 1709a1cb98faSBarry Smith 7---15----8---16----9 1710a1cb98faSBarry Smith | | | 1711a1cb98faSBarry Smith | | | 1712a1cb98faSBarry Smith 19 0 21 1 23 1713a1cb98faSBarry Smith | | | 1714a1cb98faSBarry Smith | | | 1715a1cb98faSBarry Smith 4---13----5---14----6 1716a1cb98faSBarry Smith .ve 1717a1cb98faSBarry Smith and for simplicial cells 1718a1cb98faSBarry Smith .vb 1719a1cb98faSBarry Smith 14----8---15----9----16 1720a1cb98faSBarry Smith |\ 5 |\ 7 | 1721a1cb98faSBarry Smith | \ | \ | 1722a1cb98faSBarry Smith 13 2 14 3 15 1723a1cb98faSBarry Smith | 4 \ | 6 \ | 1724a1cb98faSBarry Smith | \ | \ | 1725a1cb98faSBarry Smith 11----6---12----7----13 1726a1cb98faSBarry Smith |\ |\ | 1727a1cb98faSBarry Smith | \ 1 | \ 3 | 1728a1cb98faSBarry Smith 10 0 11 1 12 1729a1cb98faSBarry Smith | 0 \ | 2 \ | 1730a1cb98faSBarry Smith | \ | \ | 1731a1cb98faSBarry Smith 8----4----9----5----10 1732a1cb98faSBarry Smith .ve 1733a1cb98faSBarry Smith 17341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 1735768d5fceSMatthew G. Knepley @*/ 173642108689Sksagiyam 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) 1737d71ae5a4SJacob Faibussowitsch { 17389318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 1739fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 1740fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 1741fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 1742552f7358SJed Brown 1743768d5fceSMatthew G. Knepley PetscFunctionBegin; 17449566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 17459566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 17465dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(*dm, DM_SHAPE_BOX, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 174742108689Sksagiyam if (periodicity) { 174842108689Sksagiyam DM cdm; 174942108689Sksagiyam 175042108689Sksagiyam PetscCall(DMGetCoordinateDM(*dm, &cdm)); 175142108689Sksagiyam PetscCall(DMPlexSetMaxProjectionHeight(cdm, localizationHeight)); 175242108689Sksagiyam PetscCall(DMSetSparseLocalize(*dm, sparseLocalize)); 175342108689Sksagiyam PetscCall(DMLocalizeCoordinates(*dm)); 175442108689Sksagiyam } 17553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17569318fe57SMatthew G. Knepley } 1757fdbf62faSLisandro Dalcin 1758d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1759d71ae5a4SJacob Faibussowitsch { 17609318fe57SMatthew G. Knepley DM bdm, vol; 17619318fe57SMatthew G. Knepley PetscInt i; 17629318fe57SMatthew G. Knepley 17639318fe57SMatthew G. Knepley PetscFunctionBegin; 17641fcf445aSMatthew G. Knepley // TODO Now we can support periodicity 176508401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 17669566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 17679566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 17689566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 176946139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, bdm, 0, 0, 0)); 17709566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 17711fcf445aSMatthew G. Knepley PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, NULL, NULL, &vol)); 177246139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, bdm, 0, 0, 0)); 17739566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 177469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 17759318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 17769318fe57SMatthew G. Knepley Vec v; 17779318fe57SMatthew G. Knepley PetscScalar *x; 17789318fe57SMatthew G. Knepley PetscInt cDim, n; 17799318fe57SMatthew G. Knepley 17809566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 17819566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 17829566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 17839566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 17849318fe57SMatthew G. Knepley x += cDim; 17859318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 17869566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 17879566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 17889318fe57SMatthew G. Knepley } 17893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1790552f7358SJed Brown } 1791552f7358SJed Brown 179200dabe28SStefano Zampini /*@ 179339f4f5dbSPierre Jolivet DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tessellating the (x,y) plane and extruding in the third direction using wedge cells. 179400dabe28SStefano Zampini 1795d083f849SBarry Smith Collective 179600dabe28SStefano Zampini 179700dabe28SStefano Zampini Input Parameters: 1798a1cb98faSBarry Smith + comm - The communicator for the `DM` object 179920f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1, 1, 1) 180020f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 180120f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 180220f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 1803a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 180400dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 180500dabe28SStefano Zampini 180600dabe28SStefano Zampini Output Parameter: 1807a1cb98faSBarry Smith . dm - The `DM` object 180800dabe28SStefano Zampini 180900dabe28SStefano Zampini Level: beginner 181000dabe28SStefano Zampini 18111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 181200dabe28SStefano Zampini @*/ 1813d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 1814d71ae5a4SJacob Faibussowitsch { 18159318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 181600dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 181700dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 181800dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 181900dabe28SStefano Zampini 182000dabe28SStefano Zampini PetscFunctionBegin; 18219566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 18229566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 18239566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 1824d410b0cfSMatthew G. Knepley if (!interpolate) { 1825d410b0cfSMatthew G. Knepley DM udm; 182600dabe28SStefano Zampini 18279566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 182869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 182900dabe28SStefano Zampini } 18307ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 18313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 183200dabe28SStefano Zampini } 183300dabe28SStefano Zampini 1834cfb853baSMatthew G. Knepley /* 1835cfb853baSMatthew 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. 1836cfb853baSMatthew G. Knepley 1837cfb853baSMatthew G. Knepley Input Parameters: 1838cfb853baSMatthew G. Knepley + len - The length of the tuple 1839cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max) 1840cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition 1841cfb853baSMatthew G. Knepley 1842cfb853baSMatthew G. Knepley Output Parameter: 184320f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max` 1844cfb853baSMatthew G. Knepley 1845cfb853baSMatthew G. Knepley Level: developer 1846cfb853baSMatthew G. Knepley 184720f4b53cSBarry Smith Note: 184820f4b53cSBarry Smith Ordering is lexicographic with lowest index as least significant in ordering. 184920f4b53cSBarry 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}. 185020f4b53cSBarry Smith 1851cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal() 1852cfb853baSMatthew G. Knepley */ 1853cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[]) 1854cfb853baSMatthew G. Knepley { 1855cfb853baSMatthew G. Knepley PetscInt i; 1856cfb853baSMatthew G. Knepley 1857cfb853baSMatthew G. Knepley PetscFunctionBegin; 1858cfb853baSMatthew G. Knepley for (i = 0; i < len; ++i) { 1859cfb853baSMatthew G. Knepley if (tup[i] < max[i] - 1) { 1860cfb853baSMatthew G. Knepley break; 1861cfb853baSMatthew G. Knepley } else { 1862cfb853baSMatthew G. Knepley tup[i] = 0; 1863cfb853baSMatthew G. Knepley } 1864cfb853baSMatthew G. Knepley } 1865cfb853baSMatthew G. Knepley if (i == len) tup[i - 1] = max[i - 1]; 1866cfb853baSMatthew G. Knepley else ++tup[i]; 18673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1868cfb853baSMatthew G. Knepley } 1869cfb853baSMatthew G. Knepley 1870cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[]) 1871cfb853baSMatthew G. Knepley { 18728d2ec52aSSatish Balay PetscInt idx = tup[len - 1]; 1873cfb853baSMatthew G. Knepley 18748d2ec52aSSatish Balay for (PetscInt i = len - 2; i >= 0; --i) { 1875cfb853baSMatthew G. Knepley idx *= max[i]; 1876cfb853baSMatthew G. Knepley idx += tup[i]; 1877cfb853baSMatthew G. Knepley } 1878cfb853baSMatthew G. Knepley return idx; 1879cfb853baSMatthew G. Knepley } 1880cfb853baSMatthew G. Knepley 18818d2ec52aSSatish Balay static void IndexToTuple_Private(PetscInt len, const PetscInt max[], PetscInt idx, PetscInt tup[]) 1882cfb853baSMatthew G. Knepley { 18838d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 18848d2ec52aSSatish Balay tup[i] = idx % max[i]; 18858d2ec52aSSatish Balay idx = (idx - tup[i]) / max[i]; 18868d2ec52aSSatish Balay } 18878d2ec52aSSatish Balay } 18888d2ec52aSSatish Balay 18898d2ec52aSSatish Balay static void TupleToRanks_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt tup[], PetscInt ranks[]) 18908d2ec52aSSatish Balay { 18918d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 18928d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 18938d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 18948d2ec52aSSatish Balay const PetscInt idx = (tup[i] < 0 ? max[i] + tup[i] : tup[i]) % max[i]; 18958d2ec52aSSatish Balay 18968d2ec52aSSatish Balay if (idx < rem * (div + 1)) ranks[i] = idx / (div + 1); 18978d2ec52aSSatish Balay else ranks[i] = rem + (idx - rem * (div + 1)) / div; 18988d2ec52aSSatish Balay } 18998d2ec52aSSatish Balay } 19008d2ec52aSSatish Balay 19018d2ec52aSSatish Balay static void RanksToSizes_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt ranks[], PetscInt sizes[]) 19028d2ec52aSSatish Balay { 19038d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 19048d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 19058d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 19068d2ec52aSSatish Balay 19078d2ec52aSSatish Balay sizes[i] = ranks[i] < rem ? div + 1 : div; 19088d2ec52aSSatish Balay } 19098d2ec52aSSatish Balay } 19108d2ec52aSSatish Balay 19118d2ec52aSSatish Balay /* 19128d2ec52aSSatish 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. 19138d2ec52aSSatish Balay 19148d2ec52aSSatish 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. 19158d2ec52aSSatish Balay 19168d2ec52aSSatish 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. 1917dfe9cfe5SMatthew Knepley 1918dfe9cfe5SMatthew Knepley Parallel Layout: 1919dfe9cfe5SMatthew Knepley 1920dfe9cfe5SMatthew 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. 19218d2ec52aSSatish Balay */ 19228d2ec52aSSatish Balay static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], PetscInt overlap, const DMBoundaryType bd[]) 19238d2ec52aSSatish Balay { 19248d2ec52aSSatish Balay const PetscInt debug = ((DM_Plex *)dm->data)->printAdj; 19258d2ec52aSSatish Balay PetscSF sf; 1926cfb853baSMatthew G. Knepley Vec coordinates; 1927cfb853baSMatthew G. Knepley PetscSection coordSection; 1928cfb853baSMatthew G. Knepley DMLabel cutLabel = NULL; 1929cfb853baSMatthew G. Knepley PetscBool cutMarker = PETSC_FALSE; 1930cfb853baSMatthew G. Knepley PetscBool periodic = PETSC_FALSE; 19318d2ec52aSSatish Balay PetscInt numCells = 1; 19328d2ec52aSSatish Balay PetscInt numVertices = 1; 19338d2ec52aSSatish Balay PetscSFNode *remotes; 1934cfb853baSMatthew G. Knepley PetscScalar *coords; 19358d2ec52aSSatish Balay PetscInt *procs; // The number of processes along each dimension 19368d2ec52aSSatish Balay PetscInt *lrank; // Rank in each dimension, lrank[d] \in [0, procs[d]) 19378d2ec52aSSatish Balay PetscInt *ledges; // The number of edges along each dimension for this process 19388d2ec52aSSatish Balay PetscInt *vstart; // The first vertex along each dimension on this processes 19398d2ec52aSSatish Balay PetscInt *vertices; // The number of vertices along each dimension on this process 19408d2ec52aSSatish Balay PetscInt *rvert; // The global (not local) vertex number along each dimension 19418d2ec52aSSatish Balay PetscInt *rrank; // The rank along each dimension for the process owning rvert[] 19428d2ec52aSSatish Balay PetscInt *rvertices; // The number of vertices along each dimension for the process rrank[] 19438d2ec52aSSatish Balay PetscInt *vert, *vtmp, *supp, cone[2], *leaves; 19448d2ec52aSSatish Balay PetscInt cell = 0, coordSize, Nl = 0, Nl2 = 0; 19458d2ec52aSSatish Balay PetscMPIInt rank, size; 19468d2ec52aSSatish Balay MPI_Comm comm; 1947cfb853baSMatthew G. Knepley 1948cfb853baSMatthew G. Knepley PetscFunctionBegin; 19498d2ec52aSSatish Balay PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 19508d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_rank(comm, &rank)); 19518d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_size(comm, &size)); 1952cfb853baSMatthew G. Knepley PetscCall(DMSetDimension(dm, dim)); 19538d2ec52aSSatish Balay PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 19548d2ec52aSSatish Balay PetscCall(PetscCalloc4(dim, &procs, dim, &lrank, dim, &rrank, 2 * dim, &supp)); 19558d2ec52aSSatish Balay PetscCall(PetscCalloc7(dim, &ledges, dim, &vertices, dim, &rvertices, dim, &vert, dim, &rvert, dim, &vstart, dim, &vtmp)); 1956cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 1957cfb853baSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 19588d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE; 1959cfb853baSMatthew G. Knepley if (periodic && cutMarker) { 1960cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "periodic_cut")); 1961cfb853baSMatthew G. Knepley PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 1962cfb853baSMatthew G. Knepley } 19638d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, comm, PETSC_ERR_SUP, "Hypercubic mesh must be periodic now"); 19648d2ec52aSSatish Balay overlap = overlap == PETSC_DETERMINE ? 1 : overlap; 19658d2ec52aSSatish Balay PetscCheck(overlap >= 1, comm, PETSC_ERR_SUP, "Overlap %" PetscInt_FMT " must be greater than 0", overlap); 19668d2ec52aSSatish Balay if (size > 1) { 19678d2ec52aSSatish Balay PetscInt Npr = 1; 19688d2ec52aSSatish Balay 19698d2ec52aSSatish Balay // Make process grid 19708d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "Process grid:")); 19718d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 19728d2ec52aSSatish Balay procs[d] = PetscRintReal(PetscPowReal(size, 1. / dim)); 19738d2ec52aSSatish Balay Npr *= procs[d]; 19748d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, " %" PetscInt_FMT, procs[d])); 19758d2ec52aSSatish Balay } 19768d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "\n")); 19778d2ec52aSSatish Balay PetscCheck(Npr == size, comm, PETSC_ERR_PLIB, "Process grid size %" PetscInt_FMT " != %d comm size", Npr, size); 19788d2ec52aSSatish Balay IndexToTuple_Private(dim, procs, rank, lrank); 19798d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 19808d2ec52aSSatish Balay ledges[d] = edges[d] / procs[d] + (edges[d] % procs[d] > lrank[d] ? 1 : 0); 19818d2ec52aSSatish Balay vstart[d] = 0; 19828d2ec52aSSatish Balay for (PetscInt r = 0; r < lrank[d]; ++r) vstart[d] += edges[d] / procs[d] + (edges[d] % procs[d] > r ? 1 : 0); 19838d2ec52aSSatish Balay vstart[d] -= overlap; // For halo 19848d2ec52aSSatish Balay } 19858d2ec52aSSatish Balay } else { 19868d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 19878d2ec52aSSatish Balay procs[d] = 1; 19888d2ec52aSSatish Balay ledges[d] = edges[d]; 19898d2ec52aSSatish Balay } 19908d2ec52aSSatish Balay } 19918d2ec52aSSatish Balay // Calculate local patch size 19928d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 19938d2ec52aSSatish Balay vertices[d] = ledges[d] + (procs[d] > 1 ? 2 * overlap : 0); 1994cfb853baSMatthew G. Knepley numVertices *= vertices[d]; 1995cfb853baSMatthew G. Knepley } 1996cfb853baSMatthew G. Knepley numCells = numVertices * dim; 1997cfb853baSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 19988d2ec52aSSatish Balay for (PetscInt c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2)); 19998d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim)); 2000cfb853baSMatthew G. Knepley PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */ 2001cfb853baSMatthew G. Knepley /* Build cell cones and vertex supports */ 2002cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "celltype")); 20038d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Topology for rank %d:\n", rank)); 2004cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2005cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells; 2006cfb853baSMatthew G. Knepley PetscInt s = 0; 20078d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2008cfb853baSMatthew G. Knepley 20098d2ec52aSSatish Balay if (debug) { 20108d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 20118d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d])); 20128d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 20138d2ec52aSSatish Balay } 2014cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT)); 20158d2ec52aSSatish Balay // Define edge cones 20168d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 20178d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2018cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + 1) % vertices[d]; 2019cfb853baSMatthew G. Knepley cone[0] = vertex; 2020cfb853baSMatthew G. Knepley cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells; 20218d2ec52aSSatish Balay if (debug) { 20228d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ":", cone[1])); 20238d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vtmp[e])); 20248d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 20258d2ec52aSSatish Balay } 2026cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, cell, cone)); 2027cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT)); 20288d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1])); 2029cfb853baSMatthew G. Knepley ++cell; 20308d2ec52aSSatish Balay // Shared vertices are any in the first or last overlap layers 20318d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 2032cfb853baSMatthew G. Knepley } 20338d2ec52aSSatish Balay if (size > 1 && leaf) ++Nl; 20348d2ec52aSSatish Balay // Define vertex supports 20358d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 20368d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2037cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + vertices[d] - 1) % vertices[d]; 2038cfb853baSMatthew G. Knepley supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d; 2039cfb853baSMatthew G. Knepley supp[s++] = (vertex - numCells) * dim + d; 2040cfb853baSMatthew G. Knepley PetscCall(DMPlexSetSupport(dm, vertex, supp)); 2041cfb853baSMatthew G. Knepley } 2042cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2043cfb853baSMatthew G. Knepley } 20448d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2045cfb853baSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 20468d2ec52aSSatish Balay // Allocate for SF 20478d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &leaves)); 20488d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &remotes)); 20498d2ec52aSSatish Balay // Build coordinates 2050cfb853baSMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 2051cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(coordSection, 1)); 2052cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 2053cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 20548d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) { 2055cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetDof(coordSection, v, dim)); 2056cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 2057cfb853baSMatthew G. Knepley } 2058cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetUp(coordSection)); 2059cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 20608d2ec52aSSatish Balay PetscCall(VecCreate(comm, &coordinates)); 2061cfb853baSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 2062cfb853baSMatthew G. Knepley PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 2063cfb853baSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinates, dim)); 2064cfb853baSMatthew G. Knepley PetscCall(VecSetType(coordinates, VECSTANDARD)); 2065cfb853baSMatthew G. Knepley PetscCall(VecGetArray(coordinates, &coords)); 20668d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Geometry for rank %d:\n", rank)); 20678d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) vert[d] = 0; 2068cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2069cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert); 20708d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2071cfb853baSMatthew G. Knepley 20728d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 20738d2ec52aSSatish Balay coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / edges[d]) * (vert[d] + vstart[d]); 20748d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 20758d2ec52aSSatish Balay } 20768d2ec52aSSatish Balay if (size > 1 && leaf) { 20778d2ec52aSSatish Balay PetscInt rnumCells = 1; 20788d2ec52aSSatish Balay 20798d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) rvert[d] = vert[d] + vstart[d]; 20808d2ec52aSSatish Balay TupleToRanks_Private(dim, edges, procs, rvert, rrank); 20818d2ec52aSSatish Balay leaves[Nl2] = vertex + numCells; 20828d2ec52aSSatish Balay remotes[Nl2].rank = TupleToIndex_Private(dim, procs, rrank); 20838d2ec52aSSatish Balay RanksToSizes_Private(dim, edges, procs, rrank, rvertices); 20848d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 20858d2ec52aSSatish Balay rvertices[d] += 2 * overlap; // Add halo 20868d2ec52aSSatish Balay rnumCells *= rvertices[d]; 20878d2ec52aSSatish Balay } 20888d2ec52aSSatish Balay rnumCells *= dim; 20898d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 20908d2ec52aSSatish Balay const PetscInt diff = rrank[d] - lrank[d]; 20918d2ec52aSSatish Balay 20928d2ec52aSSatish Balay if (!diff) rvert[d] = vert[d]; // Vertex is local 20938d2ec52aSSatish Balay else if (rvert[d] < 0) rvert[d] = rvertices[d] - 1 + rvert[d]; // Wrap around at the bottom 20948d2ec52aSSatish Balay else if (rvert[d] >= edges[d]) rvert[d] = rvert[d] - edges[d] + 1; // Wrap around at the top 20958d2ec52aSSatish Balay else if (diff == -1) rvert[d] = rvertices[d] - 1 + (vert[d] - overlap); 20968d2ec52aSSatish Balay else if (diff == 1) rvert[d] = (vertices[d] - vert[d] - 1) + overlap; 20978d2ec52aSSatish Balay else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Process distance %" PetscInt_FMT " in direction %" PetscInt_FMT " should not be possible", diff, d); 20988d2ec52aSSatish Balay } 20998d2ec52aSSatish Balay remotes[Nl2].index = TupleToIndex_Private(dim, rvertices, rvert) + rnumCells; 21008d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Shared Vertex %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", leaves[Nl2], remotes[Nl2].rank, remotes[Nl2].index)); 21018d2ec52aSSatish Balay ++Nl2; 21028d2ec52aSSatish Balay } 21038d2ec52aSSatish Balay if (debug) { 21048d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 21058d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d] + vstart[d])); 21068d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %g", (double)PetscRealPart(coords[vertex * dim + d]))); 21078d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 21088d2ec52aSSatish Balay } 2109cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2110cfb853baSMatthew G. Knepley } 21118d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2112cfb853baSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &coords)); 2113cfb853baSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 2114cfb853baSMatthew G. Knepley PetscCall(VecDestroy(&coordinates)); 21158d2ec52aSSatish Balay // Build SF 21168d2ec52aSSatish Balay PetscCheck(Nl == Nl2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Initial number of leaves %" PetscInt_FMT " != %" PetscInt_FMT " final number", Nl, Nl2); 21178d2ec52aSSatish Balay PetscCall(DMGetPointSF(dm, &sf)); 21188d2ec52aSSatish Balay PetscCall(PetscSFSetGraph(sf, numCells + numVertices, Nl, leaves, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 21198d2ec52aSSatish Balay if (debug) PetscCall(PetscSFView(sf, PETSC_VIEWER_STDOUT_WORLD)); 2120cfb853baSMatthew G. Knepley //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper)); 2121cfb853baSMatthew G. Knepley // Attach the extent 2122cfb853baSMatthew G. Knepley { 2123cfb853baSMatthew G. Knepley PetscContainer c; 21248d2ec52aSSatish Balay PetscInt *extent, *lextent; 2125cfb853baSMatthew G. Knepley 2126cfb853baSMatthew G. Knepley PetscCall(PetscMalloc1(dim, &extent)); 21278d2ec52aSSatish Balay PetscCall(PetscMalloc1(dim, &lextent)); 21288d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 21298d2ec52aSSatish Balay extent[d] = edges[d]; 21308d2ec52aSSatish Balay lextent[d] = ledges[d]; 21318d2ec52aSSatish Balay } 2132cfb853baSMatthew G. Knepley PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 213349abdd8aSBarry Smith PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 2134cfb853baSMatthew G. Knepley PetscCall(PetscContainerSetPointer(c, extent)); 2135cfb853baSMatthew G. Knepley PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c)); 2136cfb853baSMatthew G. Knepley PetscCall(PetscContainerDestroy(&c)); 21378d2ec52aSSatish Balay PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 21388d2ec52aSSatish Balay PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 21398d2ec52aSSatish Balay PetscCall(PetscContainerSetPointer(c, lextent)); 21408d2ec52aSSatish Balay PetscCall(PetscObjectCompose((PetscObject)dm, "_lextent", (PetscObject)c)); 21418d2ec52aSSatish Balay PetscCall(PetscContainerDestroy(&c)); 2142cfb853baSMatthew G. Knepley } 21438d2ec52aSSatish Balay PetscCall(PetscFree4(procs, lrank, rrank, supp)); 21448d2ec52aSSatish Balay PetscCall(PetscFree7(ledges, vertices, rvertices, vert, rvert, vstart, vtmp)); 21453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2146cfb853baSMatthew G. Knepley } 2147cfb853baSMatthew G. Knepley 2148cfb853baSMatthew G. Knepley /*@C 2149aaa8cc7dSPierre Jolivet DMPlexCreateHypercubicMesh - Creates a periodic mesh on the tensor product of unit intervals using only vertices and edges. 2150cfb853baSMatthew G. Knepley 2151cfb853baSMatthew G. Knepley Collective 2152cfb853baSMatthew G. Knepley 2153cfb853baSMatthew G. Knepley Input Parameters: 21548d2ec52aSSatish Balay + comm - The communicator for the `DM` object 2155cfb853baSMatthew G. Knepley . dim - The spatial dimension 215620f4b53cSBarry Smith . edges - Number of edges per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 215720f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 21588d2ec52aSSatish Balay . upper - The upper right corner, or `NULL` for (1, 1, 1) 21598d2ec52aSSatish Balay - overlap - The number of vertices in each direction to include in the overlap (default is 1) 2160cfb853baSMatthew G. Knepley 2161cfb853baSMatthew G. Knepley Output Parameter: 2162cfb853baSMatthew G. Knepley . dm - The DM object 2163cfb853baSMatthew G. Knepley 216420f4b53cSBarry Smith Level: beginner 216520f4b53cSBarry Smith 216620f4b53cSBarry Smith Note: 216720f4b53cSBarry Smith If you want to customize this mesh using options, you just need to 216820f4b53cSBarry Smith .vb 216920f4b53cSBarry Smith DMCreate(comm, &dm); 217020f4b53cSBarry Smith DMSetType(dm, DMPLEX); 217120f4b53cSBarry Smith DMSetFromOptions(dm); 217220f4b53cSBarry Smith .ve 217320f4b53cSBarry Smith and use the options on the `DMSetFromOptions()` page. 2174cfb853baSMatthew G. Knepley 2175cfb853baSMatthew G. Knepley The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively, 217620f4b53cSBarry Smith .vb 217720f4b53cSBarry Smith 18--0-19--2-20--4-18 217820f4b53cSBarry Smith | | | | 217920f4b53cSBarry Smith 13 15 17 13 218020f4b53cSBarry Smith | | | | 218120f4b53cSBarry Smith 24-12-25-14-26-16-24 218220f4b53cSBarry Smith | | | | 218320f4b53cSBarry Smith 7 9 11 7 218420f4b53cSBarry Smith | | | | 218520f4b53cSBarry Smith 21--6-22--8-23-10-21 218620f4b53cSBarry Smith | | | | 218720f4b53cSBarry Smith 1 3 5 1 218820f4b53cSBarry Smith | | | | 218920f4b53cSBarry Smith 18--0-19--2-20--4-18 219020f4b53cSBarry Smith .ve 2191cfb853baSMatthew G. Knepley 219276fbde31SPierre Jolivet .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 2193cfb853baSMatthew G. Knepley @*/ 21948d2ec52aSSatish Balay PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], PetscInt overlap, DM *dm) 2195cfb853baSMatthew G. Knepley { 2196cfb853baSMatthew G. Knepley PetscInt *edg; 2197cfb853baSMatthew G. Knepley PetscReal *low, *upp; 2198cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 2199cfb853baSMatthew G. Knepley PetscInt d; 2200cfb853baSMatthew G. Knepley 2201cfb853baSMatthew G. Knepley PetscFunctionBegin; 2202cfb853baSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 2203cfb853baSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 2204cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt)); 2205cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 2206cfb853baSMatthew G. Knepley edg[d] = edges ? edges[d] : 1; 2207cfb853baSMatthew G. Knepley low[d] = lower ? lower[d] : 0.; 2208cfb853baSMatthew G. Knepley upp[d] = upper ? upper[d] : 1.; 2209cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 2210cfb853baSMatthew G. Knepley } 22118d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, overlap, bdt)); 2212cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edg, low, upp, bdt)); 22133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2214cfb853baSMatthew G. Knepley } 2215cfb853baSMatthew G. Knepley 2216cc4c1da9SBarry Smith /*@ 2217a1cb98faSBarry Smith DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database. 2218a9074c1eSMatthew G. Knepley 221920f4b53cSBarry Smith Logically Collective 2220a9074c1eSMatthew G. Knepley 2221a9074c1eSMatthew G. Knepley Input Parameters: 222220f4b53cSBarry Smith + dm - the `DM` context 2223a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 2224a9074c1eSMatthew G. Knepley 2225a1cb98faSBarry Smith Level: advanced 2226a1cb98faSBarry Smith 2227a1cb98faSBarry Smith Note: 2228a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 2229a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 2230a9074c1eSMatthew G. Knepley 22311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()` 2232a9074c1eSMatthew G. Knepley @*/ 2233d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 2234d71ae5a4SJacob Faibussowitsch { 2235a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2236a9074c1eSMatthew G. Knepley 2237a9074c1eSMatthew G. Knepley PetscFunctionBegin; 2238a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 22399566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 22409566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 22413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2242a9074c1eSMatthew G. Knepley } 2243a9074c1eSMatthew G. Knepley 22449318fe57SMatthew G. Knepley /* Remap geometry to cylinder 224561a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 224661a622f3SMatthew G. Knepley 22479318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 22489318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 22499318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 22500510c589SMatthew G. Knepley 22519318fe57SMatthew G. Knepley phi = arctan(y/x) 22529318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 22539318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 22540510c589SMatthew G. Knepley 22559318fe57SMatthew G. Knepley so we remap them using 22560510c589SMatthew G. Knepley 22579318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 22589318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 22590510c589SMatthew G. Knepley 22609318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 22619318fe57SMatthew G. Knepley */ 2262d71ae5a4SJacob 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[]) 2263d71ae5a4SJacob Faibussowitsch { 22649318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 22659318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 226622cc497dSMatthew G. Knepley 22679318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 22689318fe57SMatthew G. Knepley f0[0] = u[0]; 22699318fe57SMatthew G. Knepley f0[1] = u[1]; 22709318fe57SMatthew G. Knepley } else { 22719318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 22720510c589SMatthew G. Knepley 22739318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 22749318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 22759318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 22769318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 22779318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 22789318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 22799318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 22809318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 22819318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 22829318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 22839318fe57SMatthew G. Knepley } else { 22849318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 22859318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 22869318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 22879318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 22889318fe57SMatthew G. Knepley } 22899318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 22909318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 22919318fe57SMatthew G. Knepley } 22929318fe57SMatthew G. Knepley f0[2] = u[2]; 22939318fe57SMatthew G. Knepley } 22940510c589SMatthew G. Knepley 229549704ca5SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ, PetscInt Nr) 2296d71ae5a4SJacob Faibussowitsch { 22970510c589SMatthew G. Knepley const PetscInt dim = 3; 22989318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 2299d8c47e87SMatthew G. Knepley PetscMPIInt rank; 23000510c589SMatthew G. Knepley 23010510c589SMatthew G. Knepley PetscFunctionBegin; 230246139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 23039566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 23049566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 23050510c589SMatthew G. Knepley /* Create topology */ 23060510c589SMatthew G. Knepley { 23070510c589SMatthew G. Knepley PetscInt cone[8], c; 23080510c589SMatthew G. Knepley 2309dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 2310dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 2311006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 2312ae8bcbbbSMatthew G. Knepley numCells *= 3; 2313dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 2314006a8963SMatthew G. Knepley } 23159566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 23169566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 23179566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 2318dd400576SPatrick Sanan if (rank == 0) { 2319006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 23209371c9d4SSatish Balay cone[0] = 15; 23219371c9d4SSatish Balay cone[1] = 18; 23229371c9d4SSatish Balay cone[2] = 17; 23239371c9d4SSatish Balay cone[3] = 16; 23249371c9d4SSatish Balay cone[4] = 31; 23259371c9d4SSatish Balay cone[5] = 32; 23269371c9d4SSatish Balay cone[6] = 33; 23279371c9d4SSatish Balay cone[7] = 34; 23289566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 23299371c9d4SSatish Balay cone[0] = 16; 23309371c9d4SSatish Balay cone[1] = 17; 23319371c9d4SSatish Balay cone[2] = 24; 23329371c9d4SSatish Balay cone[3] = 23; 23339371c9d4SSatish Balay cone[4] = 32; 23349371c9d4SSatish Balay cone[5] = 36; 23359371c9d4SSatish Balay cone[6] = 37; 23369371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 23379566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 23389371c9d4SSatish Balay cone[0] = 18; 23399371c9d4SSatish Balay cone[1] = 27; 23409371c9d4SSatish Balay cone[2] = 24; 23419371c9d4SSatish Balay cone[3] = 17; 23429371c9d4SSatish Balay cone[4] = 34; 23439371c9d4SSatish Balay cone[5] = 33; 23449371c9d4SSatish Balay cone[6] = 37; 23459371c9d4SSatish Balay cone[7] = 38; 23469566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 23479371c9d4SSatish Balay cone[0] = 29; 23489371c9d4SSatish Balay cone[1] = 27; 23499371c9d4SSatish Balay cone[2] = 18; 23509371c9d4SSatish Balay cone[3] = 15; 23519371c9d4SSatish Balay cone[4] = 35; 23529371c9d4SSatish Balay cone[5] = 31; 23539371c9d4SSatish Balay cone[6] = 34; 23549371c9d4SSatish Balay cone[7] = 38; 23559566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 23569371c9d4SSatish Balay cone[0] = 29; 23579371c9d4SSatish Balay cone[1] = 15; 23589371c9d4SSatish Balay cone[2] = 16; 23599371c9d4SSatish Balay cone[3] = 23; 23609371c9d4SSatish Balay cone[4] = 35; 23619371c9d4SSatish Balay cone[5] = 36; 23629371c9d4SSatish Balay cone[6] = 32; 23639371c9d4SSatish Balay cone[7] = 31; 23649566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2365006a8963SMatthew G. Knepley 23669371c9d4SSatish Balay cone[0] = 31; 23679371c9d4SSatish Balay cone[1] = 34; 23689371c9d4SSatish Balay cone[2] = 33; 23699371c9d4SSatish Balay cone[3] = 32; 23709371c9d4SSatish Balay cone[4] = 19; 23719371c9d4SSatish Balay cone[5] = 22; 23729371c9d4SSatish Balay cone[6] = 21; 23739371c9d4SSatish Balay cone[7] = 20; 23749566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 23759371c9d4SSatish Balay cone[0] = 32; 23769371c9d4SSatish Balay cone[1] = 33; 23779371c9d4SSatish Balay cone[2] = 37; 23789371c9d4SSatish Balay cone[3] = 36; 23799371c9d4SSatish Balay cone[4] = 22; 23809371c9d4SSatish Balay cone[5] = 25; 23819371c9d4SSatish Balay cone[6] = 26; 23829371c9d4SSatish Balay cone[7] = 21; 23839566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 23849371c9d4SSatish Balay cone[0] = 34; 23859371c9d4SSatish Balay cone[1] = 38; 23869371c9d4SSatish Balay cone[2] = 37; 23879371c9d4SSatish Balay cone[3] = 33; 23889371c9d4SSatish Balay cone[4] = 20; 23899371c9d4SSatish Balay cone[5] = 21; 23909371c9d4SSatish Balay cone[6] = 26; 23919371c9d4SSatish Balay cone[7] = 28; 23929566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 23939371c9d4SSatish Balay cone[0] = 35; 23949371c9d4SSatish Balay cone[1] = 38; 23959371c9d4SSatish Balay cone[2] = 34; 23969371c9d4SSatish Balay cone[3] = 31; 23979371c9d4SSatish Balay cone[4] = 30; 23989371c9d4SSatish Balay cone[5] = 19; 23999371c9d4SSatish Balay cone[6] = 20; 24009371c9d4SSatish Balay cone[7] = 28; 24019566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 24029371c9d4SSatish Balay cone[0] = 35; 24039371c9d4SSatish Balay cone[1] = 31; 24049371c9d4SSatish Balay cone[2] = 32; 24059371c9d4SSatish Balay cone[3] = 36; 24069371c9d4SSatish Balay cone[4] = 30; 24079371c9d4SSatish Balay cone[5] = 25; 24089371c9d4SSatish Balay cone[6] = 22; 24099371c9d4SSatish Balay cone[7] = 19; 24109566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 2411ae8bcbbbSMatthew G. Knepley 24129371c9d4SSatish Balay cone[0] = 19; 24139371c9d4SSatish Balay cone[1] = 20; 24149371c9d4SSatish Balay cone[2] = 21; 24159371c9d4SSatish Balay cone[3] = 22; 24169371c9d4SSatish Balay cone[4] = 15; 24179371c9d4SSatish Balay cone[5] = 16; 24189371c9d4SSatish Balay cone[6] = 17; 24199371c9d4SSatish Balay cone[7] = 18; 24209566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 24219371c9d4SSatish Balay cone[0] = 22; 24229371c9d4SSatish Balay cone[1] = 21; 24239371c9d4SSatish Balay cone[2] = 26; 24249371c9d4SSatish Balay cone[3] = 25; 24259371c9d4SSatish Balay cone[4] = 16; 24269371c9d4SSatish Balay cone[5] = 23; 24279371c9d4SSatish Balay cone[6] = 24; 24289371c9d4SSatish Balay cone[7] = 17; 24299566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 24309371c9d4SSatish Balay cone[0] = 20; 24319371c9d4SSatish Balay cone[1] = 28; 24329371c9d4SSatish Balay cone[2] = 26; 24339371c9d4SSatish Balay cone[3] = 21; 24349371c9d4SSatish Balay cone[4] = 18; 24359371c9d4SSatish Balay cone[5] = 17; 24369371c9d4SSatish Balay cone[6] = 24; 24379371c9d4SSatish Balay cone[7] = 27; 24389566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 24399371c9d4SSatish Balay cone[0] = 30; 24409371c9d4SSatish Balay cone[1] = 28; 24419371c9d4SSatish Balay cone[2] = 20; 24429371c9d4SSatish Balay cone[3] = 19; 24439371c9d4SSatish Balay cone[4] = 29; 24449371c9d4SSatish Balay cone[5] = 15; 24459371c9d4SSatish Balay cone[6] = 18; 24469371c9d4SSatish Balay cone[7] = 27; 24479566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 24489371c9d4SSatish Balay cone[0] = 30; 24499371c9d4SSatish Balay cone[1] = 19; 24509371c9d4SSatish Balay cone[2] = 22; 24519371c9d4SSatish Balay cone[3] = 25; 24529371c9d4SSatish Balay cone[4] = 29; 24539371c9d4SSatish Balay cone[5] = 23; 24549371c9d4SSatish Balay cone[6] = 16; 24559371c9d4SSatish Balay cone[7] = 15; 24569566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 2457006a8963SMatthew G. Knepley } else { 24589371c9d4SSatish Balay cone[0] = 5; 24599371c9d4SSatish Balay cone[1] = 8; 24609371c9d4SSatish Balay cone[2] = 7; 24619371c9d4SSatish Balay cone[3] = 6; 24629371c9d4SSatish Balay cone[4] = 9; 24639371c9d4SSatish Balay cone[5] = 12; 24649371c9d4SSatish Balay cone[6] = 11; 24659371c9d4SSatish Balay cone[7] = 10; 24669566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 24679371c9d4SSatish Balay cone[0] = 6; 24689371c9d4SSatish Balay cone[1] = 7; 24699371c9d4SSatish Balay cone[2] = 14; 24709371c9d4SSatish Balay cone[3] = 13; 24719371c9d4SSatish Balay cone[4] = 12; 24729371c9d4SSatish Balay cone[5] = 15; 24739371c9d4SSatish Balay cone[6] = 16; 24749371c9d4SSatish Balay cone[7] = 11; 24759566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 24769371c9d4SSatish Balay cone[0] = 8; 24779371c9d4SSatish Balay cone[1] = 17; 24789371c9d4SSatish Balay cone[2] = 14; 24799371c9d4SSatish Balay cone[3] = 7; 24809371c9d4SSatish Balay cone[4] = 10; 24819371c9d4SSatish Balay cone[5] = 11; 24829371c9d4SSatish Balay cone[6] = 16; 24839371c9d4SSatish Balay cone[7] = 18; 24849566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 24859371c9d4SSatish Balay cone[0] = 19; 24869371c9d4SSatish Balay cone[1] = 17; 24879371c9d4SSatish Balay cone[2] = 8; 24889371c9d4SSatish Balay cone[3] = 5; 24899371c9d4SSatish Balay cone[4] = 20; 24909371c9d4SSatish Balay cone[5] = 9; 24919371c9d4SSatish Balay cone[6] = 10; 24929371c9d4SSatish Balay cone[7] = 18; 24939566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 24949371c9d4SSatish Balay cone[0] = 19; 24959371c9d4SSatish Balay cone[1] = 5; 24969371c9d4SSatish Balay cone[2] = 6; 24979371c9d4SSatish Balay cone[3] = 13; 24989371c9d4SSatish Balay cone[4] = 20; 24999371c9d4SSatish Balay cone[5] = 15; 25009371c9d4SSatish Balay cone[6] = 12; 25019371c9d4SSatish Balay cone[7] = 9; 25029566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2503006a8963SMatthew G. Knepley } 2504d8c47e87SMatthew G. Knepley } 25059566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 25069566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 25070510c589SMatthew G. Knepley } 2508dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 25090510c589SMatthew G. Knepley { 25100510c589SMatthew G. Knepley Vec coordinates; 25110510c589SMatthew G. Knepley PetscSection coordSection; 25120510c589SMatthew G. Knepley PetscScalar *coords; 25130510c589SMatthew G. Knepley PetscInt coordSize, v; 25140510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 25150510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 25160510c589SMatthew G. Knepley 25170510c589SMatthew G. Knepley /* Build coordinates */ 25189566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 25199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 25209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 25219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 25220510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 25239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 25249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 25250510c589SMatthew G. Knepley } 25269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 25279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 25289566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 25299566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 25309566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 25319566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 25329566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 25339566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 2534dd400576SPatrick Sanan if (rank == 0) { 25359371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 25369371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 25379371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 25389371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 25399371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 25409371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 25419371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 25429371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 25439371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 25449371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 25459371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 25469371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 25479371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 25489371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 25499371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 25509371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 25519371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 25529371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 25539371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 25549371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 25559371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 25569371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 25579371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 25589371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 25599371c9d4SSatish Balay coords[8 * dim + 0] = dis; 25609371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 25619371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 25629371c9d4SSatish Balay coords[9 * dim + 0] = dis; 25639371c9d4SSatish Balay coords[9 * dim + 1] = dis; 25649371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 25659371c9d4SSatish Balay coords[10 * dim + 0] = dis; 25669371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 25679371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 25689371c9d4SSatish Balay coords[11 * dim + 0] = dis; 25699371c9d4SSatish Balay coords[11 * dim + 1] = dis; 25709371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 25719371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 25729371c9d4SSatish Balay coords[12 * dim + 1] = dis; 25739371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 25749371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 25759371c9d4SSatish Balay coords[13 * dim + 1] = dis; 25769371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 25779371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 25789371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 25799371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 25809371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 25819371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 25829371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 2583ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 25849371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 25859371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 25869371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 25879371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 25889371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 25899371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 25909371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 25919371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 25929371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 25939371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 25949371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 25959371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 25969371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 25979371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 25989371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 25999371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 26009371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 26019371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 26029371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 26039371c9d4SSatish Balay coords[22 * dim + 1] = dis; 26049371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 26059371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 26069371c9d4SSatish Balay coords[23 * dim + 1] = dis; 26079371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 2608ae8bcbbbSMatthew G. Knepley } 2609d8c47e87SMatthew G. Knepley } 26109566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 26119566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 26129566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 26130510c589SMatthew G. Knepley } 2614006a8963SMatthew G. Knepley /* Create periodicity */ 2615006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 26166858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 26176858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 2618006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 2619ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 26206858538eSMatthew G. Knepley PetscInt numZCells = 3; 2621006a8963SMatthew G. Knepley 26226858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 26236858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 26244fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 2625006a8963SMatthew G. Knepley } 2626dbc1dc17SMatthew G. Knepley { 26279318fe57SMatthew G. Knepley DM cdm; 26289318fe57SMatthew G. Knepley PetscDS cds; 26299318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 2630dbc1dc17SMatthew G. Knepley 263149704ca5SMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL)); 26329566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 26339566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 26349566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 2635dbc1dc17SMatthew G. Knepley } 263646139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 263746139095SJed Brown 26389318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 26399566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 264049704ca5SMatthew G. Knepley 264149704ca5SMatthew G. Knepley char oldprefix[PETSC_MAX_PATH_LEN]; 264249704ca5SMatthew G. Knepley const char *prefix; 264349704ca5SMatthew G. Knepley 264449704ca5SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 264549704ca5SMatthew G. Knepley PetscCall(PetscStrncpy(oldprefix, prefix, PETSC_MAX_PATH_LEN)); 264649704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, "petsc_cyl_ref_")); 264749704ca5SMatthew G. Knepley for (PetscInt r = 0; r < PetscMax(0, Nr); ++r) { 264849704ca5SMatthew G. Knepley DM rdm; 264949704ca5SMatthew G. Knepley 265049704ca5SMatthew G. Knepley PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 265149704ca5SMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &rdm)); 265249704ca5SMatthew G. Knepley } 265349704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldprefix)); 265449704ca5SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, snapToCylinder)); 265549704ca5SMatthew G. Knepley 265649704ca5SMatthew G. Knepley DMLabel bdlabel, edgelabel; 265749704ca5SMatthew G. Knepley IS faceIS; 265849704ca5SMatthew G. Knepley const PetscInt *faces; 265949704ca5SMatthew G. Knepley PetscInt Nf; 266049704ca5SMatthew G. Knepley 266149704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 266249704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 266349704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "generatrix")); 266449704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "generatrix", &edgelabel)); 266549704ca5SMatthew G. Knepley PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 266649704ca5SMatthew G. Knepley // Remove faces on top and bottom 266749704ca5SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(bdlabel, 1, &faceIS)); 2668ba1b3593SJeremy L Thompson if (faceIS) { 266949704ca5SMatthew G. Knepley PetscCall(ISGetLocalSize(faceIS, &Nf)); 267049704ca5SMatthew G. Knepley PetscCall(ISGetIndices(faceIS, &faces)); 267149704ca5SMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 267249704ca5SMatthew G. Knepley PetscReal vol, normal[3]; 267349704ca5SMatthew G. Knepley 267449704ca5SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFVM(dm, faces[f], &vol, NULL, normal)); 267549704ca5SMatthew G. Knepley if (PetscAbsReal(normal[2]) < PETSC_SMALL) PetscCall(DMLabelSetValue(edgelabel, faces[f], 1)); 267649704ca5SMatthew G. Knepley } 267749704ca5SMatthew G. Knepley PetscCall(ISRestoreIndices(faceIS, &faces)); 267849704ca5SMatthew G. Knepley PetscCall(ISDestroy(&faceIS)); 2679ba1b3593SJeremy L Thompson } 268049704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, bdlabel)); 268149704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, edgelabel)); 26823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 26830510c589SMatthew G. Knepley } 26840510c589SMatthew G. Knepley 268524119c2aSMatthew G. Knepley /*@ 26869318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 268724119c2aSMatthew G. Knepley 2688d083f849SBarry Smith Collective 268924119c2aSMatthew G. Knepley 269024119c2aSMatthew G. Knepley Input Parameters: 2691a1cb98faSBarry Smith + comm - The communicator for the `DM` object 269249704ca5SMatthew G. Knepley . periodicZ - The boundary type for the Z direction 269349704ca5SMatthew G. Knepley - Nr - The number of refinements to carry out 269424119c2aSMatthew G. Knepley 269524119c2aSMatthew G. Knepley Output Parameter: 269620f4b53cSBarry Smith . dm - The `DM` object 269724119c2aSMatthew G. Knepley 269824119c2aSMatthew G. Knepley Level: beginner 269924119c2aSMatthew G. Knepley 2700a1cb98faSBarry Smith Note: 2701a4e35b19SJacob Faibussowitsch Here is the output numbering looking from the bottom of the cylinder\: 2702a1cb98faSBarry Smith .vb 2703a1cb98faSBarry Smith 17-----14 2704a1cb98faSBarry Smith | | 2705a1cb98faSBarry Smith | 2 | 2706a1cb98faSBarry Smith | | 2707a1cb98faSBarry Smith 17-----8-----7-----14 2708a1cb98faSBarry Smith | | | | 2709a1cb98faSBarry Smith | 3 | 0 | 1 | 2710a1cb98faSBarry Smith | | | | 2711a1cb98faSBarry Smith 19-----5-----6-----13 2712a1cb98faSBarry Smith | | 2713a1cb98faSBarry Smith | 4 | 2714a1cb98faSBarry Smith | | 2715a1cb98faSBarry Smith 19-----13 2716a1cb98faSBarry Smith 2717a1cb98faSBarry Smith and up through the top 2718a1cb98faSBarry Smith 2719a1cb98faSBarry Smith 18-----16 2720a1cb98faSBarry Smith | | 2721a1cb98faSBarry Smith | 2 | 2722a1cb98faSBarry Smith | | 2723a1cb98faSBarry Smith 18----10----11-----16 2724a1cb98faSBarry Smith | | | | 2725a1cb98faSBarry Smith | 3 | 0 | 1 | 2726a1cb98faSBarry Smith | | | | 2727a1cb98faSBarry Smith 20-----9----12-----15 2728a1cb98faSBarry Smith | | 2729a1cb98faSBarry Smith | 4 | 2730a1cb98faSBarry Smith | | 2731a1cb98faSBarry Smith 20-----15 2732a1cb98faSBarry Smith .ve 2733a1cb98faSBarry Smith 27341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 273524119c2aSMatthew G. Knepley @*/ 273649704ca5SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, PetscInt Nr, DM *dm) 2737d71ae5a4SJacob Faibussowitsch { 27389318fe57SMatthew G. Knepley PetscFunctionBegin; 273949704ca5SMatthew G. Knepley PetscAssertPointer(dm, 4); 27409566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 27419566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 274249704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ, Nr)); 27433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27449318fe57SMatthew G. Knepley } 27459318fe57SMatthew G. Knepley 2746d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 2747d71ae5a4SJacob Faibussowitsch { 274824119c2aSMatthew G. Knepley const PetscInt dim = 3; 2749412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 27509fe9f049SMatthew G. Knepley PetscMPIInt rank; 275124119c2aSMatthew G. Knepley 275224119c2aSMatthew G. Knepley PetscFunctionBegin; 275363a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 275446139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 27559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 27569566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 2757412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 27589566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 275924119c2aSMatthew G. Knepley /* Create topology */ 276024119c2aSMatthew G. Knepley { 276124119c2aSMatthew G. Knepley PetscInt cone[6], c; 276224119c2aSMatthew G. Knepley 2763dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 2764dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 27659566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 27669566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 27679566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 276824119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 27699371c9d4SSatish Balay cone[0] = c + n * 1; 27709371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 27719371c9d4SSatish Balay cone[2] = 0 + 3 * n; 27729371c9d4SSatish Balay cone[3] = c + n * 2; 27739371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 27749371c9d4SSatish Balay cone[5] = 1 + 3 * n; 27759566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 27769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 277724119c2aSMatthew G. Knepley } 27789566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 27799566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 278024119c2aSMatthew G. Knepley } 278148a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 278224119c2aSMatthew G. Knepley /* Create cylinder geometry */ 278324119c2aSMatthew G. Knepley { 278424119c2aSMatthew G. Knepley Vec coordinates; 278524119c2aSMatthew G. Knepley PetscSection coordSection; 278624119c2aSMatthew G. Knepley PetscScalar *coords; 2787412e9a14SMatthew G. Knepley PetscInt coordSize, c; 278824119c2aSMatthew G. Knepley 278924119c2aSMatthew G. Knepley /* Build coordinates */ 27909566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 27919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 27929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 27939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 279424119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 27959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 27969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 279724119c2aSMatthew G. Knepley } 27989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 27999566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 28009566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 28019566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 28029566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 28039566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 28049566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 28059566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 280624119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 28079371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 28089371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 28099371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 28109371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 28119371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 28129371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 281324119c2aSMatthew G. Knepley } 2814dd400576SPatrick Sanan if (rank == 0) { 28159371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 28169371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 28179371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 28189371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 28199371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 28209371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 28219fe9f049SMatthew G. Knepley } 28229566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 28239566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 28249566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 282524119c2aSMatthew G. Knepley } 282646139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 28279318fe57SMatthew G. Knepley /* Interpolate */ 28289566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 28293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28309318fe57SMatthew G. Knepley } 28319318fe57SMatthew G. Knepley 28329318fe57SMatthew G. Knepley /*@ 28339318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 28349318fe57SMatthew G. Knepley 28359318fe57SMatthew G. Knepley Collective 28369318fe57SMatthew G. Knepley 28379318fe57SMatthew G. Knepley Input Parameters: 2838a1cb98faSBarry Smith + comm - The communicator for the `DM` object 28399318fe57SMatthew G. Knepley . n - The number of wedges around the origin 28409318fe57SMatthew G. Knepley - interpolate - Create edges and faces 28419318fe57SMatthew G. Knepley 28429318fe57SMatthew G. Knepley Output Parameter: 2843a1cb98faSBarry Smith . dm - The `DM` object 28449318fe57SMatthew G. Knepley 28459318fe57SMatthew G. Knepley Level: beginner 28469318fe57SMatthew G. Knepley 28471cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 28489318fe57SMatthew G. Knepley @*/ 2849d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 2850d71ae5a4SJacob Faibussowitsch { 28519318fe57SMatthew G. Knepley PetscFunctionBegin; 28524f572ea9SToby Isaac PetscAssertPointer(dm, 4); 28539566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 28549566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 28559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 28563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 285724119c2aSMatthew G. Knepley } 285824119c2aSMatthew G. Knepley 2859d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2860d71ae5a4SJacob Faibussowitsch { 286165a81367SMatthew G. Knepley PetscReal prod = 0.0; 286265a81367SMatthew G. Knepley PetscInt i; 286365a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 286465a81367SMatthew G. Knepley return PetscSqrtReal(prod); 286565a81367SMatthew G. Knepley } 2866dd2b43ebSStefano Zampini 2867d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2868d71ae5a4SJacob Faibussowitsch { 286965a81367SMatthew G. Knepley PetscReal prod = 0.0; 287065a81367SMatthew G. Knepley PetscInt i; 287165a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += x[i] * y[i]; 287265a81367SMatthew G. Knepley return prod; 287365a81367SMatthew G. Knepley } 287465a81367SMatthew G. Knepley 287551a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 2876d71ae5a4SJacob 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[]) 2877d71ae5a4SJacob Faibussowitsch { 287851a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 287951a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 288051a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 288151a74b61SMatthew G. Knepley 288251a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 288351a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 288451a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 288551a74b61SMatthew G. Knepley } 288651a74b61SMatthew G. Knepley 2887d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 2888d71ae5a4SJacob Faibussowitsch { 288965a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 289065a81367SMatthew G. Knepley PetscSection coordSection; 289165a81367SMatthew G. Knepley Vec coordinates; 289265a81367SMatthew G. Knepley PetscScalar *coords; 289365a81367SMatthew G. Knepley PetscReal *coordsIn; 289407c565c5SJose E. Roman PetscInt numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, e; 289565a81367SMatthew G. Knepley PetscMPIInt rank; 289665a81367SMatthew G. Knepley 289765a81367SMatthew G. Knepley PetscFunctionBegin; 28989318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 289946139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 29009566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 29019566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 29029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 290365a81367SMatthew G. Knepley switch (dim) { 29045c344501SMatthew G. Knepley case 1: 29055c344501SMatthew G. Knepley numCells = 16; 29065c344501SMatthew G. Knepley numVerts = numCells; 29075c344501SMatthew G. Knepley 29085c344501SMatthew G. Knepley // Build Topology 29095c344501SMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 29105c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 29115c344501SMatthew G. Knepley PetscCall(DMSetUp(dm)); 29125c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 29135c344501SMatthew G. Knepley PetscInt cone[2]; 29145c344501SMatthew G. Knepley 29155c344501SMatthew G. Knepley cone[0] = c + numCells; 29165c344501SMatthew G. Knepley cone[1] = (c + 1) % numVerts + numCells; 29175c344501SMatthew G. Knepley PetscCall(DMPlexSetCone(dm, c, cone)); 29185c344501SMatthew G. Knepley } 29195c344501SMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 29205c344501SMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 29215c344501SMatthew G. Knepley PetscCall(PetscMalloc1(numVerts * embedDim, &coordsIn)); 29225c344501SMatthew G. Knepley for (PetscInt v = 0; v < numVerts; ++v) { 29235c344501SMatthew G. Knepley const PetscReal rad = 2. * PETSC_PI * v / numVerts; 29245c344501SMatthew G. Knepley 29255c344501SMatthew G. Knepley coordsIn[v * embedDim + 0] = PetscCosReal(rad); 29265c344501SMatthew G. Knepley coordsIn[v * embedDim + 1] = PetscSinReal(rad); 29275c344501SMatthew G. Knepley } 29285c344501SMatthew G. Knepley break; 292965a81367SMatthew G. Knepley case 2: 293065a81367SMatthew G. Knepley if (simplex) { 293151a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 293251a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 293365a81367SMatthew G. Knepley const PetscInt degree = 5; 293451a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 293565a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 293665a81367SMatthew G. Knepley PetscInt cone[3]; 293707c565c5SJose E. Roman PetscInt *graph; 293865a81367SMatthew G. Knepley 29399371c9d4SSatish Balay vertex[0] *= R / radius; 29409371c9d4SSatish Balay vertex[1] *= R / radius; 29419371c9d4SSatish Balay vertex[2] *= R / radius; 2942dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 2943dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 294465a81367SMatthew G. Knepley firstVertex = numCells; 294551a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 294665a81367SMatthew G. Knepley 294765a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 294865a81367SMatthew G. Knepley 294965a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 295051a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 295165a81367SMatthew G. Knepley */ 295265a81367SMatthew G. Knepley /* Construct vertices */ 29539566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 2954dd400576SPatrick Sanan if (rank == 0) { 295507c565c5SJose E. Roman for (PetscInt p = 0, i = 0; p < embedDim; ++p) { 295665a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 295765a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 295865a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 295965a81367SMatthew G. Knepley ++i; 296065a81367SMatthew G. Knepley } 296165a81367SMatthew G. Knepley } 296265a81367SMatthew G. Knepley } 296345da822fSValeria Barra } 296465a81367SMatthew G. Knepley /* Construct graph */ 29659566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 296607c565c5SJose E. Roman for (PetscInt i = 0; i < numVerts; ++i) { 296707c565c5SJose E. Roman PetscInt k = 0; 296807c565c5SJose E. Roman for (PetscInt j = 0; j < numVerts; ++j) { 29699371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 29709371c9d4SSatish Balay graph[i * numVerts + j] = 1; 29719371c9d4SSatish Balay ++k; 29729371c9d4SSatish Balay } 297365a81367SMatthew G. Knepley } 297463a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 297565a81367SMatthew G. Knepley } 297665a81367SMatthew G. Knepley /* Build Topology */ 29779566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 297807c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 29799566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 298065a81367SMatthew G. Knepley /* Cells */ 298107c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 298207c565c5SJose E. Roman for (PetscInt j = 0; j < i; ++j) { 298307c565c5SJose E. Roman for (PetscInt k = 0; k < j; ++k) { 298465a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 29859371c9d4SSatish Balay cone[0] = firstVertex + i; 29869371c9d4SSatish Balay cone[1] = firstVertex + j; 29879371c9d4SSatish Balay cone[2] = firstVertex + k; 298865a81367SMatthew G. Knepley /* Check orientation */ 298965a81367SMatthew G. Knepley { 29909371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 29919371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 29929371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 29939371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 29949371c9d4SSatish Balay }; 299565a81367SMatthew G. Knepley PetscReal normal[3]; 299665a81367SMatthew G. Knepley PetscInt e, f; 299765a81367SMatthew G. Knepley 299865a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 299965a81367SMatthew G. Knepley normal[d] = 0.0; 300065a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3001ad540459SPierre 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]); 300265a81367SMatthew G. Knepley } 300365a81367SMatthew G. Knepley } 30049371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 30059371c9d4SSatish Balay PetscInt tmp = cone[1]; 30069371c9d4SSatish Balay cone[1] = cone[2]; 30079371c9d4SSatish Balay cone[2] = tmp; 300865a81367SMatthew G. Knepley } 300965a81367SMatthew G. Knepley } 30109566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 301165a81367SMatthew G. Knepley } 301265a81367SMatthew G. Knepley } 301365a81367SMatthew G. Knepley } 301465a81367SMatthew G. Knepley } 30159566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 30169566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 30179566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 301865a81367SMatthew G. Knepley } else { 30192829fed8SMatthew G. Knepley /* 30202829fed8SMatthew G. Knepley 12-21--13 30212829fed8SMatthew G. Knepley | | 30222829fed8SMatthew G. Knepley 25 4 24 30232829fed8SMatthew G. Knepley | | 30242829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 30252829fed8SMatthew G. Knepley | | | | 30262829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 30272829fed8SMatthew G. Knepley | | | | 30282829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 30292829fed8SMatthew G. Knepley | | 30302829fed8SMatthew G. Knepley 20 1 19 30312829fed8SMatthew G. Knepley | | 30322829fed8SMatthew G. Knepley 10-18--11 30332829fed8SMatthew G. Knepley | | 30342829fed8SMatthew G. Knepley 23 2 22 30352829fed8SMatthew G. Knepley | | 30362829fed8SMatthew G. Knepley 12-21--13 30372829fed8SMatthew G. Knepley */ 30382829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 30392829fed8SMatthew G. Knepley 3040dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 3041dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 3042dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 304365a81367SMatthew G. Knepley firstVertex = numCells; 304465a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 30452829fed8SMatthew G. Knepley /* Build Topology */ 30469566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 304707c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 304848a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 30499566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3050dd400576SPatrick Sanan if (rank == 0) { 30512829fed8SMatthew G. Knepley /* Cell 0 */ 30529371c9d4SSatish Balay cone[0] = 14; 30539371c9d4SSatish Balay cone[1] = 15; 30549371c9d4SSatish Balay cone[2] = 16; 30559371c9d4SSatish Balay cone[3] = 17; 30569566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 30579371c9d4SSatish Balay ornt[0] = 0; 30589371c9d4SSatish Balay ornt[1] = 0; 30599371c9d4SSatish Balay ornt[2] = 0; 30609371c9d4SSatish Balay ornt[3] = 0; 30619566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 30622829fed8SMatthew G. Knepley /* Cell 1 */ 30639371c9d4SSatish Balay cone[0] = 18; 30649371c9d4SSatish Balay cone[1] = 19; 30659371c9d4SSatish Balay cone[2] = 14; 30669371c9d4SSatish Balay cone[3] = 20; 30679566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 30689371c9d4SSatish Balay ornt[0] = 0; 30699371c9d4SSatish Balay ornt[1] = 0; 30709371c9d4SSatish Balay ornt[2] = -1; 30719371c9d4SSatish Balay ornt[3] = 0; 30729566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 30732829fed8SMatthew G. Knepley /* Cell 2 */ 30749371c9d4SSatish Balay cone[0] = 21; 30759371c9d4SSatish Balay cone[1] = 22; 30769371c9d4SSatish Balay cone[2] = 18; 30779371c9d4SSatish Balay cone[3] = 23; 30789566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 30799371c9d4SSatish Balay ornt[0] = 0; 30809371c9d4SSatish Balay ornt[1] = 0; 30819371c9d4SSatish Balay ornt[2] = -1; 30829371c9d4SSatish Balay ornt[3] = 0; 30839566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 30842829fed8SMatthew G. Knepley /* Cell 3 */ 30859371c9d4SSatish Balay cone[0] = 19; 30869371c9d4SSatish Balay cone[1] = 22; 30879371c9d4SSatish Balay cone[2] = 24; 30889371c9d4SSatish Balay cone[3] = 15; 30899566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 30909371c9d4SSatish Balay ornt[0] = -1; 30919371c9d4SSatish Balay ornt[1] = -1; 30929371c9d4SSatish Balay ornt[2] = 0; 30939371c9d4SSatish Balay ornt[3] = -1; 30949566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 30952829fed8SMatthew G. Knepley /* Cell 4 */ 30969371c9d4SSatish Balay cone[0] = 16; 30979371c9d4SSatish Balay cone[1] = 24; 30989371c9d4SSatish Balay cone[2] = 21; 30999371c9d4SSatish Balay cone[3] = 25; 31009566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 31019371c9d4SSatish Balay ornt[0] = -1; 31029371c9d4SSatish Balay ornt[1] = -1; 31039371c9d4SSatish Balay ornt[2] = -1; 31049371c9d4SSatish Balay ornt[3] = 0; 31059566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 31062829fed8SMatthew G. Knepley /* Cell 5 */ 31079371c9d4SSatish Balay cone[0] = 20; 31089371c9d4SSatish Balay cone[1] = 17; 31099371c9d4SSatish Balay cone[2] = 25; 31109371c9d4SSatish Balay cone[3] = 23; 31119566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 31129371c9d4SSatish Balay ornt[0] = -1; 31139371c9d4SSatish Balay ornt[1] = -1; 31149371c9d4SSatish Balay ornt[2] = -1; 31159371c9d4SSatish Balay ornt[3] = -1; 31169566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 31172829fed8SMatthew G. Knepley /* Edges */ 31189371c9d4SSatish Balay cone[0] = 6; 31199371c9d4SSatish Balay cone[1] = 7; 31209566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 31219371c9d4SSatish Balay cone[0] = 7; 31229371c9d4SSatish Balay cone[1] = 8; 31239566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 31249371c9d4SSatish Balay cone[0] = 8; 31259371c9d4SSatish Balay cone[1] = 9; 31269566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 31279371c9d4SSatish Balay cone[0] = 9; 31289371c9d4SSatish Balay cone[1] = 6; 31299566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 31309371c9d4SSatish Balay cone[0] = 10; 31319371c9d4SSatish Balay cone[1] = 11; 31329566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 31339371c9d4SSatish Balay cone[0] = 11; 31349371c9d4SSatish Balay cone[1] = 7; 31359566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 31369371c9d4SSatish Balay cone[0] = 6; 31379371c9d4SSatish Balay cone[1] = 10; 31389566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 31399371c9d4SSatish Balay cone[0] = 12; 31409371c9d4SSatish Balay cone[1] = 13; 31419566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 31429371c9d4SSatish Balay cone[0] = 13; 31439371c9d4SSatish Balay cone[1] = 11; 31449566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 31459371c9d4SSatish Balay cone[0] = 10; 31469371c9d4SSatish Balay cone[1] = 12; 31479566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 31489371c9d4SSatish Balay cone[0] = 13; 31499371c9d4SSatish Balay cone[1] = 8; 31509566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 31519371c9d4SSatish Balay cone[0] = 12; 31529371c9d4SSatish Balay cone[1] = 9; 31539566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 315445da822fSValeria Barra } 31559566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 31569566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 31572829fed8SMatthew G. Knepley /* Build coordinates */ 31589566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3159dd400576SPatrick Sanan if (rank == 0) { 31609371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 31619371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 31629371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 31639371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 31649371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 31659371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 31669371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 31679371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 31689371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 31699371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 31709371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 31719371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 31729371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 31739371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 31749371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 31759371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 31769371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 31779371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 31789371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 31799371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 31809371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 31819371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 31829371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 31839371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 318465a81367SMatthew G. Knepley } 318545da822fSValeria Barra } 318665a81367SMatthew G. Knepley break; 318765a81367SMatthew G. Knepley case 3: 3188116ded15SMatthew G. Knepley if (simplex) { 3189116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 319051a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 319151a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 319251a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 3193116ded15SMatthew G. Knepley const PetscInt degree = 12; 3194116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 31959371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 31969371c9d4SSatish Balay {0, 1, 2, 3}, 31979371c9d4SSatish Balay {0, 2, 3, 1}, 31989371c9d4SSatish Balay {0, 3, 1, 2}, 31999371c9d4SSatish Balay {1, 0, 3, 2}, 32009371c9d4SSatish Balay {1, 2, 0, 3}, 32019371c9d4SSatish Balay {1, 3, 2, 0}, 32029371c9d4SSatish Balay {2, 0, 1, 3}, 32039371c9d4SSatish Balay {2, 1, 3, 0}, 32049371c9d4SSatish Balay {2, 3, 0, 1}, 32059371c9d4SSatish Balay {3, 0, 2, 1}, 32069371c9d4SSatish Balay {3, 1, 0, 2}, 32079371c9d4SSatish Balay {3, 2, 1, 0} 32089371c9d4SSatish Balay }; 3209116ded15SMatthew G. Knepley PetscInt cone[4]; 3210116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 3211116ded15SMatthew G. Knepley 32129371c9d4SSatish Balay vertexA[0] *= R; 32139371c9d4SSatish Balay vertexA[1] *= R; 32149371c9d4SSatish Balay vertexA[2] *= R; 32159371c9d4SSatish Balay vertexA[3] *= R; 32169371c9d4SSatish Balay vertexB[0] *= R; 32179371c9d4SSatish Balay vertexB[1] *= R; 32189371c9d4SSatish Balay vertexB[2] *= R; 32199371c9d4SSatish Balay vertexB[3] *= R; 32209371c9d4SSatish Balay vertexC[0] *= R; 32219371c9d4SSatish Balay vertexC[1] *= R; 32229371c9d4SSatish Balay vertexC[2] *= R; 32239371c9d4SSatish Balay vertexC[3] *= R; 3224dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 3225dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 3226116ded15SMatthew G. Knepley firstVertex = numCells; 3227116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 3228116ded15SMatthew G. Knepley 3229116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 3230116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 3231116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 3232116ded15SMatthew G. Knepley 3233116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 32346333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 3235116ded15SMatthew G. Knepley 3236116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 3237116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 3238116ded15SMatthew G. Knepley */ 3239116ded15SMatthew G. Knepley /* Construct vertices */ 32409566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3241116ded15SMatthew G. Knepley i = 0; 3242dd400576SPatrick Sanan if (rank == 0) { 3243116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3244116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3245116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3246116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 3247116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 3248116ded15SMatthew G. Knepley ++i; 3249116ded15SMatthew G. Knepley } 3250116ded15SMatthew G. Knepley } 3251116ded15SMatthew G. Knepley } 3252116ded15SMatthew G. Knepley } 3253116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 3254116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 3255116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3256116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 3257116ded15SMatthew G. Knepley ++i; 3258116ded15SMatthew G. Knepley } 3259116ded15SMatthew G. Knepley } 3260116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 3261116ded15SMatthew G. Knepley s[3] = 1; 3262116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3263116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3264116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3265116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 3266116ded15SMatthew G. Knepley ++i; 3267116ded15SMatthew G. Knepley } 3268116ded15SMatthew G. Knepley } 3269116ded15SMatthew G. Knepley } 3270116ded15SMatthew G. Knepley } 327145da822fSValeria Barra } 327263a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 3273116ded15SMatthew G. Knepley /* Construct graph */ 32749566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 3275116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 3276116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 32779371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 32789371c9d4SSatish Balay graph[i * numVerts + j] = 1; 32799371c9d4SSatish Balay ++k; 32809371c9d4SSatish Balay } 3281116ded15SMatthew G. Knepley } 328263a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 3283116ded15SMatthew G. Knepley } 3284116ded15SMatthew G. Knepley /* Build Topology */ 32859566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 328607c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 32879566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3288116ded15SMatthew G. Knepley /* Cells */ 3289dd400576SPatrick Sanan if (rank == 0) { 329007c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 3291116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 3292116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 3293116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 32949371c9d4SSatish 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]) { 32959371c9d4SSatish Balay cone[0] = firstVertex + i; 32969371c9d4SSatish Balay cone[1] = firstVertex + j; 32979371c9d4SSatish Balay cone[2] = firstVertex + k; 32989371c9d4SSatish Balay cone[3] = firstVertex + l; 3299116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 3300116ded15SMatthew G. Knepley { 33019371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 33029371c9d4SSatish 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}}}, 3303116ded15SMatthew G. Knepley 33049371c9d4SSatish 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}}}, 3305116ded15SMatthew G. Knepley 33069371c9d4SSatish 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}}}, 3307116ded15SMatthew G. Knepley 33089371c9d4SSatish 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}} } 33099371c9d4SSatish Balay }; 3310116ded15SMatthew G. Knepley PetscReal normal[4]; 3311116ded15SMatthew G. Knepley PetscInt e, f, g; 3312116ded15SMatthew G. Knepley 3313116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 3314116ded15SMatthew G. Knepley normal[d] = 0.0; 3315116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3316116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 3317116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 3318116ded15SMatthew 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]); 3319116ded15SMatthew G. Knepley } 3320116ded15SMatthew G. Knepley } 3321116ded15SMatthew G. Knepley } 3322116ded15SMatthew G. Knepley } 33239371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 33249371c9d4SSatish Balay PetscInt tmp = cone[1]; 33259371c9d4SSatish Balay cone[1] = cone[2]; 33269371c9d4SSatish Balay cone[2] = tmp; 33279371c9d4SSatish Balay } 3328116ded15SMatthew G. Knepley } 33299566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 3330116ded15SMatthew G. Knepley } 3331116ded15SMatthew G. Knepley } 3332116ded15SMatthew G. Knepley } 3333116ded15SMatthew G. Knepley } 3334116ded15SMatthew G. Knepley } 333545da822fSValeria Barra } 33369566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 33379566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 33389566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 3339116ded15SMatthew G. Knepley } 3340f4d061e9SPierre Jolivet break; 3341d71ae5a4SJacob Faibussowitsch default: 3342d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 334365a81367SMatthew G. Knepley } 334465a81367SMatthew G. Knepley /* Create coordinates */ 33459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 33469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 33479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 33489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 33492829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 33509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 33519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 33522829fed8SMatthew G. Knepley } 33539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 33549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 33559566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 33569566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 33579566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 33589566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 33599566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 33609566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 33619371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 3362ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 33639566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 33649566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 33659566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 33669566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 336751a74b61SMatthew G. Knepley { 336851a74b61SMatthew G. Knepley DM cdm; 336951a74b61SMatthew G. Knepley PetscDS cds; 33709318fe57SMatthew G. Knepley PetscScalar c = R; 337151a74b61SMatthew G. Knepley 3372e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, snapToSphere)); 33739566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 33749566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 33759566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 337651a74b61SMatthew G. Knepley } 337746139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 33789318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 33799566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 33803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 33819318fe57SMatthew G. Knepley } 33829318fe57SMatthew G. Knepley 3383b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 3384b7f5c055SJed Brown 3385b7f5c055SJed Brown /* 3386b7f5c055SJed Brown The Schwarz P implicit surface is 3387b7f5c055SJed Brown 3388b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 3389b7f5c055SJed Brown */ 3390d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3391d71ae5a4SJacob Faibussowitsch { 3392b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 3393b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 3394b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 3395b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3396b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 3397ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 3398b7f5c055SJed Brown } 3399b7f5c055SJed Brown } 3400b7f5c055SJed Brown 34014663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3402d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3403d71ae5a4SJacob Faibussowitsch { 3404ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 34053ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 34064663dae6SJed Brown } 34074663dae6SJed Brown 3408b7f5c055SJed Brown /* 3409b7f5c055SJed Brown The Gyroid implicit surface is 3410b7f5c055SJed Brown 3411b7f5c055SJed 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) 3412b7f5c055SJed Brown 3413b7f5c055SJed Brown */ 3414d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3415d71ae5a4SJacob Faibussowitsch { 3416b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 3417b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 3418b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 3419b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 3420b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 3421b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 3422b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 3423b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3424b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3425b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 3426b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3427b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3428b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 3429b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3430b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3431b7f5c055SJed Brown } 3432b7f5c055SJed Brown 34334663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3434d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3435d71ae5a4SJacob Faibussowitsch { 34364663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 34374663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 34384663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 34394663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 34404663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 34413ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 34424663dae6SJed Brown } 34434663dae6SJed Brown 3444b7f5c055SJed Brown /* 3445b7f5c055SJed Brown We wish to solve 3446b7f5c055SJed Brown 3447b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 3448b7f5c055SJed Brown 3449b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 3450b7f5c055SJed 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 3451b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 3452b7f5c055SJed Brown 3453b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 3454b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 3455b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 3456b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 3457da81f932SPierre Jolivet Since Q is symmetric, this is equivalent to multiplying by Q and taking the last two entries. 3458b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 3459b7f5c055SJed Brown 3460b7f5c055SJed Brown f(y) = 0 1 equation 3461b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 3462b7f5c055SJed Brown 3463b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 3464b7f5c055SJed Brown */ 3465d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 3466d71ae5a4SJacob Faibussowitsch { 3467b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 3468b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 34692f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 34709371c9d4SSatish Balay PetscReal n_y[3][3] = { 34719371c9d4SSatish Balay {0, 0, 0}, 34729371c9d4SSatish Balay {0, 0, 0}, 34739371c9d4SSatish Balay {0, 0, 0} 34749371c9d4SSatish Balay }; 3475b7f5c055SJed Brown 3476b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 3477b7f5c055SJed Brown 3478b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 3479b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3480ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 3481b7f5c055SJed Brown 3482b7f5c055SJed Brown // Define the Householder reflector 3483b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 3484b7f5c055SJed Brown n[0] += norm * sign; 3485b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 3486b7f5c055SJed Brown 3487b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3488b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 3489b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 3490b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 3491b7f5c055SJed Brown 3492b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3493b7f5c055SJed Brown n[i] /= norm; 3494b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3495b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 3496b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 3497b7f5c055SJed Brown } 3498b7f5c055SJed Brown } 3499b7f5c055SJed Brown 3500b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 3501b7f5c055SJed 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]; 3502b7f5c055SJed Brown 3503b7f5c055SJed Brown res[0] = f; 3504b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 3505b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 3506b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 3507b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3508b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 3509b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 3510b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 3511b7f5c055SJed Brown } 3512b7f5c055SJed Brown } 3513b7f5c055SJed Brown 3514b7f5c055SJed Brown /* 3515b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 3516b7f5c055SJed Brown */ 3517d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 3518d71ae5a4SJacob Faibussowitsch { 3519b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 3520b7f5c055SJed Brown 3521b7f5c055SJed Brown PetscFunctionBegin; 3522b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 3523b7f5c055SJed Brown PetscScalar res[3], J[9]; 3524b7f5c055SJed Brown PetscReal resnorm; 3525b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 3526b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 3527b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 352863a3b9bcSJacob 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]))); 3529b7f5c055SJed Brown } 3530b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 3531b7f5c055SJed Brown 3532b7f5c055SJed Brown // Take the Newton step 35339566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 3534b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 3535b7f5c055SJed Brown } 3536b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 35373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3538b7f5c055SJed Brown } 3539b7f5c055SJed Brown 3540b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 3541b7f5c055SJed Brown 3542d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 3543d71ae5a4SJacob Faibussowitsch { 3544b7f5c055SJed Brown PetscMPIInt rank; 3545b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 3546b7f5c055SJed Brown PetscInt(*edges)[2] = NULL, *edgeSets = NULL; 3547b7f5c055SJed Brown PetscInt *cells_flat = NULL; 3548b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 3549b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 35508434afd1SBarry Smith PetscSimplePointFn *normalFunc = NULL; 3551b7f5c055SJed Brown DMLabel label; 3552b7f5c055SJed Brown 3553b7f5c055SJed Brown PetscFunctionBegin; 355446139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 35559566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 355663a3b9bcSJacob 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); 3557b7f5c055SJed Brown switch (tpstype) { 3558b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 3559b7f5c055SJed 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"); 3560c5853193SPierre Jolivet if (rank == 0) { 3561b7f5c055SJed Brown PetscInt(*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 3562b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 3563b7f5c055SJed Brown PetscReal L = 1; 3564b7f5c055SJed Brown 3565b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 3566b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 3567b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 3568b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 3569b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 3570b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 35719566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 35729566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 35739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 35749566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 3575b7f5c055SJed Brown // x-normal pipes 3576b7f5c055SJed Brown vcount = 0; 3577b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 3578b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3579b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3580b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3581b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 3582b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3583b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3584b7f5c055SJed Brown } 3585b7f5c055SJed Brown } 3586b7f5c055SJed Brown } 3587b7f5c055SJed Brown } 3588b7f5c055SJed Brown // y-normal pipes 3589b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3590b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 3591b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3592b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3593b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3594b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 3595b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3596b7f5c055SJed Brown } 3597b7f5c055SJed Brown } 3598b7f5c055SJed Brown } 3599b7f5c055SJed Brown } 3600b7f5c055SJed Brown // z-normal pipes 3601b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3602b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3603b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 3604b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3605b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3606b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3607b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 3608b7f5c055SJed Brown } 3609b7f5c055SJed Brown } 3610b7f5c055SJed Brown } 3611b7f5c055SJed Brown } 3612b7f5c055SJed Brown // junctions 3613b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3614b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3615b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3616b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 3617b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 3618b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 3619b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 3620b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 3621b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 3622b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 3623b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 3624b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 3625b7f5c055SJed Brown } 3626b7f5c055SJed Brown } 3627b7f5c055SJed Brown } 3628b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 3629b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 3630b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 3631b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 3632b7f5c055SJed Brown }; 3633b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 36349371c9d4SSatish 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}; 3635b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 36369371c9d4SSatish 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}; 3637b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 3638b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 3639b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 3640b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 3641b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 3642b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 3643b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 3644b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 3645b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 3646b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 3647b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 3648b7f5c055SJed Brown if (ijk[dir] == 0) { 3649b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 3650b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 3651b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 3652b7f5c055SJed Brown numEdges++; 3653b7f5c055SJed Brown } 3654b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 3655b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 3656b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 3657b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 3658b7f5c055SJed Brown numEdges++; 3659b7f5c055SJed Brown } 3660b7f5c055SJed Brown } 3661b7f5c055SJed Brown } 3662b7f5c055SJed Brown } 3663b7f5c055SJed Brown } 3664b7f5c055SJed Brown } 366563a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 3666b7f5c055SJed Brown numFaces = 24 * Njunctions; 3667b7f5c055SJed Brown cells_flat = cells[0][0][0]; 3668b7f5c055SJed Brown } 3669b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 36704663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 3671b7f5c055SJed Brown break; 3672b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 3673c5853193SPierre Jolivet if (rank == 0) { 3674b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 3675b7f5c055SJed Brown // 3676b7f5c055SJed 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) 3677b7f5c055SJed Brown // 3678b7f5c055SJed Brown // on the cell [0,2]^3. 3679b7f5c055SJed Brown // 3680b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 3681b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 3682b7f5c055SJed Brown // like a boomerang: 3683b7f5c055SJed Brown // 3684b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 3685b7f5c055SJed Brown // ----- ------- ------- ------- // 3686b7f5c055SJed Brown // // 3687b7f5c055SJed Brown // + + + + + + + \ + // 3688b7f5c055SJed Brown // \ / \ // 3689b7f5c055SJed Brown // \ `-_ _-' / } // 3690b7f5c055SJed Brown // *-_ `-' _-' / // 3691b7f5c055SJed Brown // + `-+ + + +-' + + / + // 3692b7f5c055SJed Brown // // 3693b7f5c055SJed Brown // // 3694b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 3695b7f5c055SJed Brown // ----- ------- ------- ------- // 3696b7f5c055SJed Brown // // 3697b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 3698b7f5c055SJed Brown // `-_ _-_ _-` / // 3699b7f5c055SJed Brown // \ _-' `-_ / { // 3700b7f5c055SJed Brown // \ / \ // 3701b7f5c055SJed Brown // + + + + + + + \ + // 3702b7f5c055SJed Brown // 3703b7f5c055SJed Brown // 3704b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 3705b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 3706b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 3707b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 3708b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 3709b7f5c055SJed Brown // 3710b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 3711b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 3712b7f5c055SJed Brown // 3713b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 3714b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 3715b7f5c055SJed Brown 3716b7f5c055SJed Brown PetscInt facesPerBlock = 64; 3717b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 3718b7f5c055SJed Brown PetscInt extentPlus[3]; 3719b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 37209371c9d4SSatish 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; 37219371c9d4SSatish Balay const PetscInt pattern[64][4] = { 37229371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 3723b7f5c055SJed Brown /* layer 0 */ 37249371c9d4SSatish Balay {A, C, K, G }, 37259371c9d4SSatish Balay {C, B, II, K }, 37269371c9d4SSatish Balay {D, A, H, L }, 37279371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 37289371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 37299371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 37309371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 37319371c9d4SSatish Balay {B, F, M, II }, 3732b7f5c055SJed Brown /* layer 1 */ 37339371c9d4SSatish Balay {G, K, Q, O }, 37349371c9d4SSatish Balay {K, II, P, Q }, 37359371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 37369371c9d4SSatish Balay {J, L, R, P }, 37379371c9d4SSatish Balay {N, J, P, S }, 37389371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 37399371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 37409371c9d4SSatish Balay {II, M, T, P }, 3741b7f5c055SJed Brown /* layer 2 */ 37429371c9d4SSatish Balay {O, Q, Y, U }, 37439371c9d4SSatish Balay {Q, P, W, Y }, 37449371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 37459371c9d4SSatish Balay {P, R, Ap, W }, 37469371c9d4SSatish Balay {S, P, X, Bp }, 37479371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 37489371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 37499371c9d4SSatish Balay {P, T, Z, X }, 3750b7f5c055SJed Brown /* layer 3 */ 37519371c9d4SSatish Balay {U, Y, Ep, Dp }, 37529371c9d4SSatish Balay {Y, W, Cp, Ep }, 37539371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 37549371c9d4SSatish Balay {W, Ap, Gp, Cp }, 37559371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 37569371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 37579371c9d4SSatish Balay {Z, V, Dp, Hp }, 37589371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 3759b7f5c055SJed Brown /* layer 4 */ 37609371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 37619371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 37629371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 37639371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 37649371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 37659371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 37669371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 37679371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 3768b7f5c055SJed Brown /* layer 5 */ 37699371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 37709371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 37719371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 37729371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 37739371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 37749371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 37759371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 37769371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 3777b7f5c055SJed Brown /* layer 6 */ 37789371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 37799371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 37809371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 37819371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 37829371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 37839371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 37849371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 37859371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 3786b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 37879371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 37889371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 37899371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 37909371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 37919371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 37929371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 37939371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 37949371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 3795b7f5c055SJed Brown }; 3796b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 37979371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 3798bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 3799bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 3800bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 3801bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 3802bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 3803bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 3804b7f5c055SJed Brown 3805bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 3806bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 3807bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 3808bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 3809bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 3810bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 3811bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 3812bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 3813b7f5c055SJed Brown 3814bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 3815bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 3816bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 3817bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 3818bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 3819bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 3820b7f5c055SJed Brown 3821bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 3822bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 3823bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 3824bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 3825bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 3826bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 3827bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 3828bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 3829b7f5c055SJed Brown 3830bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 3831bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 3832bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 3833bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 3834bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 3835bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 3836b7f5c055SJed Brown 3837bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 3838bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 3839bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 3840bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 3841bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 3842bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 3843bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 3844bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 3845b7f5c055SJed Brown 3846bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 3847bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 3848bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 3849bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 3850bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 3851bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 3852b7f5c055SJed Brown 3853bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 3854bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 3855bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 3856bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 3857bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 3858bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 3859bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 3860bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 3861b7f5c055SJed Brown }; 3862b7f5c055SJed Brown PetscInt(*cells)[64][4] = NULL; 3863b7f5c055SJed Brown PetscBool *seen; 3864b7f5c055SJed Brown PetscInt *vertToTrueVert; 3865b7f5c055SJed Brown PetscInt count; 3866b7f5c055SJed Brown 3867b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 3868b7f5c055SJed Brown numBlocks = 1; 3869b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 3870b7f5c055SJed Brown numBlocksPlus = 1; 3871b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 3872b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 38739566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 38749566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 3875b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3876b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3877b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3878b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3879b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 3880b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 3881b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 3882b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 3883b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 3884b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 3885b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 3886b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 3887b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 3888b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 3889b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 3890b7f5c055SJed Brown 3891b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 3892b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 3893b7f5c055SJed Brown } 3894b7f5c055SJed Brown } 3895b7f5c055SJed Brown } 3896b7f5c055SJed Brown } 3897b7f5c055SJed Brown } 38989371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 38999371c9d4SSatish Balay if (seen[i]) numVertices++; 3900b7f5c055SJed Brown count = 0; 39019566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 39029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 3903b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 3904b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 3905b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 3906b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 3907b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 3908b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 3909b7f5c055SJed Brown 3910b7f5c055SJed Brown if (seen[vIdx]) { 3911b7f5c055SJed Brown PetscInt thisVert; 3912b7f5c055SJed Brown 3913b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 3914b7f5c055SJed Brown 3915b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 3916b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 3917b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 3918b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 3919b7f5c055SJed Brown } 3920b7f5c055SJed Brown } 3921b7f5c055SJed Brown } 3922b7f5c055SJed Brown } 3923b7f5c055SJed Brown } 3924b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 3925b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3926ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 3927b7f5c055SJed Brown } 3928b7f5c055SJed Brown } 39299566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 39309566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 3931b7f5c055SJed Brown cells_flat = cells[0][0]; 3932b7f5c055SJed Brown numEdges = 0; 3933b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 3934b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3935b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3936b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3937b7f5c055SJed Brown 3938b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3939b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 3940b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 3941b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 3942b7f5c055SJed Brown } 3943b7f5c055SJed Brown } 3944b7f5c055SJed Brown } 3945b7f5c055SJed Brown } 39469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 39479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 3948b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 3949b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 3950b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 3951b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 3952b7f5c055SJed Brown 3953b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 3954b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 3955b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 3956b7f5c055SJed Brown edges[edge][0] = ev[0]; 3957b7f5c055SJed Brown edges[edge][1] = ev[1]; 3958b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 3959b7f5c055SJed Brown } 3960b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 3961b7f5c055SJed Brown edges[edge][0] = ev[0]; 3962b7f5c055SJed Brown edges[edge][1] = ev[1]; 3963b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 3964b7f5c055SJed Brown } 3965b7f5c055SJed Brown } 3966b7f5c055SJed Brown } 3967b7f5c055SJed Brown } 3968b7f5c055SJed Brown } 3969b7f5c055SJed Brown } 3970b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 39714663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 3972b7f5c055SJed Brown break; 3973b7f5c055SJed Brown } 3974b7f5c055SJed Brown 39759566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 3976c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 39779566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 39789566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 3979b7f5c055SJed Brown { 3980b7f5c055SJed Brown DM idm; 39819566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 398269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 3983b7f5c055SJed Brown } 3984c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 39859566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 39869566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 3987b7f5c055SJed Brown 39889566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 39899566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 3990b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 3991b7f5c055SJed Brown PetscInt njoin; 3992b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 39939566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 399463a3b9bcSJacob 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]); 39959566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 39969566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 3997b7f5c055SJed Brown } 39989566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 39999566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 40001436d7faSJed Brown if (tps_distribute) { 40011436d7faSJed Brown DM pdm = NULL; 40021436d7faSJed Brown PetscPartitioner part; 40031436d7faSJed Brown 40049566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 40059566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 40069566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 400748a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 40081436d7faSJed Brown // Do not auto-distribute again 40099566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 40101436d7faSJed Brown } 4011b7f5c055SJed Brown 40129566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 4013b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 4014b7f5c055SJed Brown PetscInt m; 4015b7f5c055SJed Brown DM dmf; 4016b7f5c055SJed Brown Vec X; 4017b7f5c055SJed Brown PetscScalar *x; 40189566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 401969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 4020b7f5c055SJed Brown 40219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 40229566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 40239566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 402448a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 40259566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 4026b7f5c055SJed Brown } 4027b7f5c055SJed Brown 4028b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 40299566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 40309566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 4031b7f5c055SJed Brown 403246139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 403346139095SJed Brown 4034b7f5c055SJed Brown if (thickness > 0) { 40354663dae6SJed Brown DM edm, cdm, ecdm; 40364663dae6SJed Brown DMPlexTransform tr; 40374663dae6SJed Brown const char *prefix; 40384663dae6SJed Brown PetscOptions options; 40394663dae6SJed Brown // Code from DMPlexExtrude 40404663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 40414663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 40424663dae6SJed Brown PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDE)); 40434663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 40444663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 40454663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 40464663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 40474663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 40484663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 40494663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 40504663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 40514663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 40524663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 40534663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 40544663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 40554663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 40564663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 40574663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 40584663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 40594663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 40604663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 40614663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 40624663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 4063a77a5016SMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, edm)); 406469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 4065b7f5c055SJed Brown } 40663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4067b7f5c055SJed Brown } 4068b7f5c055SJed Brown 4069b7f5c055SJed Brown /*@ 4070b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 4071b7f5c055SJed Brown 4072b7f5c055SJed Brown Collective 4073b7f5c055SJed Brown 4074b7f5c055SJed Brown Input Parameters: 4075a1cb98faSBarry Smith + comm - The communicator for the `DM` object 4076b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 4077b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 407820f4b53cSBarry Smith . periodic - array of length 3 with periodicity, or `NULL` for non-periodic 40791436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 4080817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 40811436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 4082817da375SSatish Balay - thickness - Thickness in normal direction 4083b7f5c055SJed Brown 4084b7f5c055SJed Brown Output Parameter: 4085a1cb98faSBarry Smith . dm - The `DM` object 4086a1cb98faSBarry Smith 4087a1cb98faSBarry Smith Level: beginner 4088b7f5c055SJed Brown 4089b7f5c055SJed Brown Notes: 409015229ffcSPierre Jolivet This meshes the surface of the Schwarz P or Gyroid surfaces. Schwarz P is the simplest member of the triply-periodic minimal surfaces. 40911d27aa22SBarry Smith <https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22)> and can be cut with "clean" boundaries. 40921d27aa22SBarry 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. 4093b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 4094b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 4095b7f5c055SJed Brown This projection could readily be extended to related surfaces. 4096b7f5c055SJed Brown 40971d27aa22SBarry Smith See {cite}`maskery2018insights` 40981d27aa22SBarry Smith 40991d27aa22SBarry Smith The face (edge) sets for the Schwarz P surface are numbered $1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z)$. 41001d27aa22SBarry Smith When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). 41011d27aa22SBarry Smith Use `DMPlexLabelComplete()` to propagate to coarse-level vertices. 4102b7f5c055SJed Brown 410360225df5SJacob Faibussowitsch Developer Notes: 4104b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 4105b7f5c055SJed Brown 41061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 4107b7f5c055SJed Brown @*/ 4108d71ae5a4SJacob 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) 4109d71ae5a4SJacob Faibussowitsch { 4110b7f5c055SJed Brown PetscFunctionBegin; 41119566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 41129566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 41139566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 41143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4115b7f5c055SJed Brown } 4116b7f5c055SJed Brown 41179318fe57SMatthew G. Knepley /*@ 41189318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 41199318fe57SMatthew G. Knepley 41209318fe57SMatthew G. Knepley Collective 41219318fe57SMatthew G. Knepley 41229318fe57SMatthew G. Knepley Input Parameters: 4123a1cb98faSBarry Smith + comm - The communicator for the `DM` object 41249318fe57SMatthew G. Knepley . dim - The dimension 41259318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 41269318fe57SMatthew G. Knepley - R - The radius 41279318fe57SMatthew G. Knepley 41289318fe57SMatthew G. Knepley Output Parameter: 4129a1cb98faSBarry Smith . dm - The `DM` object 41309318fe57SMatthew G. Knepley 41319318fe57SMatthew G. Knepley Level: beginner 41329318fe57SMatthew G. Knepley 41331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 41349318fe57SMatthew G. Knepley @*/ 4135d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 4136d71ae5a4SJacob Faibussowitsch { 41379318fe57SMatthew G. Knepley PetscFunctionBegin; 41384f572ea9SToby Isaac PetscAssertPointer(dm, 5); 41399566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 41409566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 41419566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 41423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41439318fe57SMatthew G. Knepley } 41449318fe57SMatthew G. Knepley 4145d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 4146d71ae5a4SJacob Faibussowitsch { 41479318fe57SMatthew G. Knepley DM sdm, vol; 41489318fe57SMatthew G. Knepley DMLabel bdlabel; 4149dd2b43ebSStefano Zampini const char *prefix; 41509318fe57SMatthew G. Knepley 41519318fe57SMatthew G. Knepley PetscFunctionBegin; 41529566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 41539566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 4154dd2b43ebSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 4155dd2b43ebSStefano Zampini PetscCall(DMSetOptionsPrefix(sdm, prefix)); 4156dd2b43ebSStefano Zampini PetscCall(DMAppendOptionsPrefix(sdm, "bd_")); 4157dd2b43ebSStefano Zampini PetscCall(DMPlexDistributeSetDefault(sdm, PETSC_FALSE)); 41589566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 41599566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 41609566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 41619566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 41629566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 416369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 41649566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 41659566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 41669566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 41679566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 41683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 416951a74b61SMatthew G. Knepley } 417051a74b61SMatthew G. Knepley 417151a74b61SMatthew G. Knepley /*@ 417251a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 417351a74b61SMatthew G. Knepley 417451a74b61SMatthew G. Knepley Collective 417551a74b61SMatthew G. Knepley 417651a74b61SMatthew G. Knepley Input Parameters: 4177a1cb98faSBarry Smith + comm - The communicator for the `DM` object 417851a74b61SMatthew G. Knepley . dim - The dimension 417951a74b61SMatthew G. Knepley - R - The radius 418051a74b61SMatthew G. Knepley 418151a74b61SMatthew G. Knepley Output Parameter: 4182a1cb98faSBarry Smith . dm - The `DM` object 418351a74b61SMatthew G. Knepley 4184a1cb98faSBarry Smith Options Database Key: 418560225df5SJacob Faibussowitsch . bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 418651a74b61SMatthew G. Knepley 418751a74b61SMatthew G. Knepley Level: beginner 418851a74b61SMatthew G. Knepley 41891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 419051a74b61SMatthew G. Knepley @*/ 4191d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 4192d71ae5a4SJacob Faibussowitsch { 419351a74b61SMatthew G. Knepley PetscFunctionBegin; 41949566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 41959566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 41969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 41973ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 41982829fed8SMatthew G. Knepley } 41992829fed8SMatthew G. Knepley 4200d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 4201d71ae5a4SJacob Faibussowitsch { 42020a6ba040SMatthew G. Knepley PetscFunctionBegin; 42039318fe57SMatthew G. Knepley switch (ct) { 42049371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 42059318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 42069318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 42079318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 42089318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 42099318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 42109318fe57SMatthew G. Knepley 42119566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 42129566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 42139371c9d4SSatish Balay } break; 42149371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 42159318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 42169318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 42179318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 42189318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 42199318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 42209318fe57SMatthew G. Knepley 42219566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 42229566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 42239371c9d4SSatish Balay } break; 42249371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 4225b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 4226b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 4227b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 4228b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 4229b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 4230b5a892a1SMatthew G. Knepley 42319566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 42329566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 42339371c9d4SSatish Balay } break; 42349371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 42359318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 42369318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 42379318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 42389318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 42399318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 42409318fe57SMatthew G. Knepley 42419566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 42429566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 42439371c9d4SSatish Balay } break; 42449371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 42459318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 42469318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 42479318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 42489318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 42499318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 42509318fe57SMatthew G. Knepley 42519566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 42529566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 42539371c9d4SSatish Balay } break; 42549371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 42559318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 42569318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 42579318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 42589318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 42599318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 42609318fe57SMatthew G. Knepley 42619566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 42629566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 42639371c9d4SSatish Balay } break; 42649371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 42659318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 42669318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 4267f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 42689318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 4269f0edb160SMatthew 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}; 42709318fe57SMatthew G. Knepley 42719566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 42729566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 42739371c9d4SSatish Balay } break; 42749371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 42759318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 42769318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 4277f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 42789318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 42799371c9d4SSatish 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}; 42809318fe57SMatthew G. Knepley 42819566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 42829566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 42839371c9d4SSatish Balay } break; 42849371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 42859318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 42869318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 4287f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 42889318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 42899371c9d4SSatish 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}; 42909318fe57SMatthew G. Knepley 42919566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 42929566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 42939371c9d4SSatish Balay } break; 42949371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 42959318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 42969318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 42979318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 42989318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 42999371c9d4SSatish 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}; 43009318fe57SMatthew G. Knepley 43019566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 43029566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 43039371c9d4SSatish Balay } break; 43049371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 43059318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 43069318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 43079318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 43089318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 43099371c9d4SSatish 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}; 43109318fe57SMatthew G. Knepley 43119566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 43129566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 43139371c9d4SSatish Balay } break; 43149371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 43159318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 43169318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 4317f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 43189318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 43199371c9d4SSatish 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}; 43209318fe57SMatthew G. Knepley 43219566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 43229566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 43239371c9d4SSatish Balay } break; 4324d71ae5a4SJacob Faibussowitsch default: 4325d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 43269318fe57SMatthew G. Knepley } 43279318fe57SMatthew G. Knepley { 43289318fe57SMatthew G. Knepley PetscInt Nv, v; 43299318fe57SMatthew G. Knepley 43309318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 43319566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 43329566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 43339566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 43349566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 43359318fe57SMatthew G. Knepley } 43369566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 43379566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 43383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43390a6ba040SMatthew G. Knepley } 43400a6ba040SMatthew G. Knepley 43419318fe57SMatthew G. Knepley /*@ 4342a1cb98faSBarry Smith DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell 43439318fe57SMatthew G. Knepley 43449318fe57SMatthew G. Knepley Collective 43459318fe57SMatthew G. Knepley 43469318fe57SMatthew G. Knepley Input Parameters: 43479318fe57SMatthew G. Knepley + comm - The communicator 43489318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 43499318fe57SMatthew G. Knepley 43509318fe57SMatthew G. Knepley Output Parameter: 43519318fe57SMatthew G. Knepley . refdm - The reference cell 43529318fe57SMatthew G. Knepley 43539318fe57SMatthew G. Knepley Level: intermediate 43549318fe57SMatthew G. Knepley 435542747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()` 43569318fe57SMatthew G. Knepley @*/ 4357d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 4358d71ae5a4SJacob Faibussowitsch { 43590a6ba040SMatthew G. Knepley PetscFunctionBegin; 43609566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 43619566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 43629566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 43633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43649318fe57SMatthew G. Knepley } 436579a015ccSMatthew G. Knepley 4366d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 4367d71ae5a4SJacob Faibussowitsch { 43689318fe57SMatthew G. Knepley DM plex; 43699318fe57SMatthew G. Knepley DMLabel label; 43709318fe57SMatthew G. Knepley PetscBool hasLabel; 43710a6ba040SMatthew G. Knepley 4372c22d3578SMatthew G. Knepley PetscFunctionBegin; 43739566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 43743ba16761SJacob Faibussowitsch if (hasLabel) PetscFunctionReturn(PETSC_SUCCESS); 43759566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 43769566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 43779566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 43789566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 43791c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 43809566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 43813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 43829318fe57SMatthew G. Knepley } 4383acdc6f61SToby Isaac 4384669647acSMatthew G. Knepley /* 4385669647acSMatthew 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. 4386669647acSMatthew G. Knepley 4387669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 4388669647acSMatthew G. Knepley */ 4389d71ae5a4SJacob 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[]) 4390d71ae5a4SJacob Faibussowitsch { 4391669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 4392669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 4393669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 4394669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 4395669647acSMatthew G. Knepley 4396669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 4397669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 4398669647acSMatthew G. Knepley } 4399669647acSMatthew G. Knepley 44005390be7dSMatthew G. Knepley // Insert vertices and their joins, marked by depth 44015390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Vertices(DM dm, DMLabel label, DMLabel vlabel, PetscInt val, PetscInt n, const PetscInt vertices[]) 44025390be7dSMatthew G. Knepley { 44035390be7dSMatthew G. Knepley PetscFunctionBegin; 44045390be7dSMatthew G. Knepley PetscCall(DMPlexMarkSubmesh_Interpolated(dm, vlabel, val, PETSC_FALSE, PETSC_FALSE, label, NULL)); 44055390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 44065390be7dSMatthew G. Knepley } 44075390be7dSMatthew G. Knepley 44085390be7dSMatthew G. Knepley // Insert faces and their closures, marked by depth 44095390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Faces(DM dm, DMLabel label, PetscInt n, const PetscInt faces[]) 44105390be7dSMatthew G. Knepley { 44115390be7dSMatthew G. Knepley PetscFunctionBegin; 44125390be7dSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) { 44135390be7dSMatthew G. Knepley const PetscInt point = faces[p]; 44145390be7dSMatthew G. Knepley PetscInt *closure = NULL; 44155390be7dSMatthew G. Knepley PetscInt clSize, pdepth; 44165390be7dSMatthew G. Knepley 44175390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, point, &pdepth)); 44185390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, point, pdepth)); 44195390be7dSMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 44205390be7dSMatthew G. Knepley for (PetscInt cl = 0; cl < clSize * 2; cl += 2) { 44215390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, closure[cl], &pdepth)); 44225390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, closure[cl], pdepth)); 44235390be7dSMatthew G. Knepley } 44245390be7dSMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 44255390be7dSMatthew G. Knepley } 44265390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 44275390be7dSMatthew G. Knepley } 44285390be7dSMatthew G. Knepley 44294e22dd4cSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *flg); 44304e22dd4cSMatthew G. Knepley 44315dca41c3SJed Brown const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "zbox", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 44329318fe57SMatthew G. Knepley 4433d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems *PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 4434d71ae5a4SJacob Faibussowitsch { 44359318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 44369318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 44379318fe57SMatthew G. Knepley PetscInt dim = 2; 4438b9da1bb3SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, orient = PETSC_FALSE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 4439d0812dedSMatthew G. Knepley PetscBool flg, flg2, fflg, strflg, bdfflg, nameflg; 44409318fe57SMatthew G. Knepley MPI_Comm comm; 4441ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4442ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4443ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 44444e22dd4cSMatthew G. Knepley const char *option; 44459318fe57SMatthew G. Knepley 44469318fe57SMatthew G. Knepley PetscFunctionBegin; 4447708be2fdSJed Brown PetscCall(PetscLogEventBegin(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 44489566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 44499318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 44509566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 4451d0812dedSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_file_contents", "Contents of a file format in a string", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &strflg)); 44529566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 44539566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 44549566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 44559566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 44569566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 44579566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 44589566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 44599566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 4460b9da1bb3SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_orient", "Orient the constructed mesh", "DMPlexOrient", orient, &orient, &flg)); 44619566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 44629566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 44639566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 44643f3e541fSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_adj", "Debug output level all adjacency computations", "", 0, &((DM_Plex *)dm->data)->printAdj, NULL, 0)); 44659318fe57SMatthew G. Knepley 446661a622f3SMatthew G. Knepley switch (cell) { 446761a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 446861a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 446961a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 447061a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 447161a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 447261a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 4473d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 4474d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_TRUE; 4475d71ae5a4SJacob Faibussowitsch break; 4476d71ae5a4SJacob Faibussowitsch default: 4477d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_FALSE; 4478d71ae5a4SJacob Faibussowitsch break; 447961a622f3SMatthew G. Knepley } 448061a622f3SMatthew G. Knepley 44819318fe57SMatthew G. Knepley if (fflg) { 44829318fe57SMatthew G. Knepley DM dmnew; 44831e4a82c4SMatthew G. Knepley const char *name; 44849318fe57SMatthew G. Knepley 44851e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 44861e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, nameflg ? plexname : name, interpolate, &dmnew)); 44875de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 448869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 44899318fe57SMatthew G. Knepley } else if (refDomain) { 44909566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 44919318fe57SMatthew G. Knepley } else if (bdfflg) { 44929318fe57SMatthew G. Knepley DM bdm, dmnew; 44931e4a82c4SMatthew G. Knepley const char *name; 44949318fe57SMatthew G. Knepley 44951e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 44961e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, nameflg ? plexname : name, interpolate, &bdm)); 44979566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 44989566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 44999566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 45009566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 45015de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 450269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 4503d0812dedSMatthew G. Knepley } else if (strflg) { 4504d0812dedSMatthew G. Knepley DM dmnew; 4505d0812dedSMatthew G. Knepley PetscViewer viewer; 4506d0812dedSMatthew G. Knepley const char *contents; 4507d0812dedSMatthew G. Knepley char *strname; 4508d0812dedSMatthew G. Knepley char tmpdir[PETSC_MAX_PATH_LEN]; 4509d0812dedSMatthew G. Knepley char tmpfilename[PETSC_MAX_PATH_LEN]; 4510d0812dedSMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 4511d0812dedSMatthew G. Knepley MPI_Comm comm; 4512d0812dedSMatthew G. Knepley PetscMPIInt rank; 4513d0812dedSMatthew G. Knepley 4514d0812dedSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4515d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 4516d0812dedSMatthew G. Knepley PetscCall(PetscStrchr(filename, ':', &strname)); 4517d0812dedSMatthew G. Knepley PetscCheck(strname, comm, PETSC_ERR_ARG_WRONG, "File contents must have the form \"ext:string_name\", not %s", filename); 4518d0812dedSMatthew G. Knepley strname[0] = '\0'; 4519d0812dedSMatthew G. Knepley ++strname; 4520d0812dedSMatthew G. Knepley PetscCall(PetscDLSym(NULL, strname, (void **)&contents)); 4521d0812dedSMatthew G. Knepley PetscCheck(contents, comm, PETSC_ERR_ARG_WRONG, "Could not locate mesh string %s", strname); 4522d0812dedSMatthew G. Knepley PetscCall(PetscGetTmp(comm, tmpdir, PETSC_MAX_PATH_LEN)); 4523ed32af8cSMatthew G. Knepley PetscCall(PetscStrlcat(tmpdir, "/meshXXXXXX", PETSC_MAX_PATH_LEN)); 4524ed32af8cSMatthew G. Knepley PetscCall(PetscMkdtemp(tmpdir)); 4525ed32af8cSMatthew G. Knepley PetscCall(PetscSNPrintf(tmpfilename, PETSC_MAX_PATH_LEN, "%s/mesh.%s", tmpdir, filename)); 4526d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIOpen(comm, tmpfilename, &viewer)); 4527d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", contents)); 4528d0812dedSMatthew G. Knepley PetscCall(PetscViewerDestroy(&viewer)); 4529d0812dedSMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), tmpfilename, plexname, interpolate, &dmnew)); 4530ed32af8cSMatthew G. Knepley PetscCall(PetscRMTree(tmpdir)); 4531d0812dedSMatthew G. Knepley PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%s Mesh", strname)); 4532d0812dedSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, name)); 4533d0812dedSMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 4534d0812dedSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 45359318fe57SMatthew G. Knepley } else { 45369566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 45379318fe57SMatthew G. Knepley switch (shape) { 4538669647acSMatthew G. Knepley case DM_SHAPE_BOX: 45395dca41c3SJed Brown case DM_SHAPE_ZBOX: 4540669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 45419318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 45429318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 45439318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 45449318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4545669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 45469318fe57SMatthew G. Knepley PetscInt i, n; 45479318fe57SMatthew G. Knepley 45489318fe57SMatthew G. Knepley n = dim; 45499318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 45509566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 45519318fe57SMatthew G. Knepley n = 3; 45529566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 455363a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 45549318fe57SMatthew G. Knepley n = 3; 45559566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 455663a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 45579318fe57SMatthew G. Knepley n = 3; 45589566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 455963a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 4560669647acSMatthew G. Knepley 4561669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 4562669647acSMatthew G. Knepley if (isAnnular) 4563669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 4564669647acSMatthew G. Knepley 45659318fe57SMatthew G. Knepley switch (cell) { 456661a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 45679566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 4568d410b0cfSMatthew G. Knepley if (!interpolate) { 4569d410b0cfSMatthew G. Knepley DM udm; 4570d410b0cfSMatthew G. Knepley 45719566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 457269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 4573d410b0cfSMatthew G. Knepley } 45749318fe57SMatthew G. Knepley break; 4575d71ae5a4SJacob Faibussowitsch default: 45765dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(dm, shape, dim, simplex, faces, lower, upper, bdt, interpolate)); 4577d71ae5a4SJacob Faibussowitsch break; 45789318fe57SMatthew G. Knepley } 4579669647acSMatthew G. Knepley if (isAnnular) { 4580669647acSMatthew G. Knepley DM cdm; 4581669647acSMatthew G. Knepley PetscDS cds; 4582669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 4583669647acSMatthew G. Knepley 4584669647acSMatthew G. Knepley // Fix coordinates for annular region 4585669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 4586669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 4587669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 4588e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL)); 4589669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 4590669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 4591669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 4592669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 4593669647acSMatthew G. Knepley } 45949371c9d4SSatish Balay } break; 45959371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 45969318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 45979318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 45989318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 45999318fe57SMatthew G. Knepley PetscInt i, n; 46009318fe57SMatthew G. Knepley 46019318fe57SMatthew G. Knepley n = dim + 1; 46029318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 46039566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 46049318fe57SMatthew G. Knepley n = 3; 46059566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 460663a3b9bcSJacob 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); 46079318fe57SMatthew G. Knepley n = 3; 46089566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 460963a3b9bcSJacob 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); 46109566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 46119371c9d4SSatish Balay } break; 46129371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 46139318fe57SMatthew G. Knepley PetscReal R = 1.0; 46149318fe57SMatthew G. Knepley 46159566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 46169566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 46179371c9d4SSatish Balay } break; 46189371c9d4SSatish Balay case DM_SHAPE_BALL: { 46199318fe57SMatthew G. Knepley PetscReal R = 1.0; 46209318fe57SMatthew G. Knepley 46219566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 46229566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 46239371c9d4SSatish Balay } break; 46249371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 46259318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 46269318fe57SMatthew G. Knepley PetscInt Nw = 6; 462749704ca5SMatthew G. Knepley PetscInt Nr = 0; 46289318fe57SMatthew G. Knepley 46299566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 46309566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 463149704ca5SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_refine", "Number of refinements before projection", "", Nr, &Nr, NULL)); 46329318fe57SMatthew G. Knepley switch (cell) { 4633d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_TRI_PRISM_TENSOR: 4634d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 4635d71ae5a4SJacob Faibussowitsch break; 4636d71ae5a4SJacob Faibussowitsch default: 463749704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt, Nr)); 4638d71ae5a4SJacob Faibussowitsch break; 46399318fe57SMatthew G. Knepley } 46409371c9d4SSatish Balay } break; 4641b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 46429371c9d4SSatish Balay case DM_SHAPE_GYROID: { 4643b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 4644b7f5c055SJed Brown PetscReal thickness = 0.; 4645b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4646b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 46471436d7faSJed Brown PetscBool tps_distribute; 46489566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 46499566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 46509566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 46519566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 46529566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 46539566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 46549566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 46559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 46569371c9d4SSatish Balay } break; 46579371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 465805bd46c0SStefano Zampini DM dmnew; 465905bd46c0SStefano Zampini PetscReal rl = 0.0; 466005bd46c0SStefano Zampini 466105bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 466205bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 46635de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 466469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 46659371c9d4SSatish Balay } break; 4666cfb853baSMatthew G. Knepley case DM_SHAPE_HYPERCUBIC: { 46678d2ec52aSSatish Balay PetscInt *edges, overlap = 1; 4668cfb853baSMatthew G. Knepley PetscReal *lower, *upper; 4669cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 4670cfb853baSMatthew G. Knepley PetscInt n, d; 4671cfb853baSMatthew G. Knepley 4672cfb853baSMatthew G. Knepley *useCoordSpace = PETSC_FALSE; 4673cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt)); 4674cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 4675cfb853baSMatthew G. Knepley edges[d] = 1; 4676cfb853baSMatthew G. Knepley lower[d] = 0.; 4677cfb853baSMatthew G. Knepley upper[d] = 1.; 4678cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 4679cfb853baSMatthew G. Knepley } 4680cfb853baSMatthew G. Knepley n = dim; 4681cfb853baSMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg)); 4682cfb853baSMatthew G. Knepley n = dim; 4683cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 4684cfb853baSMatthew 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); 4685cfb853baSMatthew G. Knepley n = dim; 4686cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 4687cfb853baSMatthew 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); 4688cfb853baSMatthew G. Knepley n = dim; 4689cfb853baSMatthew G. Knepley PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 4690cfb853baSMatthew 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); 46918d2ec52aSSatish Balay PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", overlap, &overlap, NULL, 0)); 46928d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, overlap, bdt)); 4693cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edges, lower, upper, bdt)); 4694cfb853baSMatthew G. Knepley } break; 4695d71ae5a4SJacob Faibussowitsch default: 4696d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 46979318fe57SMatthew G. Knepley } 46989318fe57SMatthew G. Knepley } 46999566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 470048a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 4701b9da1bb3SMatthew G. Knepley if (orient) PetscCall(DMPlexOrient(dm)); 47024e22dd4cSMatthew G. Knepley // Allow label creation 47034e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_label_", &option, NULL, &flg)); 47044e22dd4cSMatthew G. Knepley if (flg) { 47054e22dd4cSMatthew G. Knepley DMLabel label; 47064e22dd4cSMatthew G. Knepley PetscInt points[1024], n = 1024; 47074e22dd4cSMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 47084e22dd4cSMatthew G. Knepley const char *name = &option[14]; 47094e22dd4cSMatthew G. Knepley 47104e22dd4cSMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 47114e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 47124e22dd4cSMatthew G. Knepley fulloption[0] = '-'; 47134e22dd4cSMatthew G. Knepley fulloption[1] = 0; 47144e22dd4cSMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, option, PETSC_MAX_PATH_LEN)); 47154e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, NULL)); 47164e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) PetscCall(DMLabelSetValue(label, points[p], 1)); 47174e22dd4cSMatthew G. Knepley } 4718dd0eeac9SMatthew G. Knepley // Allow cohesive label creation 4719dd0eeac9SMatthew G. Knepley // Faces are input, completed, and all points are marked with their depth 4720dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_cohesive_label_", &option, NULL, &flg)); 4721dd0eeac9SMatthew G. Knepley if (flg) { 4722dd0eeac9SMatthew G. Knepley DMLabel label; 4723dd0eeac9SMatthew G. Knepley PetscInt points[1024], n, pStart, pEnd, Nl = 1; 47245390be7dSMatthew G. Knepley PetscBool noCreate = PETSC_FALSE; 4725dd0eeac9SMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 4726dd0eeac9SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 4727dd0eeac9SMatthew G. Knepley size_t len; 4728dd0eeac9SMatthew G. Knepley 4729dd0eeac9SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4730dd0eeac9SMatthew G. Knepley PetscCall(PetscStrncpy(name, &option[23], PETSC_MAX_PATH_LEN)); 4731dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlen(name, &len)); 4732dd0eeac9SMatthew G. Knepley if (name[len - 1] == '0') Nl = 10; 4733dd0eeac9SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 47346497c311SBarry Smith if (l > 0) name[len - 1] = (char)('0' + l); 4735dd0eeac9SMatthew G. Knepley fulloption[0] = 0; 4736dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, "-dm_plex_cohesive_label_", 32)); 4737dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, name, PETSC_MAX_PATH_LEN - 32)); 4738dd0eeac9SMatthew G. Knepley n = 1024; 4739dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, &flg)); 4740dd0eeac9SMatthew G. Knepley if (!flg) break; 47415390be7dSMatthew G. Knepley PetscCall(DMHasLabel(dm, name, &noCreate)); 47425390be7dSMatthew G. Knepley if (noCreate) { 47435390be7dSMatthew G. Knepley DMLabel inlabel; 47445390be7dSMatthew G. Knepley IS pointIS; 47455390be7dSMatthew G. Knepley const PetscInt *lpoints; 47465390be7dSMatthew G. Knepley PetscInt pdep, ln, inval = points[0]; 47475390be7dSMatthew G. Knepley char newname[PETSC_MAX_PATH_LEN]; 47485390be7dSMatthew G. Knepley 47495390be7dSMatthew G. Knepley PetscCheck(n == 1, comm, PETSC_ERR_ARG_WRONG, "Must specify a label value with this option"); 47505390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &inlabel)); 47515390be7dSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(inlabel, inval, &pointIS)); 47525390be7dSMatthew G. Knepley PetscCall(ISGetLocalSize(pointIS, &ln)); 47535390be7dSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &lpoints)); 47545390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, lpoints[0], &pdep)); 47555390be7dSMatthew G. Knepley PetscCall(PetscSNPrintf(newname, PETSC_MAX_PATH_LEN, "%s%" PetscInt_FMT, name, points[0])); 47565390be7dSMatthew G. Knepley PetscCall(DMCreateLabel(dm, newname)); 47575390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, newname, &label)); 47585390be7dSMatthew G. Knepley if (!pdep) PetscCall(ProcessCohesiveLabel_Vertices(dm, label, inlabel, inval, ln, lpoints)); 47595390be7dSMatthew G. Knepley else PetscCall(ProcessCohesiveLabel_Faces(dm, label, ln, lpoints)); 47605390be7dSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &lpoints)); 47615390be7dSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 47625390be7dSMatthew G. Knepley } else { 4763dd0eeac9SMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 4764dd0eeac9SMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 4765dd0eeac9SMatthew G. Knepley if (pStart >= pEnd) n = 0; 47665390be7dSMatthew G. Knepley PetscCall(ProcessCohesiveLabel_Faces(dm, label, n, points)); 4767dd0eeac9SMatthew G. Knepley } 4768dd0eeac9SMatthew G. Knepley PetscCall(DMPlexOrientLabel(dm, label)); 47690542aa8cSMatthew G. Knepley PetscCall(DMPlexLabelCohesiveComplete(dm, label, NULL, 1, PETSC_FALSE, PETSC_FALSE, NULL)); 4770dd0eeac9SMatthew G. Knepley } 4771dd0eeac9SMatthew G. Knepley } 47725390be7dSMatthew G. Knepley PetscCall(DMViewFromOptions(dm, NULL, "-created_dm_view")); 4773708be2fdSJed Brown PetscCall(PetscLogEventEnd(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 47743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 47750a6ba040SMatthew G. Knepley } 47760a6ba040SMatthew G. Knepley 4777d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 4778d71ae5a4SJacob Faibussowitsch { 47790a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 47807f9d8d6cSVaclav Hapla PetscBool flg, flg2; 47819318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 4782adc21957SMatthew G. Knepley char method[PETSC_MAX_PATH_LEN]; 47830a6ba040SMatthew G. Knepley 47840a6ba040SMatthew G. Knepley PetscFunctionBegin; 47850a6ba040SMatthew G. Knepley /* Handle viewing */ 47869566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 47875962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level for all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 47885962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fvm", "Debug output level for all fvm computations", "DMPlexSNESComputeResidualFVM", 0, &mesh->printFVM, NULL, 0)); 47899566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 47909566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 4791f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 4792a77a5016SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_project", "Debug output level all projection computations", "DMPlexProject", 0, &mesh->printProject, NULL, 0)); 47939566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 47949566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 47955e2c5519SMatthew G. Knepley // Interpolation 47965e2c5519SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_interpolate_prefer_tensor", "When different orderings exist, prefer the tensor order", "DMPlexSetInterpolationPreferTensor", mesh->interpolatePreferTensor, &mesh->interpolatePreferTensor, NULL)); 47979318fe57SMatthew G. Knepley /* Labeling */ 47989566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 47999566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 4800953fc75cSMatthew G. Knepley /* Point Location */ 48019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 48020848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 48039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 4804d02c7345SMatthew G. Knepley /* Reordering */ 4805adc21957SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_reorder_section", "Compute point permutation for local section", "DMReorderSectionSetDefault", PETSC_FALSE, &flg2, &flg)); 4806adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetDefault(dm, flg2 ? DM_REORDER_DEFAULT_TRUE : DM_REORDER_DEFAULT_FALSE)); 4807adc21957SMatthew G. Knepley PetscCall(PetscOptionsString("-dm_reorder_section_type", "Reordering method for local section", "DMReorderSectionSetType", method, method, PETSC_MAX_PATH_LEN, &flg)); 4808adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetType(dm, method)); 48092e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 48109566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 4811b29cfa1cSToby Isaac /* Projection behavior */ 4812d5b43468SJose E. Roman PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 48139566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 4814f12cf164SMatthew G. Knepley /* Checking structure */ 4815f12cf164SMatthew G. Knepley { 48167f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 4817f12cf164SMatthew G. Knepley 48187f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 48197f9d8d6cSVaclav Hapla if (all) { 48207f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 48217f9d8d6cSVaclav Hapla } else { 48229566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 48237f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 48249566063dSJacob 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)); 48257f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 48269566063dSJacob 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)); 48277f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 48289566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 48297f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 48309566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 4831d7d32a9aSMatthew G. Knepley if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 48329566063dSJacob 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)); 48337f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 48347f9d8d6cSVaclav Hapla } 48359566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 48369566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 4837f12cf164SMatthew G. Knepley } 48389318fe57SMatthew G. Knepley { 48399318fe57SMatthew G. Knepley PetscReal scale = 1.0; 48404f3833eaSMatthew G. Knepley 48419566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 48429318fe57SMatthew G. Knepley if (flg) { 48439318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 48449318fe57SMatthew G. Knepley 48459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 48469566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 48479566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 48489566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 48499318fe57SMatthew G. Knepley } 48509318fe57SMatthew G. Knepley } 48519566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 48523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 485368d4fef7SMatthew G. Knepley } 485468d4fef7SMatthew G. Knepley 4855d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems *PetscOptionsObject, PetscInt *overlap) 4856d71ae5a4SJacob Faibussowitsch { 4857c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 4858c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 4859c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 4860c506a872SMatthew G. Knepley PetscBool flg; 4861c506a872SMatthew G. Knepley 4862c506a872SMatthew G. Knepley PetscFunctionBegin; 4863c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 4864c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 4865c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 4866c506a872SMatthew G. Knepley if (numOvLabels) { 4867c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 4868c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 4869c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 4870c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 4871c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 4872c506a872SMatthew G. Knepley } 4873c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 4874c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 4875c506a872SMatthew 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); 4876c506a872SMatthew G. Knepley 4877c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 4878c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 4879c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 4880c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 4881c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 4882c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 4883c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 4884c506a872SMatthew G. Knepley } 4885c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 4886c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 4887c506a872SMatthew 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); 4888c506a872SMatthew G. Knepley } 48893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4890c506a872SMatthew G. Knepley } 4891c506a872SMatthew G. Knepley 4892d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems *PetscOptionsObject) 4893d71ae5a4SJacob Faibussowitsch { 4894bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 4895bdf63967SMatthew G. Knepley char oname[256]; 48964e22dd4cSMatthew G. Knepley char sublabelname[PETSC_MAX_PATH_LEN] = ""; 4897adc21957SMatthew G. Knepley DMReorderDefaultFlag reorder; 4898d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 48999318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 49001b742f01SMatthew 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; 490168d4fef7SMatthew G. Knepley 490268d4fef7SMatthew G. Knepley PetscFunctionBegin; 4903d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 4904dd4c3f67SMatthew G. Knepley if (dm->cloneOpts) goto non_refine; 49059318fe57SMatthew G. Knepley /* Handle automatic creation */ 49069566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 49076bc1bd01Sksagiyam if (dim < 0) { 49086bc1bd01Sksagiyam PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 49096bc1bd01Sksagiyam created = PETSC_TRUE; 49106bc1bd01Sksagiyam } 49116bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 4912d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 49139566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 4914d89e6e46SMatthew G. Knepley if (flg) { 4915d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 4916d89e6e46SMatthew G. Knepley 49179566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 4918d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 4919d89e6e46SMatthew G. Knepley DM udm; 4920d89e6e46SMatthew G. Knepley 49219566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 492269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 4923d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 4924d89e6e46SMatthew G. Knepley DM idm; 4925d89e6e46SMatthew G. Knepley 49269566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 492769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 4928d89e6e46SMatthew G. Knepley } 4929d89e6e46SMatthew G. Knepley } 49304e22dd4cSMatthew G. Knepley // Handle submesh selection before distribution 49314e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_submesh", "Label to use for submesh selection", "", sublabelname, sublabelname, PETSC_MAX_PATH_LEN, &flg)); 49324e22dd4cSMatthew G. Knepley if (flg) { 49334e22dd4cSMatthew G. Knepley DM subdm; 49344e22dd4cSMatthew G. Knepley DMLabel label; 49354e22dd4cSMatthew G. Knepley IS valueIS, pointIS; 49364e22dd4cSMatthew G. Knepley const PetscInt *values, *points; 49374e22dd4cSMatthew G. Knepley PetscBool markedFaces = PETSC_FALSE; 49384e22dd4cSMatthew G. Knepley PetscInt Nv, value, Np; 49394e22dd4cSMatthew G. Knepley 49404e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, sublabelname, &label)); 49414e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &Nv)); 49424e22dd4cSMatthew 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); 49434e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetValueIS(label, &valueIS)); 49444e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &values)); 49454e22dd4cSMatthew G. Knepley value = values[0]; 49464e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(valueIS, &values)); 49474e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 49484e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumSize(label, value, &Np)); 49494e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, value, &pointIS)); 49504e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &points)); 49514e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 49524e22dd4cSMatthew G. Knepley PetscInt pdepth; 49534e22dd4cSMatthew G. Knepley 49544e22dd4cSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, points[p], &pdepth)); 49554e22dd4cSMatthew G. Knepley if (pdepth) { 49564e22dd4cSMatthew G. Knepley markedFaces = PETSC_TRUE; 49574e22dd4cSMatthew G. Knepley break; 49584e22dd4cSMatthew G. Knepley } 49594e22dd4cSMatthew G. Knepley } 49604e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &points)); 49614e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 49624e22dd4cSMatthew G. Knepley PetscCall(DMPlexCreateSubmesh(dm, label, value, markedFaces, &subdm)); 49634e22dd4cSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &subdm)); 49644e22dd4cSMatthew G. Knepley PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 49654e22dd4cSMatthew G. Knepley } 49669b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 49679566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 49689566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 49699566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 49709566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 49719566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 49729566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 49739318fe57SMatthew G. Knepley if (flg) { 49749566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 49759566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 49769318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 49779318fe57SMatthew G. Knepley } 4978b23db253SStefano Zampini if (prerefine) PetscCall(DMLocalizeCoordinates(dm)); 49799b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 49809b44eab4SMatthew G. Knepley DM rdm; 49819b44eab4SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 49829b44eab4SMatthew G. Knepley 4983dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 49849566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 498569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 4986dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 498761a622f3SMatthew G. Knepley if (coordFunc && remap) { 49889566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 49899b44eab4SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 49909b44eab4SMatthew G. Knepley } 49919b44eab4SMatthew G. Knepley } 49929566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 49939318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 49949566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 49959318fe57SMatthew G. Knepley if (extLayers) { 49969318fe57SMatthew G. Knepley DM edm; 49979318fe57SMatthew G. Knepley 49989566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 499969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 500048d16a33SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = NULL; 5001dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5002d410b0cfSMatthew G. Knepley extLayers = 0; 50035e17fc22SAidan Hamilton PetscCall(DMGetDimension(dm, &dim)); 50049318fe57SMatthew G. Knepley } 5005bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 50066bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 50079566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 50086bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 50099566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 5010adc21957SMatthew G. Knepley if (reorder == DM_REORDER_DEFAULT_TRUE || flg) { 5011bdf63967SMatthew G. Knepley DM pdm; 5012bdf63967SMatthew G. Knepley IS perm; 5013bdf63967SMatthew G. Knepley 50149566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 50159566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 50169566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 501769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 5018dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5019bdf63967SMatthew G. Knepley } 50209b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 50219566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 5022c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 5023a286e215SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute_save_sf", "Flag to save the migration SF", "DMPlexSetMigrationSF", saveSF, &saveSF, NULL)); 5024dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 50259b44eab4SMatthew G. Knepley if (distribute) { 50269b44eab4SMatthew G. Knepley DM pdm = NULL; 50279b44eab4SMatthew G. Knepley PetscPartitioner part; 5028a286e215SMatthew G. Knepley PetscSF sfMigration; 50299b44eab4SMatthew G. Knepley 50309566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 50319566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 5032a286e215SMatthew G. Knepley PetscCall(DMPlexDistribute(dm, overlap, &sfMigration, &pdm)); 50335d2873a6SJames Wright if (pdm) { 50345d2873a6SJames Wright // Delete the local section to force the existing one to be rebuilt with the distributed DM 50355d2873a6SJames Wright PetscCall(DMSetLocalSection(dm, pdm->localSection)); 50365d2873a6SJames Wright PetscCall(DMPlexReplace_Internal(dm, &pdm)); 50375d2873a6SJames Wright } 5038a286e215SMatthew G. Knepley if (saveSF) PetscCall(DMPlexSetMigrationSF(dm, sfMigration)); 5039a286e215SMatthew G. Knepley PetscCall(PetscSFDestroy(&sfMigration)); 50409b44eab4SMatthew G. Knepley } 50414054ae39SJames Wright 50424054ae39SJames Wright { 50434054ae39SJames Wright PetscBool useBoxLabel = PETSC_FALSE; 50444054ae39SJames Wright PetscCall(PetscOptionsBool("-dm_plex_box_label", "Create 'Face Sets' assuming boundary faces align with cartesian directions", "DMCreate", useBoxLabel, &useBoxLabel, NULL)); 5045d7d2d1d2SJames Wright if (useBoxLabel) { 5046d7d2d1d2SJames Wright PetscInt n = 3; 5047d7d2d1d2SJames Wright DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 5048d7d2d1d2SJames Wright 5049d7d2d1d2SJames Wright PetscCall(PetscOptionsEnumArray("-dm_plex_box_label_bd", "Boundary type for each dimension when using -dm_plex_box_label", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 5050d7d2d1d2SJames 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); 5051d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, bdt)); 5052d7d2d1d2SJames Wright } 50534054ae39SJames Wright } 5054d2b2dc1eSMatthew G. Knepley /* Must check CEED options before creating function space for coordinates */ 5055d2b2dc1eSMatthew G. Knepley { 5056d2b2dc1eSMatthew G. Knepley PetscBool useCeed = PETSC_FALSE, flg; 5057d2b2dc1eSMatthew G. Knepley 5058d2b2dc1eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_use_ceed", "Use LibCEED as the FEM backend", "DMPlexSetUseCeed", useCeed, &useCeed, &flg)); 5059d2b2dc1eSMatthew G. Knepley if (flg) PetscCall(DMPlexSetUseCeed(dm, useCeed)); 5060d2b2dc1eSMatthew G. Knepley } 50619318fe57SMatthew G. Knepley /* Create coordinate space */ 50629318fe57SMatthew G. Knepley if (created) { 506361a622f3SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5064e44f6aebSMatthew G. Knepley PetscInt degree = 1, deg; 50655515ebd3SMatthew G. Knepley PetscInt height = 0; 50665515ebd3SMatthew G. Knepley DM cdm; 5067c3db174cSMatthew G. Knepley PetscBool flg, localize = PETSC_TRUE, sparseLocalize = PETSC_TRUE; 50689318fe57SMatthew G. Knepley 50699566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg)); 50709566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 5071e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDegree_Internal(dm, °)); 5072e44f6aebSMatthew G. Knepley if (coordSpace && deg <= 1) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_TRUE, mesh->coordFunc)); 50735515ebd3SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 507461a622f3SMatthew G. Knepley if (flg && !coordSpace) { 507561a622f3SMatthew G. Knepley PetscDS cds; 507661a622f3SMatthew G. Knepley PetscObject obj; 507761a622f3SMatthew G. Knepley PetscClassId id; 507861a622f3SMatthew G. Knepley 50799566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 50809566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 50819566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 508261a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 508361a622f3SMatthew G. Knepley PetscContainer dummy; 508461a622f3SMatthew G. Knepley 50859566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 50869566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 50879566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 50889566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 50899566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 509061a622f3SMatthew G. Knepley } 509161a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 509261a622f3SMatthew G. Knepley } 5093c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_localize", "Localize mesh coordinates", "", localize, &localize, NULL)); 5094c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "DMSetSparseLocalize", sparseLocalize, &sparseLocalize, &flg)); 5095c3db174cSMatthew G. Knepley if (flg) PetscCall(DMSetSparseLocalize(dm, sparseLocalize)); 50965515ebd3SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg)); 50975515ebd3SMatthew G. Knepley if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height)); 5098c3db174cSMatthew G. Knepley if (localize) PetscCall(DMLocalizeCoordinates(dm)); 50999318fe57SMatthew G. Knepley } 510068d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 510161a622f3SMatthew G. Knepley remap = PETSC_TRUE; 51029566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 51039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 51049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 51059566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 510668d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 5107acdc6f61SToby Isaac DM *dms, coarseDM; 510868d4fef7SMatthew G. Knepley 51099566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 51109566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 51119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 51129566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 511368d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 51149566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 511568d4fef7SMatthew G. Knepley if (refine == 1) { 51169566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 51179566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 511868d4fef7SMatthew G. Knepley } else { 51199566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 51209566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 51219566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 51229566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 512368d4fef7SMatthew G. Knepley } 51249566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 51259566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 512668d4fef7SMatthew G. Knepley /* Free DMs */ 512768d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 5128dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 51299566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 513068d4fef7SMatthew G. Knepley } 51319566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 513268d4fef7SMatthew G. Knepley } else { 513368d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 51349318fe57SMatthew G. Knepley DM rdm; 513551a74b61SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 513668d4fef7SMatthew G. Knepley 5137dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 51389566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 513968d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 514069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 5141dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 514261a622f3SMatthew G. Knepley if (coordFunc && remap) { 51439566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 514451a74b61SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 514551a74b61SMatthew G. Knepley } 514668d4fef7SMatthew G. Knepley } 514768d4fef7SMatthew G. Knepley } 51483cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 51499566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 51509566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 5151b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 5152b653a561SMatthew G. Knepley DM *dms; 5153b653a561SMatthew G. Knepley 51549566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 51559566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 5156b653a561SMatthew G. Knepley /* Free DMs */ 5157b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 5158dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 51599566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 5160b653a561SMatthew G. Knepley } 51619566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 5162b653a561SMatthew G. Knepley } else { 5163b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 51649318fe57SMatthew G. Knepley DM cdm; 51659318fe57SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 51663cf6fe12SMatthew G. Knepley 5167dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 51689566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 51693cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 517069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 5171dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 51729318fe57SMatthew G. Knepley if (coordFunc) { 51739566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 51749318fe57SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 51759318fe57SMatthew G. Knepley } 51763cf6fe12SMatthew G. Knepley } 5177b653a561SMatthew G. Knepley } 5178be664eb1SMatthew G. Knepley // Handle coordinate remapping 5179be664eb1SMatthew G. Knepley remap = PETSC_FALSE; 5180be664eb1SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_coord_remap", "Flag to control coordinate remapping", "", remap, &remap, NULL)); 5181be664eb1SMatthew G. Knepley if (remap) { 5182be664eb1SMatthew G. Knepley DMPlexCoordMap map = DM_COORD_MAP_NONE; 5183be664eb1SMatthew G. Knepley PetscPointFunc mapFunc = NULL; 5184be664eb1SMatthew G. Knepley PetscScalar params[16]; 5185f45b553cSPierre Jolivet PetscInt Np = PETSC_STATIC_ARRAY_LENGTH(params), cdim; 5186be664eb1SMatthew G. Knepley MPI_Comm comm; 5187be664eb1SMatthew G. Knepley 5188be664eb1SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 5189be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 5190be664eb1SMatthew G. Knepley PetscCall(PetscOptionsScalarArray("-dm_coord_map_params", "Parameters for the coordinate remapping", "", params, &Np, &flg)); 5191be664eb1SMatthew G. Knepley if (!flg) Np = 0; 5192be664eb1SMatthew G. Knepley // TODO Allow user to pass a map function by name 5193be664eb1SMatthew G. Knepley PetscCall(PetscOptionsEnum("-dm_coord_map", "Coordinate mapping for built-in mesh", "", DMPlexCoordMaps, (PetscEnum)map, (PetscEnum *)&map, &flg)); 5194be664eb1SMatthew G. Knepley if (flg) { 5195be664eb1SMatthew G. Knepley switch (map) { 5196be664eb1SMatthew G. Knepley case DM_COORD_MAP_NONE: 5197be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5198be664eb1SMatthew G. Knepley break; 5199be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHEAR: 5200be664eb1SMatthew G. Knepley mapFunc = coordMap_shear; 5201be664eb1SMatthew G. Knepley if (!Np) { 5202be664eb1SMatthew G. Knepley Np = cdim + 1; 5203be664eb1SMatthew G. Knepley params[0] = 0; 5204be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5205be664eb1SMatthew G. Knepley } 5206be664eb1SMatthew 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); 5207be664eb1SMatthew G. Knepley break; 5208be664eb1SMatthew G. Knepley case DM_COORD_MAP_FLARE: 5209be664eb1SMatthew G. Knepley mapFunc = coordMap_flare; 5210be664eb1SMatthew G. Knepley if (!Np) { 5211be664eb1SMatthew G. Knepley Np = cdim + 1; 5212be664eb1SMatthew G. Knepley params[0] = 0; 5213be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5214be664eb1SMatthew G. Knepley } 5215be664eb1SMatthew 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); 5216be664eb1SMatthew G. Knepley break; 5217be664eb1SMatthew G. Knepley case DM_COORD_MAP_ANNULUS: 5218be664eb1SMatthew G. Knepley mapFunc = coordMap_annulus; 5219be664eb1SMatthew G. Knepley if (!Np) { 5220be664eb1SMatthew G. Knepley Np = 2; 5221be664eb1SMatthew G. Knepley params[0] = 1.; 5222be664eb1SMatthew G. Knepley params[1] = 2.; 5223be664eb1SMatthew G. Knepley } 5224be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The annulus coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5225be664eb1SMatthew G. Knepley break; 5226be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHELL: 5227be664eb1SMatthew G. Knepley mapFunc = coordMap_shell; 5228be664eb1SMatthew G. Knepley if (!Np) { 5229be664eb1SMatthew G. Knepley Np = 2; 5230be664eb1SMatthew G. Knepley params[0] = 1.; 5231be664eb1SMatthew G. Knepley params[1] = 2.; 5232be664eb1SMatthew G. Knepley } 5233be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The spherical shell coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5234be664eb1SMatthew G. Knepley break; 5235be664eb1SMatthew G. Knepley default: 5236be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5237be664eb1SMatthew G. Knepley } 5238be664eb1SMatthew G. Knepley } 5239be664eb1SMatthew G. Knepley if (Np) { 5240be664eb1SMatthew G. Knepley DM cdm; 5241be664eb1SMatthew G. Knepley PetscDS cds; 5242be664eb1SMatthew G. Knepley 5243be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5244be664eb1SMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 5245be664eb1SMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, Np, params)); 5246be664eb1SMatthew G. Knepley } 5247be664eb1SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, mapFunc)); 5248be664eb1SMatthew G. Knepley } 5249909dfd52SMatthew G. Knepley /* Handle ghost cells */ 52509566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 5251909dfd52SMatthew G. Knepley if (ghostCells) { 5252909dfd52SMatthew G. Knepley DM gdm; 5253909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 5254909dfd52SMatthew G. Knepley 5255909dfd52SMatthew G. Knepley lname[0] = '\0'; 52569566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 52579566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 525869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 5259909dfd52SMatthew G. Knepley } 52606913077dSMatthew G. Knepley /* Handle 1D order */ 5261adc21957SMatthew G. Knepley if (reorder != DM_REORDER_DEFAULT_FALSE && dim == 1) { 52626913077dSMatthew G. Knepley DM cdm, rdm; 52636913077dSMatthew G. Knepley PetscDS cds; 52646913077dSMatthew G. Knepley PetscObject obj; 52656913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 52666913077dSMatthew G. Knepley IS perm; 52676bc1bd01Sksagiyam PetscInt Nf; 52686913077dSMatthew G. Knepley PetscBool distributed; 52696913077dSMatthew G. Knepley 52709566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 52719566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 52729566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 52739566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 52746913077dSMatthew G. Knepley if (Nf) { 52759566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 52769566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 52776913077dSMatthew G. Knepley } 52786bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 52799566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 52809566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 528169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 52829566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 52836913077dSMatthew G. Knepley } 52846913077dSMatthew G. Knepley } 52853cf6fe12SMatthew G. Knepley /* Handle */ 5286dd4c3f67SMatthew G. Knepley non_refine: 5287dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 528822d6dc08SStefano Zampini char *phases[16]; 528922d6dc08SStefano Zampini PetscInt Nphases = 16; 529022d6dc08SStefano Zampini PetscCall(PetscOptionsStringArray("-dm_plex_option_phases", "Option phase prefixes", "DMSetFromOptions", phases, &Nphases, &flg)); 5291d0609cedSBarry Smith PetscOptionsHeadEnd(); 529222d6dc08SStefano Zampini 529322d6dc08SStefano Zampini // Phases 529422d6dc08SStefano Zampini if (flg) { 529522d6dc08SStefano Zampini const char *oldPrefix; 529622d6dc08SStefano Zampini 529722d6dc08SStefano Zampini PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &oldPrefix)); 529822d6dc08SStefano Zampini for (PetscInt ph = 0; ph < Nphases; ++ph) { 529922d6dc08SStefano Zampini PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, phases[ph])); 530022d6dc08SStefano Zampini PetscCall(PetscInfo(dm, "Options phase %s for DM %s\n", phases[ph], dm->hdr.name)); 530122d6dc08SStefano Zampini PetscCall(DMSetFromOptions(dm)); 530222d6dc08SStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix)); 530322d6dc08SStefano Zampini PetscCall(PetscFree(phases[ph])); 530422d6dc08SStefano Zampini } 530522d6dc08SStefano Zampini } 53063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 53070a6ba040SMatthew G. Knepley } 53080a6ba040SMatthew G. Knepley 5309d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) 5310d71ae5a4SJacob Faibussowitsch { 5311552f7358SJed Brown PetscFunctionBegin; 53129566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 53139566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 53149566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 53159566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 53169566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 53179566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 53183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5319552f7358SJed Brown } 5320552f7358SJed Brown 5321d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) 5322d71ae5a4SJacob Faibussowitsch { 5323552f7358SJed Brown PetscFunctionBegin; 53249566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 53259566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 53269566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 53273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5328552f7358SJed Brown } 5329552f7358SJed Brown 5330d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 5331d71ae5a4SJacob Faibussowitsch { 5332793f3fe5SMatthew G. Knepley PetscInt depth, d; 5333793f3fe5SMatthew G. Knepley 5334793f3fe5SMatthew G. Knepley PetscFunctionBegin; 53359566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 5336793f3fe5SMatthew G. Knepley if (depth == 1) { 53379566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 53389566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 53399566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 53409371c9d4SSatish Balay else { 53419371c9d4SSatish Balay *pStart = 0; 53429371c9d4SSatish Balay *pEnd = 0; 53439371c9d4SSatish Balay } 5344793f3fe5SMatthew G. Knepley } else { 53459566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 5346793f3fe5SMatthew G. Knepley } 53473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5348793f3fe5SMatthew G. Knepley } 5349793f3fe5SMatthew G. Knepley 5350d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 5351d71ae5a4SJacob Faibussowitsch { 5352502a2867SDave May PetscSF sf; 53536497c311SBarry Smith PetscMPIInt niranks, njranks; 53546497c311SBarry Smith PetscInt n; 53550a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 53560a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 5357502a2867SDave May 53582f356facSMatthew G. Knepley PetscFunctionBegin; 53599566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 53600a19bb7dSprj- if (!data->neighbors) { 53619566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 53629566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 53639566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 53649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 53659566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 53669566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 53670a19bb7dSprj- n = njranks + niranks; 53689566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 53690a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 53709566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 53710a19bb7dSprj- } 53720a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 53730a19bb7dSprj- if (ranks) { 53740a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 53750a19bb7dSprj- else *ranks = NULL; 53760a19bb7dSprj- } 53773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5378502a2867SDave May } 5379502a2867SDave May 53801eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 53811eb70e55SToby Isaac 5382d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm) 5383d71ae5a4SJacob Faibussowitsch { 5384552f7358SJed Brown PetscFunctionBegin; 5385552f7358SJed Brown dm->ops->view = DMView_Plex; 53862c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 5387552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 538838221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 5389552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 53901bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 5391adc21957SMatthew G. Knepley dm->ops->createsectionpermutation = DMCreateSectionPermutation_Plex; 539266ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 5393552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 5394552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 5395184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 53960298fd71SBarry Smith dm->ops->createfieldis = NULL; 5397552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 5398f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 53990a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 5400552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 5401bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 5402bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 5403b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 54045a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 5405552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 54060a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 54070a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 5408b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 5409d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 54100298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 54110298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 54120298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 54130298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 5414552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 5415552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 54162adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 5417793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 5418552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 54190709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 54200709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 5421bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 54228c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 5423ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 54240709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 5425b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 54262a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 542728d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 54286c6a6b79SMatthew G. Knepley dm->ops->getlocalboundingbox = DMGetLocalBoundingBox_Coordinates; 5429907a3e9cSStefano Zampini dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_Plex; 5430907a3e9cSStefano Zampini dm->ops->createddscatters = DMCreateDomainDecompositionScatters_Plex; 54319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 54326c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 54339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 54349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 54359566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 54369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 54376bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 54386bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 5439adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", DMReorderSectionGetDefault_Plex)); 5440adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", DMReorderSectionSetDefault_Plex)); 5441adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", DMReorderSectionGetType_Plex)); 5442adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", DMReorderSectionSetType_Plex)); 54439566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 5444c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 5445c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 5446d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", DMPlexGetUseCeed_Plex)); 5447d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", DMPlexSetUseCeed_Plex)); 54483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5449552f7358SJed Brown } 5450552f7358SJed Brown 5451d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 5452d71ae5a4SJacob Faibussowitsch { 545363a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 54541fca310dSJames Wright const PetscSF *face_sfs; 54551fca310dSJames Wright PetscInt num_face_sfs; 545663a16f15SMatthew G. Knepley 545763a16f15SMatthew G. Knepley PetscFunctionBegin; 545863a16f15SMatthew G. Knepley mesh->refct++; 545963a16f15SMatthew G. Knepley (*newdm)->data = mesh; 54601fca310dSJames Wright PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &face_sfs)); 54611fca310dSJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, num_face_sfs, (PetscSF *)face_sfs)); 54629566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 54639566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 54643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 546563a16f15SMatthew G. Knepley } 546663a16f15SMatthew G. Knepley 54678818961aSMatthew G Knepley /*MC 5468a1cb98faSBarry Smith DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh, or CW Complex, which can be expressed using a Hasse Diagram. 546920f4b53cSBarry Smith In the local representation, `Vec`s contain all unknowns in the interior and shared boundary. This is 54708818961aSMatthew G Knepley specified by a PetscSection object. Ownership in the global representation is determined by 5471a1cb98faSBarry Smith ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object. 54728818961aSMatthew G Knepley 5473e5893cccSMatthew G. Knepley Options Database Keys: 5474250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 5475250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 5476250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 5477250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 5478250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 5479250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 5480c3db174cSMatthew G. Knepley . -dm_localize <bool> - Whether to localize coordinates for periodic meshes 5481c3db174cSMatthew G. Knepley . -dm_sparse_localize <bool> - Whether to only localize cells on the periodic boundary 5482250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 5483ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 5484f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 5485f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 5486d5b43468SJose E. Roman . -dm_plex_max_projection_height - Maximum mesh point height used to project locally 5487f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 5488d02c7345SMatthew G. Knepley . -dm_plex_reorder_section - Use specialized blocking if available 5489aaa8cc7dSPierre Jolivet . -dm_plex_check_all - Perform all checks below 5490f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 5491f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 5492f12cf164SMatthew 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 5493f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 5494f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 5495e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 54965962854dSMatthew G. Knepley . -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 54975962854dSMatthew G. Knepley - -dm_plex_print_fvm <num> - View FVM assembly information, such as flux updates 5498e5893cccSMatthew G. Knepley 54998818961aSMatthew G Knepley Level: intermediate 55008818961aSMatthew G Knepley 55011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection` 55028818961aSMatthew G Knepley M*/ 55038818961aSMatthew G Knepley 5504d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 5505d71ae5a4SJacob Faibussowitsch { 5506552f7358SJed Brown DM_Plex *mesh; 5507412e9a14SMatthew G. Knepley PetscInt unit; 5508552f7358SJed Brown 5509552f7358SJed Brown PetscFunctionBegin; 5510f39ec787SMatthew G. Knepley PetscCall(PetscCitationsRegister(PlexCitation, &Plexcite)); 5511552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 55124dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mesh)); 5513adc21957SMatthew G. Knepley dm->reorderSection = DM_REORDER_DEFAULT_NOTSET; 5514552f7358SJed Brown dm->data = mesh; 5515552f7358SJed Brown 5516552f7358SJed Brown mesh->refct = 1; 55179566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 55189566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 5519552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 5520552f7358SJed Brown mesh->refinementLimit = -1.0; 5521e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 5522adc21957SMatthew G. Knepley mesh->reorderDefault = DM_REORDER_DEFAULT_NOTSET; 55231d1f2f2aSksagiyam mesh->distributionName = NULL; 55247d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 55257d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 55265e2c5519SMatthew G. Knepley mesh->interpolatePreferTensor = PETSC_TRUE; 5527552f7358SJed Brown 55289566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 55292e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 5530d9deefdfSMatthew G. Knepley 55318865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 5532552f7358SJed Brown 5533df0420ecSMatthew G. Knepley mesh->depthState = -1; 5534ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 55356113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 5536c29ce622SStefano Zampini mesh->nonempty_comm = MPI_COMM_SELF; 5537552f7358SJed Brown 55389566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 55393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5540552f7358SJed Brown } 5541552f7358SJed Brown 5542552f7358SJed Brown /*@ 5543a1cb98faSBarry Smith DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 5544552f7358SJed Brown 5545d083f849SBarry Smith Collective 5546552f7358SJed Brown 5547552f7358SJed Brown Input Parameter: 5548a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object 5549552f7358SJed Brown 5550552f7358SJed Brown Output Parameter: 5551a1cb98faSBarry Smith . mesh - The `DMPLEX` object 5552552f7358SJed Brown 5553552f7358SJed Brown Level: beginner 5554552f7358SJed Brown 555542747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMCreate()`, `DMSetType()` 5556552f7358SJed Brown @*/ 5557d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 5558d71ae5a4SJacob Faibussowitsch { 5559552f7358SJed Brown PetscFunctionBegin; 55604f572ea9SToby Isaac PetscAssertPointer(mesh, 2); 55619566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 55629566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 55633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5564552f7358SJed Brown } 5565552f7358SJed Brown 5566b09969d6SVaclav Hapla /*@C 5567b0fe842aSMatthew 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 5568a1cb98faSBarry Smith 556920f4b53cSBarry Smith Collective; No Fortran Support 5570b09969d6SVaclav Hapla 5571b09969d6SVaclav Hapla Input Parameters: 5572a1cb98faSBarry Smith + dm - The `DM` 5573b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 5574a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 5575a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DETERMINE` 5576b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 55775e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 5578b09969d6SVaclav Hapla 5579be8c289dSNicolas Barral Output Parameters: 5580a1cb98faSBarry Smith + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 5581be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 5582b09969d6SVaclav Hapla 5583b09969d6SVaclav Hapla Level: advanced 5584b09969d6SVaclav Hapla 5585a1cb98faSBarry Smith Notes: 5586a1cb98faSBarry Smith Two triangles sharing a face 5587a1cb98faSBarry Smith .vb 5588a1cb98faSBarry Smith 5589a1cb98faSBarry Smith 2 5590a1cb98faSBarry Smith / | \ 5591a1cb98faSBarry Smith / | \ 5592a1cb98faSBarry Smith / | \ 5593a1cb98faSBarry Smith 0 0 | 1 3 5594a1cb98faSBarry Smith \ | / 5595a1cb98faSBarry Smith \ | / 5596a1cb98faSBarry Smith \ | / 5597a1cb98faSBarry Smith 1 5598a1cb98faSBarry Smith .ve 5599a1cb98faSBarry Smith would have input 5600a1cb98faSBarry Smith .vb 5601a1cb98faSBarry Smith numCells = 2, numVertices = 4 5602a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 5603a1cb98faSBarry Smith .ve 5604a1cb98faSBarry Smith which would result in the `DMPLEX` 5605a1cb98faSBarry Smith .vb 5606a1cb98faSBarry Smith 5607a1cb98faSBarry Smith 4 5608a1cb98faSBarry Smith / | \ 5609a1cb98faSBarry Smith / | \ 5610a1cb98faSBarry Smith / | \ 5611a1cb98faSBarry Smith 2 0 | 1 5 5612a1cb98faSBarry Smith \ | / 5613a1cb98faSBarry Smith \ | / 5614a1cb98faSBarry Smith \ | / 5615a1cb98faSBarry Smith 3 5616a1cb98faSBarry Smith .ve 5617a1cb98faSBarry Smith 5618a1cb98faSBarry Smith Vertices are implicitly numbered consecutively 0,...,NVertices. 5619a1cb98faSBarry Smith Each rank owns a chunk of numVertices consecutive vertices. 5620a1cb98faSBarry Smith If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 5621a1cb98faSBarry Smith If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 5622a1cb98faSBarry Smith If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 5623a1cb98faSBarry Smith 5624a1cb98faSBarry Smith The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 5625a1cb98faSBarry Smith 56261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 5627a1cb98faSBarry Smith `PetscSF` 5628b09969d6SVaclav Hapla @*/ 5629d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved) 5630d71ae5a4SJacob Faibussowitsch { 56312464107aSksagiyam PetscSF sfPoint; 56322464107aSksagiyam PetscLayout layout; 563382fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 5634a47d0d45SMatthew G. Knepley 5635a47d0d45SMatthew G. Knepley PetscFunctionBegin; 563625b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 56379566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 563825b6865aSVaclav Hapla /* Get/check global number of vertices */ 563925b6865aSVaclav Hapla { 564025b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 564125b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 564225b6865aSVaclav Hapla 564325b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 56441690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 56459371c9d4SSatish Balay for (i = 0; i < len; i++) 56469371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 564725b6865aSVaclav Hapla ++NVerticesInCells; 5648462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 564925b6865aSVaclav Hapla 565025b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 56519371c9d4SSatish Balay else 56529371c9d4SSatish 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); 565325b6865aSVaclav Hapla } 56549079aca8SVaclav Hapla /* Count locally unique vertices */ 56559079aca8SVaclav Hapla { 56569079aca8SVaclav Hapla PetscHSetI vhash; 56579079aca8SVaclav Hapla PetscInt off = 0; 56589079aca8SVaclav Hapla 56599566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 5660a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 566148a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 5662a47d0d45SMatthew G. Knepley } 56639566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 56649566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 5665ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 56669566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 56679566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 566863a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 5669a47d0d45SMatthew G. Knepley } 56709566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 5671a47d0d45SMatthew G. Knepley /* Create cones */ 56729566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 56739566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 56749566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 56759566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 5676a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 5677a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 5678a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 5679a47d0d45SMatthew G. Knepley PetscInt lv; 5680a47d0d45SMatthew G. Knepley 56819079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 56829079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 56839566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 568463a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 5685961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 5686a47d0d45SMatthew G. Knepley } 5687a47d0d45SMatthew G. Knepley } 56882464107aSksagiyam /* Build point sf */ 56899566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 56909566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 56919566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 56929566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 56939566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 56949566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 56959566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 56969566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 56972464107aSksagiyam if (dm->sf) { 56982464107aSksagiyam const char *prefix; 56992464107aSksagiyam 57009566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 57019566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 57022464107aSksagiyam } 57039566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 57049566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 5705f4f49eeaSPierre Jolivet if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 5706a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 57079566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 57089566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 57099566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 57103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5711a47d0d45SMatthew G. Knepley } 5712a47d0d45SMatthew G. Knepley 5713b0fe842aSMatthew G. Knepley /*@C 5714b0fe842aSMatthew G. Knepley DMPlexBuildFromCellSectionParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) allowing multiple celltypes 5715b0fe842aSMatthew G. Knepley 5716b0fe842aSMatthew G. Knepley Collective; No Fortran Support 5717b0fe842aSMatthew G. Knepley 5718b0fe842aSMatthew G. Knepley Input Parameters: 5719b0fe842aSMatthew G. Knepley + dm - The `DM` 5720b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 5721b0fe842aSMatthew G. Knepley . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 5722b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DETERMINE` 5723b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 5724b0fe842aSMatthew G. Knepley - cells - An array of the global vertex numbers for each cell 5725b0fe842aSMatthew G. Knepley 5726b0fe842aSMatthew G. Knepley Output Parameters: 5727b0fe842aSMatthew G. Knepley + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 5728b0fe842aSMatthew G. Knepley - verticesAdjSaved - (Optional) vertex adjacency array 5729b0fe842aSMatthew G. Knepley 5730b0fe842aSMatthew G. Knepley Level: advanced 5731b0fe842aSMatthew G. Knepley 5732b0fe842aSMatthew G. Knepley Notes: 5733b0fe842aSMatthew G. Knepley A triangle and quadrilateral sharing a face 5734b0fe842aSMatthew G. Knepley .vb 5735b0fe842aSMatthew G. Knepley 2----------3 5736b0fe842aSMatthew G. Knepley / | | 5737b0fe842aSMatthew G. Knepley / | | 5738b0fe842aSMatthew G. Knepley / | | 5739b0fe842aSMatthew G. Knepley 0 0 | 1 | 5740b0fe842aSMatthew G. Knepley \ | | 5741b0fe842aSMatthew G. Knepley \ | | 5742b0fe842aSMatthew G. Knepley \ | | 5743b0fe842aSMatthew G. Knepley 1----------4 5744b0fe842aSMatthew G. Knepley .ve 5745b0fe842aSMatthew G. Knepley would have input 5746b0fe842aSMatthew G. Knepley .vb 5747b0fe842aSMatthew G. Knepley numCells = 2, numVertices = 5 5748b0fe842aSMatthew G. Knepley cells = [0 1 2 1 4 3 2] 5749b0fe842aSMatthew G. Knepley .ve 5750b0fe842aSMatthew G. Knepley which would result in the `DMPLEX` 5751b0fe842aSMatthew G. Knepley .vb 5752b0fe842aSMatthew G. Knepley 4----------5 5753b0fe842aSMatthew G. Knepley / | | 5754b0fe842aSMatthew G. Knepley / | | 5755b0fe842aSMatthew G. Knepley / | | 5756b0fe842aSMatthew G. Knepley 2 0 | 1 | 5757b0fe842aSMatthew G. Knepley \ | | 5758b0fe842aSMatthew G. Knepley \ | | 5759b0fe842aSMatthew G. Knepley \ | | 5760b0fe842aSMatthew G. Knepley 3----------6 5761b0fe842aSMatthew G. Knepley .ve 5762b0fe842aSMatthew G. Knepley 5763b0fe842aSMatthew G. Knepley Vertices are implicitly numbered consecutively 0,...,NVertices. 5764b0fe842aSMatthew G. Knepley Each rank owns a chunk of numVertices consecutive vertices. 5765b0fe842aSMatthew G. Knepley If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 5766b0fe842aSMatthew 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. 5767b0fe842aSMatthew G. Knepley If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 5768b0fe842aSMatthew G. Knepley 5769b0fe842aSMatthew G. Knepley The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 5770b0fe842aSMatthew G. Knepley 5771b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexCreateFromCellSectionParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 5772b0fe842aSMatthew G. Knepley `PetscSF` 5773b0fe842aSMatthew G. Knepley @*/ 5774b0fe842aSMatthew G. Knepley PetscErrorCode DMPlexBuildFromCellSectionParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, const PetscInt cells[], PetscSF *vertexSF, PetscInt **verticesAdjSaved) 5775b0fe842aSMatthew G. Knepley { 5776b0fe842aSMatthew G. Knepley PetscSF sfPoint; 5777b0fe842aSMatthew G. Knepley PetscLayout layout; 5778b0fe842aSMatthew G. Knepley PetscInt numVerticesAdj, *verticesAdj, *cones, cStart, cEnd, len; 5779b0fe842aSMatthew G. Knepley 5780b0fe842aSMatthew G. Knepley PetscFunctionBegin; 5781b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, NVertices, 4); 5782b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 5783b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetChart(cellSection, &cStart, &cEnd)); 5784b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(cellSection, &len)); 5785b0fe842aSMatthew 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); 5786b0fe842aSMatthew G. Knepley /* Get/check global number of vertices */ 5787b0fe842aSMatthew G. Knepley { 5788b0fe842aSMatthew G. Knepley PetscInt NVerticesInCells; 5789b0fe842aSMatthew G. Knepley 5790b0fe842aSMatthew G. Knepley /* NVerticesInCells = max(cells) + 1 */ 5791b0fe842aSMatthew G. Knepley NVerticesInCells = PETSC_MIN_INT; 5792b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) 5793b0fe842aSMatthew G. Knepley if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 5794b0fe842aSMatthew G. Knepley ++NVerticesInCells; 5795b0fe842aSMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 5796b0fe842aSMatthew G. Knepley 5797b0fe842aSMatthew G. Knepley if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 5798b0fe842aSMatthew G. Knepley else 5799b0fe842aSMatthew 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); 5800b0fe842aSMatthew G. Knepley } 5801b0fe842aSMatthew G. Knepley /* Count locally unique vertices */ 5802b0fe842aSMatthew G. Knepley { 5803b0fe842aSMatthew G. Knepley PetscHSetI vhash; 5804b0fe842aSMatthew G. Knepley PetscInt off = 0; 5805b0fe842aSMatthew G. Knepley 5806b0fe842aSMatthew G. Knepley PetscCall(PetscHSetICreate(&vhash)); 5807b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) PetscCall(PetscHSetIAdd(vhash, cells[i])); 5808b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 5809b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 5810b0fe842aSMatthew G. Knepley else verticesAdj = *verticesAdjSaved; 5811b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 5812b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIDestroy(&vhash)); 5813b0fe842aSMatthew 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); 5814b0fe842aSMatthew G. Knepley } 5815b0fe842aSMatthew G. Knepley PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 5816b0fe842aSMatthew G. Knepley /* Create cones */ 5817b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 5818b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 5819b0fe842aSMatthew G. Knepley PetscInt dof; 5820b0fe842aSMatthew G. Knepley 5821b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 5822b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetConeSize(dm, c, dof)); 5823b0fe842aSMatthew G. Knepley } 5824b0fe842aSMatthew G. Knepley PetscCall(DMSetUp(dm)); 5825b0fe842aSMatthew G. Knepley PetscCall(DMPlexGetCones(dm, &cones)); 5826b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 5827b0fe842aSMatthew G. Knepley PetscInt dof, off; 5828b0fe842aSMatthew G. Knepley 5829b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 5830b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cellSection, c, &off)); 5831b0fe842aSMatthew G. Knepley for (PetscInt p = off; p < off + dof; ++p) { 5832b0fe842aSMatthew G. Knepley const PetscInt gv = cells[p]; 5833b0fe842aSMatthew G. Knepley PetscInt lv; 5834b0fe842aSMatthew G. Knepley 5835b0fe842aSMatthew G. Knepley /* Positions within verticesAdj form 0-based local vertex numbering; 5836b0fe842aSMatthew G. Knepley we need to shift it by numCells to get correct DAG points (cells go first) */ 5837b0fe842aSMatthew G. Knepley PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 5838b0fe842aSMatthew G. Knepley PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 5839b0fe842aSMatthew G. Knepley cones[p] = lv + numCells; 5840b0fe842aSMatthew G. Knepley } 5841b0fe842aSMatthew G. Knepley } 5842b0fe842aSMatthew G. Knepley /* Build point sf */ 5843b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 5844b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetSize(layout, NVertices)); 5845b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 5846b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetBlockSize(layout, 1)); 5847b0fe842aSMatthew G. Knepley PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 5848b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutDestroy(&layout)); 5849b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 5850b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 5851b0fe842aSMatthew G. Knepley if (dm->sf) { 5852b0fe842aSMatthew G. Knepley const char *prefix; 5853b0fe842aSMatthew G. Knepley 5854b0fe842aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 5855b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 5856b0fe842aSMatthew G. Knepley } 5857b0fe842aSMatthew G. Knepley PetscCall(DMSetPointSF(dm, sfPoint)); 5858b0fe842aSMatthew G. Knepley PetscCall(PetscSFDestroy(&sfPoint)); 5859b0fe842aSMatthew G. Knepley if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 5860b0fe842aSMatthew G. Knepley /* Fill in the rest of the topology structure */ 5861b0fe842aSMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 5862b0fe842aSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 5863b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 5864b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5865b0fe842aSMatthew G. Knepley } 5866b0fe842aSMatthew G. Knepley 5867cc4c1da9SBarry Smith /*@ 5868a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 5869a1cb98faSBarry Smith 587020f4b53cSBarry Smith Collective; No Fortran Support 5871b09969d6SVaclav Hapla 5872b09969d6SVaclav Hapla Input Parameters: 5873a1cb98faSBarry Smith + dm - The `DM` 5874b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 5875a1cb98faSBarry Smith . sfVert - `PetscSF` describing complete vertex ownership 5876b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 5877b09969d6SVaclav Hapla 5878b09969d6SVaclav Hapla Level: advanced 5879b09969d6SVaclav Hapla 58801cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 5881b09969d6SVaclav Hapla @*/ 5882d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 5883d71ae5a4SJacob Faibussowitsch { 5884a47d0d45SMatthew G. Knepley PetscSection coordSection; 5885a47d0d45SMatthew G. Knepley Vec coordinates; 5886a47d0d45SMatthew G. Knepley PetscScalar *coords; 58871edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 5888835f2295SStefano Zampini PetscMPIInt spaceDimi; 5889a47d0d45SMatthew G. Knepley 5890a47d0d45SMatthew G. Knepley PetscFunctionBegin; 58919566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 58929566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 58931dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 58949566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 58959566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 58961dca8a05SBarry 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); 58979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 58989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 58999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 59009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 59011edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 59029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 59039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 5904a47d0d45SMatthew G. Knepley } 59059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 59069566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 59079566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 59089566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 59099566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 59109566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 59119566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 59129566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5913a47d0d45SMatthew G. Knepley { 5914a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 5915a47d0d45SMatthew G. Knepley 5916a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 5917835f2295SStefano Zampini PetscCall(PetscMPIIntCast(spaceDim, &spaceDimi)); 5918835f2295SStefano Zampini PetscCallMPI(MPI_Type_contiguous(spaceDimi, MPIU_SCALAR, &coordtype)); 59199566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 592021016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 592121016a8bSBarry Smith { 592221016a8bSBarry Smith PetscScalar *svertexCoords; 592321016a8bSBarry Smith PetscInt i; 59249566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 59253612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 59269566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 59279566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 59289566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 592921016a8bSBarry Smith } 593021016a8bSBarry Smith #else 59319566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 59329566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 593321016a8bSBarry Smith #endif 59349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 5935a47d0d45SMatthew G. Knepley } 59369566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 59379566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 59389566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 59399566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 59403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5941a47d0d45SMatthew G. Knepley } 5942a47d0d45SMatthew G. Knepley 5943c3edce3dSSatish Balay /*@ 5944b0fe842aSMatthew 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 5945a1cb98faSBarry Smith 5946a1cb98faSBarry Smith Collective 5947a47d0d45SMatthew G. Knepley 5948a47d0d45SMatthew G. Knepley Input Parameters: 5949a47d0d45SMatthew G. Knepley + comm - The communicator 5950a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 5951a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 5952a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 5953a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DECIDE` 5954a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 5955a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 5956a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 5957a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 5958a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 5959a47d0d45SMatthew G. Knepley 5960d8d19677SJose E. Roman Output Parameters: 5961a1cb98faSBarry Smith + dm - The `DM` 5962a1cb98faSBarry Smith . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 596360225df5SJacob Faibussowitsch - verticesAdj - (Optional) vertex adjacency array 5964a47d0d45SMatthew G. Knepley 5965b09969d6SVaclav Hapla Level: intermediate 5966a47d0d45SMatthew G. Knepley 5967a1cb98faSBarry Smith Notes: 5968a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 5969a1cb98faSBarry Smith `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 5970a1cb98faSBarry Smith 5971a1cb98faSBarry Smith See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters. 5972a1cb98faSBarry Smith 5973a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 5974a1cb98faSBarry Smith 59751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 5976a47d0d45SMatthew G. Knepley @*/ 5977d71ae5a4SJacob 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) 5978d71ae5a4SJacob Faibussowitsch { 5979a47d0d45SMatthew G. Knepley PetscSF sfVert; 5980a47d0d45SMatthew G. Knepley 5981a47d0d45SMatthew G. Knepley PetscFunctionBegin; 59829566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 59839566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 5984a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 5985064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 59869566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 59879566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 5988a47d0d45SMatthew G. Knepley if (interpolate) { 59895fd9971aSMatthew G. Knepley DM idm; 5990a47d0d45SMatthew G. Knepley 59919566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 59929566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 5993a47d0d45SMatthew G. Knepley *dm = idm; 5994a47d0d45SMatthew G. Knepley } 59959566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 599618d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 59979566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 59983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5999a47d0d45SMatthew G. Knepley } 6000a47d0d45SMatthew G. Knepley 6001cc4c1da9SBarry Smith /*@ 6002b0fe842aSMatthew G. Knepley DMPlexCreateFromCellSectionParallel - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) and supports multiple celltypes 6003b0fe842aSMatthew G. Knepley 6004b0fe842aSMatthew G. Knepley Collective 6005b0fe842aSMatthew G. Knepley 6006b0fe842aSMatthew G. Knepley Input Parameters: 6007b0fe842aSMatthew G. Knepley + comm - The communicator 6008b0fe842aSMatthew G. Knepley . dim - The topological dimension of the mesh 6009b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 6010b0fe842aSMatthew G. Knepley . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 6011b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DECIDE` 6012b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 6013b0fe842aSMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6014b0fe842aSMatthew G. Knepley . cells - An array of the global vertex numbers for each cell 6015b0fe842aSMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 6016b0fe842aSMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6017b0fe842aSMatthew G. Knepley 6018b0fe842aSMatthew G. Knepley Output Parameters: 6019b0fe842aSMatthew G. Knepley + dm - The `DM` 6020b0fe842aSMatthew G. Knepley . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 6021b0fe842aSMatthew G. Knepley - verticesAdj - (Optional) vertex adjacency array 6022b0fe842aSMatthew G. Knepley 6023b0fe842aSMatthew G. Knepley Level: intermediate 6024b0fe842aSMatthew G. Knepley 6025b0fe842aSMatthew G. Knepley Notes: 6026b0fe842aSMatthew G. Knepley This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 6027b0fe842aSMatthew G. Knepley `DMPlexBuildFromCellSectionParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 6028b0fe842aSMatthew G. Knepley 6029b0fe842aSMatthew G. Knepley See `DMPlexBuildFromCellSectionParallel()` for an example and details about the topology-related parameters. 6030b0fe842aSMatthew G. Knepley 6031b0fe842aSMatthew G. Knepley See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 6032b0fe842aSMatthew G. Knepley 6033b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 6034b0fe842aSMatthew G. Knepley @*/ 6035b0fe842aSMatthew 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) 6036b0fe842aSMatthew G. Knepley { 6037b0fe842aSMatthew G. Knepley PetscSF sfVert; 6038b0fe842aSMatthew G. Knepley 6039b0fe842aSMatthew G. Knepley PetscFunctionBegin; 6040b0fe842aSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 6041b0fe842aSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 6042b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 6043b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 6044b0fe842aSMatthew G. Knepley PetscCall(DMSetDimension(*dm, dim)); 6045b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildFromCellSectionParallel(*dm, numCells, numVertices, NVertices, cellSection, cells, &sfVert, verticesAdj)); 6046b0fe842aSMatthew G. Knepley if (interpolate) { 6047b0fe842aSMatthew G. Knepley DM idm; 6048b0fe842aSMatthew G. Knepley 6049b0fe842aSMatthew G. Knepley PetscCall(DMPlexInterpolate(*dm, &idm)); 6050b0fe842aSMatthew G. Knepley PetscCall(DMDestroy(dm)); 6051b0fe842aSMatthew G. Knepley *dm = idm; 6052b0fe842aSMatthew G. Knepley } 6053b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 6054b0fe842aSMatthew G. Knepley if (vertexSF) *vertexSF = sfVert; 6055b0fe842aSMatthew G. Knepley else PetscCall(PetscSFDestroy(&sfVert)); 6056b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 6057b0fe842aSMatthew G. Knepley } 6058b0fe842aSMatthew G. Knepley 6059b0fe842aSMatthew G. Knepley /*@ 6060a1cb98faSBarry Smith DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) 6061a1cb98faSBarry Smith 606220f4b53cSBarry Smith Collective; No Fortran Support 60639298eaa6SMatthew G Knepley 60649298eaa6SMatthew G Knepley Input Parameters: 6065a1cb98faSBarry Smith + dm - The `DM` 6066b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 6067a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE` 60689298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 6069a3b724e8SBarry Smith - cells - An array of `numCells` x `numCorners` numbers, the global vertex numbers for each cell 60709298eaa6SMatthew G Knepley 6071b09969d6SVaclav Hapla Level: advanced 60729298eaa6SMatthew G Knepley 6073b09969d6SVaclav Hapla Notes: 6074b09969d6SVaclav Hapla Two triangles sharing a face 6075a1cb98faSBarry Smith .vb 60769298eaa6SMatthew G Knepley 6077a1cb98faSBarry Smith 2 6078a1cb98faSBarry Smith / | \ 6079a1cb98faSBarry Smith / | \ 6080a1cb98faSBarry Smith / | \ 6081a1cb98faSBarry Smith 0 0 | 1 3 6082a1cb98faSBarry Smith \ | / 6083a1cb98faSBarry Smith \ | / 6084a1cb98faSBarry Smith \ | / 6085a1cb98faSBarry Smith 1 6086a1cb98faSBarry Smith .ve 6087a1cb98faSBarry Smith would have input 6088a1cb98faSBarry Smith .vb 6089a1cb98faSBarry Smith numCells = 2, numVertices = 4 6090a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 6091a1cb98faSBarry Smith .ve 6092a1cb98faSBarry Smith which would result in the `DMPLEX` 6093a1cb98faSBarry Smith .vb 6094a1cb98faSBarry Smith 6095a1cb98faSBarry Smith 4 6096a1cb98faSBarry Smith / | \ 6097a1cb98faSBarry Smith / | \ 6098a1cb98faSBarry Smith / | \ 6099a1cb98faSBarry Smith 2 0 | 1 5 6100a1cb98faSBarry Smith \ | / 6101a1cb98faSBarry Smith \ | / 6102a1cb98faSBarry Smith \ | / 6103a1cb98faSBarry Smith 3 6104a1cb98faSBarry Smith .ve 6105a1cb98faSBarry Smith 6106a1cb98faSBarry Smith If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1. 610725b6865aSVaclav Hapla 61081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 6109b09969d6SVaclav Hapla @*/ 6110d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 6111d71ae5a4SJacob Faibussowitsch { 6112961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 6113b09969d6SVaclav Hapla 6114b09969d6SVaclav Hapla PetscFunctionBegin; 61159566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 61169566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 611725b6865aSVaclav Hapla /* Get/check global number of vertices */ 611825b6865aSVaclav Hapla { 611925b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 612025b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 612125b6865aSVaclav Hapla 612225b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 61231690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 61249371c9d4SSatish Balay for (i = 0; i < len; i++) 61259371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 612625b6865aSVaclav Hapla ++NVerticesInCells; 612725b6865aSVaclav Hapla 612825b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 61299371c9d4SSatish Balay else 61309371c9d4SSatish 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); 613125b6865aSVaclav Hapla } 61329566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 613348a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 61349566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 61359566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 6136b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 6137ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 6138b09969d6SVaclav Hapla } 61399566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 61409566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 61419566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 61423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6143b09969d6SVaclav Hapla } 6144b09969d6SVaclav Hapla 6145cc4c1da9SBarry Smith /*@ 6146a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 6147a1cb98faSBarry Smith 6148cc4c1da9SBarry Smith Collective 6149b09969d6SVaclav Hapla 6150b09969d6SVaclav Hapla Input Parameters: 6151a1cb98faSBarry Smith + dm - The `DM` 6152b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6153b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6154b09969d6SVaclav Hapla 6155b09969d6SVaclav Hapla Level: advanced 6156b09969d6SVaclav Hapla 61571cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 6158b09969d6SVaclav Hapla @*/ 6159d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 6160d71ae5a4SJacob Faibussowitsch { 6161b09969d6SVaclav Hapla PetscSection coordSection; 6162b09969d6SVaclav Hapla Vec coordinates; 6163b09969d6SVaclav Hapla DM cdm; 6164b09969d6SVaclav Hapla PetscScalar *coords; 61651edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 6166b09969d6SVaclav Hapla 6167b09969d6SVaclav Hapla PetscFunctionBegin; 61689566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 61699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 61701dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 61719566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 61729566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 61739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 61749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 61759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 61761edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 61779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 61789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 6179b09969d6SVaclav Hapla } 61809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6181b09969d6SVaclav Hapla 61829566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 61839566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 61849566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 61859566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 61869566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 61871edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 6188ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 6189b09969d6SVaclav Hapla } 61909566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 61919566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 61929566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 61939566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 61943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6195b09969d6SVaclav Hapla } 6196b09969d6SVaclav Hapla 6197b09969d6SVaclav Hapla /*@ 6198a1cb98faSBarry Smith DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 61993df08285SMatthew G. Knepley 6200a1cb98faSBarry Smith Collective 6201b09969d6SVaclav Hapla 6202b09969d6SVaclav Hapla Input Parameters: 6203b09969d6SVaclav Hapla + comm - The communicator 6204b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 62053df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 6206a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0 62073df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 6208b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 62093df08285SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the vertices for each cell, only on process 0 6210b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 62113df08285SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex, only on process 0 6212b09969d6SVaclav Hapla 6213b09969d6SVaclav Hapla Output Parameter: 6214a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0 621525b6865aSVaclav Hapla 6216b09969d6SVaclav Hapla Level: intermediate 6217b09969d6SVaclav Hapla 6218a1cb98faSBarry Smith Notes: 6219a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`, 6220a1cb98faSBarry Smith `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()` 6221a1cb98faSBarry Smith 6222a1cb98faSBarry Smith See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters. 6223a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters. 6224a1cb98faSBarry Smith See `DMPlexCreateFromCellListParallelPetsc()` for parallel input 6225a1cb98faSBarry Smith 62261cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 62279298eaa6SMatthew G Knepley @*/ 6228d71ae5a4SJacob 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) 6229d71ae5a4SJacob Faibussowitsch { 62303df08285SMatthew G. Knepley PetscMPIInt rank; 62319298eaa6SMatthew G Knepley 62329298eaa6SMatthew G Knepley PetscFunctionBegin; 623328b400f6SJacob 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."); 62349566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 62359566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 62369566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 62379566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 6238c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 62399566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 62409298eaa6SMatthew G Knepley if (interpolate) { 62415fd9971aSMatthew G. Knepley DM idm; 62429298eaa6SMatthew G Knepley 62439566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 62449566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 62459298eaa6SMatthew G Knepley *dm = idm; 62469298eaa6SMatthew G Knepley } 6247c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 62489566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 62493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 62509298eaa6SMatthew G Knepley } 62519298eaa6SMatthew G Knepley 6252939f6067SMatthew G. Knepley /*@ 625320f4b53cSBarry Smith DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a `DM` 6254939f6067SMatthew G. Knepley 6255939f6067SMatthew G. Knepley Input Parameters: 625620f4b53cSBarry Smith + dm - The empty `DM` object, usually from `DMCreate()` and `DMSetDimension()` 6257939f6067SMatthew G. Knepley . depth - The depth of the DAG 625820f4b53cSBarry Smith . numPoints - Array of size depth + 1 containing the number of points at each `depth` 6259939f6067SMatthew G. Knepley . coneSize - The cone size of each point 6260939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 6261939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 626220f4b53cSBarry Smith - vertexCoords - An array of `numPoints`[0]*spacedim numbers representing the coordinates of each vertex, with spacedim the value set via `DMSetCoordinateDim()` 6263939f6067SMatthew G. Knepley 6264939f6067SMatthew G. Knepley Output Parameter: 626520f4b53cSBarry Smith . dm - The `DM` 626620f4b53cSBarry Smith 626720f4b53cSBarry Smith Level: advanced 6268939f6067SMatthew G. Knepley 6269a1cb98faSBarry Smith Note: 6270a1cb98faSBarry Smith Two triangles sharing a face would have input 6271a1cb98faSBarry Smith .vb 6272a1cb98faSBarry Smith depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 6273a1cb98faSBarry Smith cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 6274a1cb98faSBarry Smith vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 6275a1cb98faSBarry Smith .ve 6276939f6067SMatthew G. Knepley which would result in the DMPlex 6277a1cb98faSBarry Smith .vb 6278a1cb98faSBarry Smith 4 6279a1cb98faSBarry Smith / | \ 6280a1cb98faSBarry Smith / | \ 6281a1cb98faSBarry Smith / | \ 6282a1cb98faSBarry Smith 2 0 | 1 5 6283a1cb98faSBarry Smith \ | / 6284a1cb98faSBarry Smith \ | / 6285a1cb98faSBarry Smith \ | / 6286a1cb98faSBarry Smith 3 6287a1cb98faSBarry Smith .ve 6288a1cb98faSBarry Smith Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()` 6289939f6067SMatthew G. Knepley 62901cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 6291939f6067SMatthew G. Knepley @*/ 6292d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 6293d71ae5a4SJacob Faibussowitsch { 62949298eaa6SMatthew G Knepley Vec coordinates; 62959298eaa6SMatthew G Knepley PetscSection coordSection; 62969298eaa6SMatthew G Knepley PetscScalar *coords; 6297811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 62989298eaa6SMatthew G Knepley 62999298eaa6SMatthew G Knepley PetscFunctionBegin; 63009566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 63019566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 630263a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 63039298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 63049566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 63059298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 63069566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 6307ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 630897e052ccSToby Isaac } 63091dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 63109566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 63119298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 63129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 63139566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 63149298eaa6SMatthew G Knepley } 63159566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 63169566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 63179298eaa6SMatthew G Knepley /* Build coordinates */ 63189566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 63199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 63209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 63219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 63229298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 63239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 63249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 63259298eaa6SMatthew G Knepley } 63269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 63279566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 63289566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 63299566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 63309566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 63319566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dimEmbed)); 63329566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 63339318fe57SMatthew G. Knepley if (vertexCoords) { 63349566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 63359298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 63369298eaa6SMatthew G Knepley PetscInt off; 63379298eaa6SMatthew G Knepley 63389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 6339ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 63409298eaa6SMatthew G Knepley } 63419318fe57SMatthew G. Knepley } 63429566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 63439566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 63449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 63453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63469298eaa6SMatthew G Knepley } 63478415267dSToby Isaac 6348a4e35b19SJacob Faibussowitsch /* 6349a1cb98faSBarry Smith DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file. 6350a1cb98faSBarry Smith 6351a1cb98faSBarry Smith Collective 63528ca92349SMatthew G. Knepley 63538ca92349SMatthew G. Knepley + comm - The MPI communicator 63548ca92349SMatthew G. Knepley . filename - Name of the .dat file 63558ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 63568ca92349SMatthew G. Knepley 63578ca92349SMatthew G. Knepley Output Parameter: 6358a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 63598ca92349SMatthew G. Knepley 63608ca92349SMatthew G. Knepley Level: beginner 63618ca92349SMatthew G. Knepley 6362a1cb98faSBarry Smith Note: 6363a1cb98faSBarry Smith The format is the simplest possible: 6364a1cb98faSBarry Smith .vb 6365d0812dedSMatthew G. Knepley dim Ne Nv Nc Nl 6366d0812dedSMatthew G. Knepley v_1 v_2 ... v_Nc 6367d0812dedSMatthew G. Knepley ... 6368d0812dedSMatthew G. Knepley x y z marker_1 ... marker_Nl 6369a1cb98faSBarry Smith .ve 6370a1cb98faSBarry Smith 6371a1cb98faSBarry Smith Developer Note: 6372a1cb98faSBarry Smith Should use a `PetscViewer` not a filename 6373a1cb98faSBarry Smith 63746afe31f6SMartin Diehl .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 6375a4e35b19SJacob Faibussowitsch */ 6376ff6a9541SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 6377d71ae5a4SJacob Faibussowitsch { 63788ca92349SMatthew G. Knepley DMLabel marker; 63798ca92349SMatthew G. Knepley PetscViewer viewer; 63808ca92349SMatthew G. Knepley Vec coordinates; 63818ca92349SMatthew G. Knepley PetscSection coordSection; 63828ca92349SMatthew G. Knepley PetscScalar *coords; 63838ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 6384d0812dedSMatthew G. Knepley PetscInt cdim, coordSize, v, c, d; 63858ca92349SMatthew G. Knepley PetscMPIInt rank; 6386d0812dedSMatthew G. Knepley int snum, dim, Nv, Nc, Ncn, Nl; 63878ca92349SMatthew G. Knepley 63888ca92349SMatthew G. Knepley PetscFunctionBegin; 63899566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 63909566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 63919566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 63929566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 63939566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 6394dd400576SPatrick Sanan if (rank == 0) { 6395d0812dedSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING)); 6396d0812dedSMatthew G. Knepley snum = sscanf(line, "%d %d %d %d %d", &dim, &Nc, &Nv, &Ncn, &Nl); 6397d0812dedSMatthew G. Knepley PetscCheck(snum == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 639825ce1634SJed Brown } else { 6399f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 64008ca92349SMatthew G. Knepley } 6401d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm)); 6402835f2295SStefano Zampini cdim = dim; 64039566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 64049566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 64059566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 6406835f2295SStefano Zampini PetscCall(DMSetDimension(*dm, dim)); 64079566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 64088ca92349SMatthew G. Knepley /* Read topology */ 6409dd400576SPatrick Sanan if (rank == 0) { 6410f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 6411f8d5e320SMatthew G. Knepley PetscInt cone[8]; 64128ca92349SMatthew G. Knepley int vbuf[8], v; 64138ca92349SMatthew G. Knepley 64149371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 64159371c9d4SSatish Balay format[c * 3 + 0] = '%'; 64169371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 64179371c9d4SSatish Balay format[c * 3 + 2] = ' '; 64189371c9d4SSatish Balay } 6419f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 64209566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 64219566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 64228ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 64239566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 6424f8d5e320SMatthew G. Knepley switch (Ncn) { 6425d71ae5a4SJacob Faibussowitsch case 2: 6426d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1]); 6427d71ae5a4SJacob Faibussowitsch break; 6428d71ae5a4SJacob Faibussowitsch case 3: 6429d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); 6430d71ae5a4SJacob Faibussowitsch break; 6431d71ae5a4SJacob Faibussowitsch case 4: 6432d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); 6433d71ae5a4SJacob Faibussowitsch break; 6434d71ae5a4SJacob Faibussowitsch case 6: 6435d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); 6436d71ae5a4SJacob Faibussowitsch break; 6437d71ae5a4SJacob Faibussowitsch case 8: 6438d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 6439d71ae5a4SJacob Faibussowitsch break; 6440d71ae5a4SJacob Faibussowitsch default: 6441d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 6442f8d5e320SMatthew G. Knepley } 644308401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6444f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 64458ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 6446f8d5e320SMatthew G. Knepley if (Ncn == 8) { 64478ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 64488ca92349SMatthew G. Knepley cone[1] = cone[3]; 64498ca92349SMatthew G. Knepley cone[3] = tmp; 64508ca92349SMatthew G. Knepley } 64519566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 64528ca92349SMatthew G. Knepley } 64538ca92349SMatthew G. Knepley } 64549566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 64559566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 64568ca92349SMatthew G. Knepley /* Read coordinates */ 64579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 64589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 64599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 64609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 64618ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 64629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 64639566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 64648ca92349SMatthew G. Knepley } 64659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 64669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 64679566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 64689566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 64699566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 64709566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 64719566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 64729566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6473dd400576SPatrick Sanan if (rank == 0) { 6474f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 64758ca92349SMatthew G. Knepley double x[3]; 6476f8d5e320SMatthew G. Knepley int l, val[3]; 64778ca92349SMatthew G. Knepley 6478f8d5e320SMatthew G. Knepley if (Nl) { 64799371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 64809371c9d4SSatish Balay format[l * 3 + 0] = '%'; 64819371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 64829371c9d4SSatish Balay format[l * 3 + 2] = ' '; 64839371c9d4SSatish Balay } 6484f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 64859566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 64869566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 6487f8d5e320SMatthew G. Knepley } 64888ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 64899566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 6490f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 649108401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6492f8d5e320SMatthew G. Knepley switch (Nl) { 6493d71ae5a4SJacob Faibussowitsch case 0: 6494d71ae5a4SJacob Faibussowitsch snum = 0; 6495d71ae5a4SJacob Faibussowitsch break; 6496d71ae5a4SJacob Faibussowitsch case 1: 6497d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0]); 6498d71ae5a4SJacob Faibussowitsch break; 6499d71ae5a4SJacob Faibussowitsch case 2: 6500d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1]); 6501d71ae5a4SJacob Faibussowitsch break; 6502d71ae5a4SJacob Faibussowitsch case 3: 6503d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1], &val[2]); 6504d71ae5a4SJacob Faibussowitsch break; 6505d71ae5a4SJacob Faibussowitsch default: 6506d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 6507f8d5e320SMatthew G. Knepley } 650808401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 65098ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 65109566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 65118ca92349SMatthew G. Knepley } 65128ca92349SMatthew G. Knepley } 65139566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 65149566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 65159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 65169566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 65178ca92349SMatthew G. Knepley if (interpolate) { 65188ca92349SMatthew G. Knepley DM idm; 65198ca92349SMatthew G. Knepley DMLabel bdlabel; 65208ca92349SMatthew G. Knepley 65219566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 65229566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 65238ca92349SMatthew G. Knepley *dm = idm; 65248ca92349SMatthew G. Knepley 6525f8d5e320SMatthew G. Knepley if (!Nl) { 65269566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 65279566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 65289566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 65299566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 65308ca92349SMatthew G. Knepley } 6531f8d5e320SMatthew G. Knepley } 65323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 65338ca92349SMatthew G. Knepley } 65348ca92349SMatthew G. Knepley 6535cc4c1da9SBarry Smith /*@ 6536a1cb98faSBarry Smith DMPlexCreateFromFile - This takes a filename and produces a `DM` 6537a1cb98faSBarry Smith 6538a1cb98faSBarry Smith Collective 6539ca522641SMatthew G. Knepley 6540ca522641SMatthew G. Knepley Input Parameters: 6541ca522641SMatthew G. Knepley + comm - The communicator 6542ca522641SMatthew G. Knepley . filename - A file name 6543a1cb98faSBarry Smith . plexname - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats 6544ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 6545ca522641SMatthew G. Knepley 6546ca522641SMatthew G. Knepley Output Parameter: 6547a1cb98faSBarry Smith . dm - The `DM` 6548ca522641SMatthew G. Knepley 6549a1cb98faSBarry Smith Options Database Key: 6550a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5 655102ef0d99SVaclav Hapla 655237fdd005SBarry Smith Use `-dm_plex_create_ prefix` to pass options to the internal `PetscViewer`, e.g. 6553bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective 6554bca97951SVaclav Hapla 6555ca522641SMatthew G. Knepley Level: beginner 6556ca522641SMatthew G. Knepley 6557a1cb98faSBarry Smith Notes: 6558a1cb98faSBarry Smith Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX` 6559a1cb98faSBarry Smith meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()` 6560a1cb98faSBarry Smith before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object. 6561a1cb98faSBarry Smith The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally 6562a1cb98faSBarry Smith calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats. 6563a1cb98faSBarry Smith 65641cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 6565ca522641SMatthew G. Knepley @*/ 6566d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 6567d71ae5a4SJacob Faibussowitsch { 6568ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 6569ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 6570ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 6571ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 6572ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 6573ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 6574ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 6575ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 6576ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 65776f2c871aSStefano Zampini const char extXDMFHDF5[] = ".xdmf.h5"; 6578ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 6579*5552b385SBrandon const char extEGADSlite[] = ".egadslite"; 6580ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 6581ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 6582*5552b385SBrandon const char extIGES2[] = ".iges"; 6583ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 6584*5552b385SBrandon const char extSTEP2[] = ".step"; 6585*5552b385SBrandon const char extBREP[] = ".brep"; 6586ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 6587ca522641SMatthew G. Knepley size_t len; 6588*5552b385SBrandon PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isPLY, isEGADSlite, isEGADS, isIGES, isIGES2, isSTEP, isSTEP2, isBREP, isCV, isXDMFHDF5; 6589ca522641SMatthew G. Knepley PetscMPIInt rank; 6590ca522641SMatthew G. Knepley 6591ca522641SMatthew G. Knepley PetscFunctionBegin; 65924f572ea9SToby Isaac PetscAssertPointer(filename, 2); 65934f572ea9SToby Isaac if (plexname) PetscAssertPointer(plexname, 3); 65944f572ea9SToby Isaac PetscAssertPointer(dm, 5); 65959566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 65969566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 65979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 65989566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 659928b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 6600ef3a5affSJacob Faibussowitsch 66019371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 66029371c9d4SSatish Balay do { \ 6603274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 6604274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 6605274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 6606274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 6607ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 6608ef3a5affSJacob Faibussowitsch } else { \ 6609274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 6610ef3a5affSJacob Faibussowitsch } \ 6611ef3a5affSJacob Faibussowitsch } while (0) 6612ef3a5affSJacob Faibussowitsch 6613ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 6614ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 6615ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 6616ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 6617ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 6618ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 6619ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 6620ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 6621ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 6622ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 6623*5552b385SBrandon CheckExtension(extEGADSlite, isEGADSlite); 6624ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 6625ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 6626*5552b385SBrandon CheckExtension(extIGES2, isIGES2); 6627ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 6628*5552b385SBrandon CheckExtension(extSTEP2, isSTEP2); 6629*5552b385SBrandon CheckExtension(extBREP, isBREP); 6630ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 66316f2c871aSStefano Zampini CheckExtension(extXDMFHDF5, isXDMFHDF5); 6632ef3a5affSJacob Faibussowitsch 6633ef3a5affSJacob Faibussowitsch #undef CheckExtension 6634ef3a5affSJacob Faibussowitsch 6635de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 66369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 6637ca522641SMatthew G. Knepley } else if (isCGNS) { 66389566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 663990c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 66409566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 66412f0bd6dcSMichael Lange } else if (isFluent) { 66429566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 6643cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 6644cc2f8f65SMatthew G. Knepley PetscViewer viewer; 6645cc2f8f65SMatthew G. Knepley 664643b242b4SVaclav 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 */ 66476f2c871aSStefano Zampini PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &isXDMFHDF5, NULL)); 66489566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 66499566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 66509566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 66519566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 66529566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 66539566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 6654cd7e8a5eSksagiyam 66559566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 6656f4f49eeaSPierre Jolivet PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 66579566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 66586f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 66599566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 66606f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPopFormat(viewer)); 66619566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 66625fd9971aSMatthew G. Knepley 66635fd9971aSMatthew G. Knepley if (interpolate) { 66645fd9971aSMatthew G. Knepley DM idm; 66655fd9971aSMatthew G. Knepley 66669566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 66679566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 66685fd9971aSMatthew G. Knepley *dm = idm; 66695fd9971aSMatthew G. Knepley } 6670f2801cd6SMatthew G. Knepley } else if (isPLY) { 66719566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 6672*5552b385SBrandon } else if (isEGADSlite || isEGADS || isIGES || isIGES2 || isSTEP || isSTEP2 || isBREP) { 6673*5552b385SBrandon PetscCall(DMPlexCreateGeomFromFile(comm, filename, dm, isEGADSlite)); 6674*5552b385SBrandon 66757bee2925SMatthew Knepley if (!interpolate) { 66767bee2925SMatthew Knepley DM udm; 66777bee2925SMatthew Knepley 66789566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 66799566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 66807bee2925SMatthew Knepley *dm = udm; 66817bee2925SMatthew Knepley } 66828ca92349SMatthew G. Knepley } else if (isCV) { 66839566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 668498921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 66859566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 6686f4f49eeaSPierre Jolivet if (len) PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 66879566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 66883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6689ca522641SMatthew G. Knepley } 669012b8a6daSStefano Zampini 6691cc4c1da9SBarry Smith /*@ 66929f6c5813SMatthew 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. 66939f6c5813SMatthew G. Knepley 66940528010dSStefano Zampini Input Parameters: 66950528010dSStefano Zampini + tr - The `DMPlexTransform` 66960528010dSStefano Zampini - prefix - An options prefix, or NULL 66979f6c5813SMatthew G. Knepley 66989f6c5813SMatthew G. Knepley Output Parameter: 66999f6c5813SMatthew G. Knepley . dm - The `DM` 67009f6c5813SMatthew G. Knepley 67019f6c5813SMatthew G. Knepley Level: beginner 67029f6c5813SMatthew G. Knepley 670320f4b53cSBarry Smith Notes: 670420f4b53cSBarry 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. 670520f4b53cSBarry Smith 67069f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 67079f6c5813SMatthew G. Knepley @*/ 67080528010dSStefano Zampini PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, const char prefix[], DM *dm) 67099f6c5813SMatthew G. Knepley { 67100528010dSStefano Zampini DM bdm, bcdm, cdm; 67110528010dSStefano Zampini Vec coordinates, coordinatesNew; 67120528010dSStefano Zampini PetscSection cs; 6713817b2c36SMatthew G. Knepley PetscInt cdim, Nl; 67149f6c5813SMatthew G. Knepley 67159f6c5813SMatthew G. Knepley PetscFunctionBegin; 67169f6c5813SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm)); 67179f6c5813SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 67180528010dSStefano Zampini ((DM_Plex *)(*dm)->data)->interpolated = DMPLEX_INTERPOLATED_FULL; 67190528010dSStefano Zampini // Handle coordinates 67200528010dSStefano Zampini PetscCall(DMPlexTransformGetDM(tr, &bdm)); 6721817b2c36SMatthew G. Knepley PetscCall(DMPlexTransformSetDimensions(tr, bdm, *dm)); 6722817b2c36SMatthew G. Knepley PetscCall(DMGetCoordinateDim(*dm, &cdim)); 67230528010dSStefano Zampini PetscCall(DMGetCoordinateDM(bdm, &bcdm)); 67240528010dSStefano Zampini PetscCall(DMGetCoordinateDM(*dm, &cdm)); 67250528010dSStefano Zampini PetscCall(DMCopyDisc(bcdm, cdm)); 67260528010dSStefano Zampini PetscCall(DMGetLocalSection(cdm, &cs)); 67270528010dSStefano Zampini PetscCall(PetscSectionSetNumFields(cs, 1)); 67280528010dSStefano Zampini PetscCall(PetscSectionSetFieldComponents(cs, 0, cdim)); 67290528010dSStefano Zampini PetscCall(DMGetCoordinatesLocal(bdm, &coordinates)); 67300528010dSStefano Zampini PetscCall(VecDuplicate(coordinates, &coordinatesNew)); 67310528010dSStefano Zampini PetscCall(VecCopy(coordinates, coordinatesNew)); 67320528010dSStefano Zampini PetscCall(DMSetCoordinatesLocal(*dm, coordinatesNew)); 67330528010dSStefano Zampini PetscCall(VecDestroy(&coordinatesNew)); 67349f6c5813SMatthew G. Knepley 67359f6c5813SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)tr)); 67369f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr)); 67379f6c5813SMatthew G. Knepley ((DM_Plex *)(*dm)->data)->tr = tr; 67380528010dSStefano Zampini PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE)); 67390528010dSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix)); 67400528010dSStefano Zampini PetscCall(DMSetFromOptions(*dm)); 67419f6c5813SMatthew G. Knepley 67429f6c5813SMatthew G. Knepley PetscCall(DMGetNumLabels(bdm, &Nl)); 67439f6c5813SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 67449f6c5813SMatthew G. Knepley DMLabel label, labelNew; 67459f6c5813SMatthew G. Knepley const char *lname; 67469f6c5813SMatthew G. Knepley PetscBool isDepth, isCellType; 67479f6c5813SMatthew G. Knepley 67489f6c5813SMatthew G. Knepley PetscCall(DMGetLabelName(bdm, l, &lname)); 67499f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 67509f6c5813SMatthew G. Knepley if (isDepth) continue; 67519f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "celltype", &isCellType)); 67529f6c5813SMatthew G. Knepley if (isCellType) continue; 67539f6c5813SMatthew G. Knepley PetscCall(DMCreateLabel(*dm, lname)); 67549f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(bdm, lname, &label)); 67559f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(*dm, lname, &labelNew)); 67569f6c5813SMatthew G. Knepley PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL)); 67579f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetLabel(labelNew, label)); 67589f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetTransform(labelNew, tr)); 67599f6c5813SMatthew G. Knepley PetscCall(DMLabelSetUp(labelNew)); 67609f6c5813SMatthew G. Knepley } 67613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 67629f6c5813SMatthew G. Knepley } 6763