1552f7358SJed Brown #define PETSCDM_DLL 2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3cc4c1da9SBarry Smith #include <petsc/private/hashseti.h> 40c312b8eSJed Brown #include <petscsf.h> 5cc4c1da9SBarry Smith #include <petscdmplextransform.h> /*I "petscdmplextransform.h" I*/ 69f6c5813SMatthew G. Knepley #include <petscdmlabelephemeral.h> 7b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h> 8b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h> 9552f7358SJed Brown 10d0812dedSMatthew G. Knepley #ifdef PETSC_HAVE_UNISTD_H 11d0812dedSMatthew G. Knepley #include <unistd.h> 12d0812dedSMatthew G. Knepley #endif 13d0812dedSMatthew G. Knepley #include <errno.h> 14d0812dedSMatthew G. Knepley 15708be2fdSJed Brown PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_CreateFromOptions, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList; 1658cd63d5SVaclav Hapla 179318fe57SMatthew G. Knepley /* External function declarations here */ 189318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm); 199318fe57SMatthew G. Knepley 205552b385SBrandon PETSC_EXTERN PetscErrorCode DMPlexCheckEGADS_Private(DM dm) 215552b385SBrandon { 225552b385SBrandon PetscObject modelObj; 235552b385SBrandon 245552b385SBrandon PetscFunctionBegin; 255552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", &modelObj)); 265552b385SBrandon PetscCheck(modelObj, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Input DM must have attached EGADS Geometry Model"); 275552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 285552b385SBrandon } 295552b385SBrandon 305552b385SBrandon static PetscErrorCode DMPlexCopyContext_Private(DM dmin, const char name[], DM dmout) 315552b385SBrandon { 325552b385SBrandon PetscObject obj; 335552b385SBrandon 345552b385SBrandon PetscFunctionBegin; 355552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmin, name, &obj)); 365552b385SBrandon if (obj) PetscCall(PetscObjectCompose((PetscObject)dmout, name, obj)); 375552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 385552b385SBrandon } 395552b385SBrandon 405552b385SBrandon static PetscErrorCode DMPlexSwapContext_Private(DM dmA, const char name[], DM dmB) 415552b385SBrandon { 425552b385SBrandon PetscObject objA, objB; 435552b385SBrandon 445552b385SBrandon PetscFunctionBegin; 455552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmA, name, &objA)); 465552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmB, name, &objB)); 475552b385SBrandon PetscCall(PetscObjectReference(objA)); 485552b385SBrandon PetscCall(PetscObjectReference(objB)); 495552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dmA, name, objB)); 505552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dmB, name, objA)); 515552b385SBrandon PetscCall(PetscObjectDereference(objA)); 525552b385SBrandon PetscCall(PetscObjectDereference(objB)); 535552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 545552b385SBrandon } 555552b385SBrandon 565552b385SBrandon PetscErrorCode DMPlexCopyEGADSInfo_Internal(DM dmin, DM dmout) 575552b385SBrandon { 585552b385SBrandon PetscFunctionBegin; 595552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Model", dmout)); 605552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Context", dmout)); 615552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Model", dmout)); 625552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Context", dmout)); 635552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 645552b385SBrandon } 655552b385SBrandon 665552b385SBrandon static PetscErrorCode DMPlexSwapEGADSInfo_Private(DM dmA, DM dmB) 675552b385SBrandon { 685552b385SBrandon PetscFunctionBegin; 695552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Model", dmB)); 705552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Context", dmB)); 715552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Model", dmB)); 725552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Context", dmB)); 735552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 745552b385SBrandon } 755552b385SBrandon 76e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */ 77d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout) 78d71ae5a4SJacob Faibussowitsch { 794fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 8012a88998SMatthew G. Knepley VecType vecType; 8112a88998SMatthew G. Knepley MatType matType; 82129f447cSJames Wright PetscBool dist, useCeed, balance_partition; 83adc21957SMatthew G. Knepley DMReorderDefaultFlag reorder; 84e600fa54SMatthew G. Knepley 85e600fa54SMatthew G. Knepley PetscFunctionBegin; 86835f2295SStefano Zampini if (dmin == dmout) PetscFunctionReturn(PETSC_SUCCESS); 8712a88998SMatthew G. Knepley PetscCall(DMGetVecType(dmin, &vecType)); 8812a88998SMatthew G. Knepley PetscCall(DMSetVecType(dmout, vecType)); 8912a88998SMatthew G. Knepley PetscCall(DMGetMatType(dmin, &matType)); 9012a88998SMatthew G. Knepley PetscCall(DMSetMatType(dmout, matType)); 91e600fa54SMatthew G. Knepley if (copyPeriodicity) { 924fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L)); 934fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L)); 943d0e8ed9SDavid Salac PetscCall(DMLocalizeCoordinates(dmout)); 95e600fa54SMatthew G. Knepley } 969566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dmin, &dist)); 979566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dmout, dist)); 986bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dmin, &reorder)); 996bc1bd01Sksagiyam PetscCall(DMPlexReorderSetDefault(dmout, reorder)); 1005962854dSMatthew G. Knepley PetscCall(DMPlexGetUseCeed(dmin, &useCeed)); 1015962854dSMatthew G. Knepley PetscCall(DMPlexSetUseCeed(dmout, useCeed)); 102129f447cSJames Wright PetscCall(DMPlexGetPartitionBalance(dmin, &balance_partition)); 103129f447cSJames Wright PetscCall(DMPlexSetPartitionBalance(dmout, balance_partition)); 104e600fa54SMatthew G. Knepley ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation; 1055962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printSetValues = ((DM_Plex *)dmin->data)->printSetValues; 1065962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printFEM = ((DM_Plex *)dmin->data)->printFEM; 1075962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printFVM = ((DM_Plex *)dmin->data)->printFVM; 1085962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printL2 = ((DM_Plex *)dmin->data)->printL2; 1095962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printLocate = ((DM_Plex *)dmin->data)->printLocate; 110a77a5016SMatthew G. Knepley ((DM_Plex *)dmout->data)->printProject = ((DM_Plex *)dmin->data)->printProject; 1115962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printTol = ((DM_Plex *)dmin->data)->printTol; 1121baa6e33SBarry Smith if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0)); 1135552b385SBrandon PetscCall(DMPlexCopyEGADSInfo_Internal(dmin, dmout)); 1143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 115e600fa54SMatthew G. Knepley } 116e600fa54SMatthew G. Knepley 1179318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 1189318fe57SMatthew G. Knepley - Share the DM_Plex structure 1199318fe57SMatthew G. Knepley - Share the coordinates 1209318fe57SMatthew G. Knepley - Share the SF 1219318fe57SMatthew G. Knepley */ 122d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm) 123d71ae5a4SJacob Faibussowitsch { 1249318fe57SMatthew G. Knepley PetscSF sf; 1259318fe57SMatthew G. Knepley DM dmNew = *ndm, coordDM, coarseDM; 1269318fe57SMatthew G. Knepley Vec coords; 1274fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 1289318fe57SMatthew G. Knepley PetscInt dim, cdim; 129e535cce4SJames Wright PetscBool use_natural; 1309318fe57SMatthew G. Knepley 1319318fe57SMatthew G. Knepley PetscFunctionBegin; 1329318fe57SMatthew G. Knepley if (dm == dmNew) { 1339566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 1343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1359318fe57SMatthew G. Knepley } 1369318fe57SMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 137d0812dedSMatthew G. Knepley if (!dm->hdr.name) { 138d0812dedSMatthew G. Knepley const char *name; 139d0812dedSMatthew G. Knepley 140d0812dedSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)*ndm, &name)); 141d0812dedSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, name)); 142d0812dedSMatthew G. Knepley } 1439566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dmNew, &dim)); 1449566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 1459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmNew, &cdim)); 1469566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 1479566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmNew, &sf)); 1489566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sf)); 1499566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmNew, &coordDM)); 1509566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmNew, &coords)); 1519566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dm, coordDM)); 1529566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 1536858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM)); 1546858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords)); 1556858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dm, coordDM)); 1566858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 1579318fe57SMatthew G. Knepley /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */ 1586858538eSMatthew G. Knepley PetscCall(DMFieldDestroy(&dm->coordinates[0].field)); 1596858538eSMatthew G. Knepley dm->coordinates[0].field = dmNew->coordinates[0].field; 16061a622f3SMatthew G. Knepley ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc; 1614fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L)); 1624fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 163e535cce4SJames Wright PetscCall(DMGetNaturalSF(dmNew, &sf)); 164e535cce4SJames Wright PetscCall(DMSetNaturalSF(dm, sf)); 165e535cce4SJames Wright PetscCall(DMGetUseNatural(dmNew, &use_natural)); 166e535cce4SJames Wright PetscCall(DMSetUseNatural(dm, use_natural)); 1679566063dSJacob Faibussowitsch PetscCall(DMDestroy_Plex(dm)); 1689566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 1699318fe57SMatthew G. Knepley dm->data = dmNew->data; 1709318fe57SMatthew G. Knepley ((DM_Plex *)dmNew->data)->refct++; 1711fca310dSJames Wright { 1721fca310dSJames Wright PetscInt num_face_sfs; 1731fca310dSJames Wright const PetscSF *sfs; 1741fca310dSJames Wright PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &sfs)); 1751fca310dSJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(dm, num_face_sfs, (PetscSF *)sfs)); // for the compose function effect on dm 1761fca310dSJames Wright } 1779566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 1789566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 1799566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmNew, &coarseDM)); 1809566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 1815552b385SBrandon PetscCall(DMPlexCopyEGADSInfo_Internal(dmNew, dm)); 1829566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 1833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1849318fe57SMatthew G. Knepley } 1859318fe57SMatthew G. Knepley 1869318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew 1879318fe57SMatthew G. Knepley - Swap the DM_Plex structure 1889318fe57SMatthew G. Knepley - Swap the coordinates 1899318fe57SMatthew G. Knepley - Swap the point PetscSF 1909318fe57SMatthew G. Knepley */ 191d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) 192d71ae5a4SJacob Faibussowitsch { 1939318fe57SMatthew G. Knepley DM coordDMA, coordDMB; 1949318fe57SMatthew G. Knepley Vec coordsA, coordsB; 1959318fe57SMatthew G. Knepley PetscSF sfA, sfB; 1969318fe57SMatthew G. Knepley DMField fieldTmp; 1979318fe57SMatthew G. Knepley void *tmp; 1989318fe57SMatthew G. Knepley DMLabelLink listTmp; 1999318fe57SMatthew G. Knepley DMLabel depthTmp; 2009318fe57SMatthew G. Knepley PetscInt tmpI; 2019318fe57SMatthew G. Knepley 2029318fe57SMatthew G. Knepley PetscFunctionBegin; 2033ba16761SJacob Faibussowitsch if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS); 2049566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmA, &sfA)); 2059566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmB, &sfB)); 2069566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sfA)); 2079566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmA, sfB)); 2089566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmB, sfA)); 2099566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)sfA)); 2109318fe57SMatthew G. Knepley 2119566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &coordDMA)); 2129566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &coordDMB)); 2139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordDMA)); 2149566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmA, coordDMB)); 2159566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmB, coordDMA)); 2169566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 2179318fe57SMatthew G. Knepley 2189566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordsA)); 2199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmB, &coordsB)); 2209566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordsA)); 2219566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmA, coordsB)); 2229566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordsA)); 2239566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordsA)); 2249318fe57SMatthew G. Knepley 2256858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA)); 2266858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB)); 2276858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordDMA)); 2286858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmA, coordDMB)); 2296858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmB, coordDMA)); 2306858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 2316858538eSMatthew G. Knepley 2326858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA)); 2336858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB)); 2346858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordsA)); 2356858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB)); 2366858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA)); 2376858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordsA)); 2386858538eSMatthew G. Knepley 2395552b385SBrandon PetscCall(DMPlexSwapEGADSInfo_Private(dmA, dmB)); 2405552b385SBrandon 2416858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[0].field; 2426858538eSMatthew G. Knepley dmA->coordinates[0].field = dmB->coordinates[0].field; 2436858538eSMatthew G. Knepley dmB->coordinates[0].field = fieldTmp; 2446858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[1].field; 2456858538eSMatthew G. Knepley dmA->coordinates[1].field = dmB->coordinates[1].field; 2466858538eSMatthew G. Knepley dmB->coordinates[1].field = fieldTmp; 2479318fe57SMatthew G. Knepley tmp = dmA->data; 2489318fe57SMatthew G. Knepley dmA->data = dmB->data; 2499318fe57SMatthew G. Knepley dmB->data = tmp; 2509318fe57SMatthew G. Knepley listTmp = dmA->labels; 2519318fe57SMatthew G. Knepley dmA->labels = dmB->labels; 2529318fe57SMatthew G. Knepley dmB->labels = listTmp; 2539318fe57SMatthew G. Knepley depthTmp = dmA->depthLabel; 2549318fe57SMatthew G. Knepley dmA->depthLabel = dmB->depthLabel; 2559318fe57SMatthew G. Knepley dmB->depthLabel = depthTmp; 2569318fe57SMatthew G. Knepley depthTmp = dmA->celltypeLabel; 2579318fe57SMatthew G. Knepley dmA->celltypeLabel = dmB->celltypeLabel; 2589318fe57SMatthew G. Knepley dmB->celltypeLabel = depthTmp; 2599318fe57SMatthew G. Knepley tmpI = dmA->levelup; 2609318fe57SMatthew G. Knepley dmA->levelup = dmB->levelup; 2619318fe57SMatthew G. Knepley dmB->levelup = tmpI; 2623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2639318fe57SMatthew G. Knepley } 2649318fe57SMatthew G. Knepley 2653431e603SJed Brown PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm) 266d71ae5a4SJacob Faibussowitsch { 2679318fe57SMatthew G. Knepley DM idm; 2689318fe57SMatthew G. Knepley 2699318fe57SMatthew G. Knepley PetscFunctionBegin; 2709566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 2719566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 27269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 2733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2749318fe57SMatthew G. Knepley } 2759318fe57SMatthew G. Knepley 2769318fe57SMatthew G. Knepley /*@C 2779318fe57SMatthew G. Knepley DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates 2789318fe57SMatthew G. Knepley 27920f4b53cSBarry Smith Collective 2809318fe57SMatthew G. Knepley 2819318fe57SMatthew G. Knepley Input Parameters: 28260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 28320f4b53cSBarry Smith . degree - The degree of the finite element or `PETSC_DECIDE` 284e44f6aebSMatthew G. Knepley . project - Flag to project current coordinates into the space 2859318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface 2869318fe57SMatthew G. Knepley 2879318fe57SMatthew G. Knepley Level: advanced 2889318fe57SMatthew G. Knepley 2891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPointFunc`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()` 2909318fe57SMatthew G. Knepley @*/ 291e44f6aebSMatthew G. Knepley PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscBool project, PetscPointFunc coordFunc) 292d71ae5a4SJacob Faibussowitsch { 2939318fe57SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 294e44f6aebSMatthew G. Knepley PetscFE fe = NULL; 2959318fe57SMatthew G. Knepley DM cdm; 296ac9d17c7SMatthew G. Knepley PetscInt dim, cdim, dE, qorder, height; 2979318fe57SMatthew G. Knepley 298e44f6aebSMatthew G. Knepley PetscFunctionBegin; 2999566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 300ac9d17c7SMatthew G. Knepley cdim = dim; 3019566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 3029318fe57SMatthew G. Knepley qorder = degree; 303e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 304d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)cdm); 305dc431b0cSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0)); 306ac9d17c7SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_coordinate_dim", "Set the coordinate dimension", "DMPlexCreateCoordinateSpace", cdim, &cdim, NULL, dim)); 307d0609cedSBarry Smith PetscOptionsEnd(); 3081df12153SMatthew G. Knepley PetscCall(DMPlexGetVTKCellHeight(dm, &height)); 309ac9d17c7SMatthew G. Knepley if (cdim > dim) { 310ac9d17c7SMatthew G. Knepley DM cdm; 311ac9d17c7SMatthew G. Knepley PetscSection cs, csNew; 312ac9d17c7SMatthew G. Knepley Vec coordinates, coordinatesNew; 313ac9d17c7SMatthew G. Knepley VecType vectype; 314ac9d17c7SMatthew G. Knepley IS idx; 315ac9d17c7SMatthew G. Knepley PetscInt *indices; 316ac9d17c7SMatthew G. Knepley PetscInt bs, n; 317ac9d17c7SMatthew G. Knepley 318ac9d17c7SMatthew G. Knepley // Recreate coordinate section 319ac9d17c7SMatthew G. Knepley { 320ac9d17c7SMatthew G. Knepley const char *fieldName = NULL, *compName = NULL; 321ac9d17c7SMatthew G. Knepley PetscInt Nc, pStart, pEnd; 322ac9d17c7SMatthew G. Knepley 323ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 324ac9d17c7SMatthew G. Knepley PetscCall(DMGetLocalSection(cdm, &cs)); 325ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cs), &csNew)); 326ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetNumFields(csNew, 1)); 327ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetFieldName(cs, 0, &fieldName)); 328ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldName(csNew, 0, fieldName)); 329ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetFieldComponents(cs, 0, &Nc)); 330ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(csNew, 0, cdim)); 331ac9d17c7SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 332ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetComponentName(cs, 0, c, &compName)); 333ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetComponentName(csNew, 0, c, compName)); 334ac9d17c7SMatthew G. Knepley } 335ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetChart(cs, &pStart, &pEnd)); 336ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetChart(csNew, pStart, pEnd)); 337ac9d17c7SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 338530e699aSMatthew G. Knepley PetscInt dof; 339530e699aSMatthew G. Knepley 340530e699aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cs, p, &dof)); 341530e699aSMatthew G. Knepley if (dof) { 342ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetDof(csNew, p, cdim)); 343ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csNew, p, 0, cdim)); 344ac9d17c7SMatthew G. Knepley } 345530e699aSMatthew G. Knepley } 346ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetUp(csNew)); 347ac9d17c7SMatthew G. Knepley } 348ac9d17c7SMatthew G. Knepley PetscCall(DMSetLocalSection(cdm, csNew)); 349ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionDestroy(&csNew)); 350530e699aSMatthew G. Knepley // Reset coordinate dimension for coordinate DM 351530e699aSMatthew G. Knepley PetscCall(DMSetCoordinateDim(cdm, cdim)); 352530e699aSMatthew G. Knepley PetscCall(DMSetCoordinateField(cdm, NULL)); 353ac9d17c7SMatthew G. Knepley // Inject coordinates into higher dimension 354ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 355ac9d17c7SMatthew G. Knepley PetscCall(VecGetBlockSize(coordinates, &bs)); 356ac9d17c7SMatthew G. Knepley PetscCheck(bs == dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension"); 357ac9d17c7SMatthew G. Knepley PetscCall(VecCreate(PetscObjectComm((PetscObject)coordinates), &coordinatesNew)); 358ac9d17c7SMatthew G. Knepley PetscCall(VecGetType(coordinates, &vectype)); 359ac9d17c7SMatthew G. Knepley PetscCall(VecSetType(coordinatesNew, vectype)); 360ac9d17c7SMatthew G. Knepley PetscCall(VecGetLocalSize(coordinates, &n)); 361ac9d17c7SMatthew G. Knepley PetscCheck(!(n % bs), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension"); 362ac9d17c7SMatthew G. Knepley n /= bs; 363ac9d17c7SMatthew G. Knepley PetscCall(VecSetSizes(coordinatesNew, n * cdim, PETSC_DETERMINE)); 364ac9d17c7SMatthew G. Knepley PetscCall(VecSetUp(coordinatesNew)); 365ac9d17c7SMatthew G. Knepley PetscCall(PetscMalloc1(n * bs, &indices)); 366ac9d17c7SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) 367ac9d17c7SMatthew G. Knepley for (PetscInt b = 0; b < bs; ++b) indices[i * bs + b] = i * cdim + b; 368ac9d17c7SMatthew G. Knepley PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n * bs, indices, PETSC_OWN_POINTER, &idx)); 369ac9d17c7SMatthew G. Knepley PetscCall(VecISCopy(coordinatesNew, idx, SCATTER_FORWARD, coordinates)); 370ac9d17c7SMatthew G. Knepley PetscCall(ISDestroy(&idx)); 371ac9d17c7SMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinatesNew)); 372ac9d17c7SMatthew G. Knepley PetscCall(VecDestroy(&coordinatesNew)); 373ac9d17c7SMatthew G. Knepley PetscCall(DMSetCoordinateDim(dm, cdim)); 374ac9d17c7SMatthew G. Knepley { 375ac9d17c7SMatthew G. Knepley PetscInt gn; 376ac9d17c7SMatthew G. Knepley 377ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinates(dm, &coordinatesNew)); 378ac9d17c7SMatthew G. Knepley PetscCall(VecGetLocalSize(coordinatesNew, &gn)); 379ac9d17c7SMatthew G. Knepley PetscCheck(gn == n * cdim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Global coordinate size %" PetscInt_FMT " != %" PetscInt_FMT "local coordinate size", gn, n * cdim); 380ac9d17c7SMatthew G. Knepley } 381ac9d17c7SMatthew G. Knepley dE = cdim; 382530e699aSMatthew G. Knepley project = PETSC_FALSE; 383ac9d17c7SMatthew G. Knepley } 384e44f6aebSMatthew G. Knepley if (degree >= 0) { 385e44f6aebSMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 386e44f6aebSMatthew G. Knepley PetscInt cStart, cEnd, gct; 387dc431b0cSMatthew G. Knepley 3881df12153SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd)); 389dc431b0cSMatthew G. Knepley if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 390e44f6aebSMatthew G. Knepley gct = (PetscInt)ct; 391462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &gct, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm))); 392e44f6aebSMatthew G. Knepley ct = (DMPolytopeType)gct; 393e44f6aebSMatthew G. Knepley // Work around current bug in PetscDualSpaceSetUp_Lagrange() 394e44f6aebSMatthew G. Knepley // Can be seen in plex_tutorials-ex10_1 395e44f6aebSMatthew 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)); 3964f9ab2b4SJed Brown } 397e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinateDisc(dm, fe, project)); 3989566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 3999318fe57SMatthew G. Knepley mesh->coordFunc = coordFunc; 4003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4019318fe57SMatthew G. Knepley } 4029318fe57SMatthew G. Knepley 4031df5d5c5SMatthew G. Knepley /*@ 4041df5d5c5SMatthew G. Knepley DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 4051df5d5c5SMatthew G. Knepley 406d083f849SBarry Smith Collective 4071df5d5c5SMatthew G. Knepley 4081df5d5c5SMatthew G. Knepley Input Parameters: 409a1cb98faSBarry Smith + comm - The communicator for the `DM` object 4101df5d5c5SMatthew G. Knepley . dim - The spatial dimension 4111df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells 4121df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces) 4131df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 4141df5d5c5SMatthew G. Knepley 4151df5d5c5SMatthew G. Knepley Output Parameter: 41660225df5SJacob Faibussowitsch . newdm - The `DM` object 4171df5d5c5SMatthew G. Knepley 4181df5d5c5SMatthew G. Knepley Level: beginner 4191df5d5c5SMatthew G. Knepley 4201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()` 4211df5d5c5SMatthew G. Knepley @*/ 422d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) 423d71ae5a4SJacob Faibussowitsch { 4241df5d5c5SMatthew G. Knepley DM dm; 4251df5d5c5SMatthew G. Knepley PetscMPIInt rank; 4261df5d5c5SMatthew G. Knepley 4271df5d5c5SMatthew G. Knepley PetscFunctionBegin; 4289566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &dm)); 4299566063dSJacob Faibussowitsch PetscCall(DMSetType(dm, DMPLEX)); 4309566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 43146139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 4329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 433ce78fa2fSMatthew G. Knepley switch (dim) { 434ce78fa2fSMatthew G. Knepley case 2: 4359566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular")); 4369566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral")); 437ce78fa2fSMatthew G. Knepley break; 438ce78fa2fSMatthew G. Knepley case 3: 4399566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral")); 4409566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral")); 441ce78fa2fSMatthew G. Knepley break; 442d71ae5a4SJacob Faibussowitsch default: 443d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 444ce78fa2fSMatthew G. Knepley } 4451df5d5c5SMatthew G. Knepley if (rank) { 4461df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {0, 0}; 4479566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL)); 4481df5d5c5SMatthew G. Knepley } else { 4491df5d5c5SMatthew G. Knepley switch (dim) { 4501df5d5c5SMatthew G. Knepley case 2: 4511df5d5c5SMatthew G. Knepley if (simplex) { 4521df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {4, 2}; 4531df5d5c5SMatthew G. Knepley PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 4541df5d5c5SMatthew G. Knepley PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 4551df5d5c5SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 4561df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 4571df5d5c5SMatthew G. Knepley 4589566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4591df5d5c5SMatthew G. Knepley } else { 4601df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {6, 2}; 4611df5d5c5SMatthew G. Knepley PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 4621df5d5c5SMatthew G. Knepley PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 4631df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 4641df5d5c5SMatthew 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}; 4651df5d5c5SMatthew G. Knepley 4669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4671df5d5c5SMatthew G. Knepley } 4681df5d5c5SMatthew G. Knepley break; 4691df5d5c5SMatthew G. Knepley case 3: 4701df5d5c5SMatthew G. Knepley if (simplex) { 4711df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {5, 2}; 4721df5d5c5SMatthew G. Knepley PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 4731df5d5c5SMatthew G. Knepley PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 4741df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 4751df5d5c5SMatthew 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}; 4761df5d5c5SMatthew G. Knepley 4779566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4781df5d5c5SMatthew G. Knepley } else { 4791df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {12, 2}; 4801df5d5c5SMatthew G. Knepley PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 4811df5d5c5SMatthew G. Knepley PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 4821df5d5c5SMatthew G. Knepley PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 4839371c9d4SSatish 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}; 4841df5d5c5SMatthew G. Knepley 4859566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4861df5d5c5SMatthew G. Knepley } 4871df5d5c5SMatthew G. Knepley break; 488d71ae5a4SJacob Faibussowitsch default: 489d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 4901df5d5c5SMatthew G. Knepley } 4911df5d5c5SMatthew G. Knepley } 49246139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 4931df5d5c5SMatthew G. Knepley *newdm = dm; 4941df5d5c5SMatthew G. Knepley if (refinementLimit > 0.0) { 4951df5d5c5SMatthew G. Knepley DM rdm; 4961df5d5c5SMatthew G. Knepley const char *name; 4971df5d5c5SMatthew G. Knepley 4989566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 4999566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 5009566063dSJacob Faibussowitsch PetscCall(DMRefine(*newdm, comm, &rdm)); 5019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)*newdm, &name)); 5029566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, name)); 5039566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 5041df5d5c5SMatthew G. Knepley *newdm = rdm; 5051df5d5c5SMatthew G. Knepley } 5061df5d5c5SMatthew G. Knepley if (interpolate) { 5075fd9971aSMatthew G. Knepley DM idm; 5081df5d5c5SMatthew G. Knepley 5099566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*newdm, &idm)); 5109566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 5111df5d5c5SMatthew G. Knepley *newdm = idm; 5121df5d5c5SMatthew G. Knepley } 5133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5141df5d5c5SMatthew G. Knepley } 5151df5d5c5SMatthew G. Knepley 516d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 517d71ae5a4SJacob Faibussowitsch { 5189318fe57SMatthew G. Knepley const PetscInt numVertices = 2; 5199318fe57SMatthew G. Knepley PetscInt markerRight = 1; 5209318fe57SMatthew G. Knepley PetscInt markerLeft = 1; 5219318fe57SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 5229318fe57SMatthew G. Knepley Vec coordinates; 5239318fe57SMatthew G. Knepley PetscSection coordSection; 5249318fe57SMatthew G. Knepley PetscScalar *coords; 5259318fe57SMatthew G. Knepley PetscInt coordSize; 5269318fe57SMatthew G. Knepley PetscMPIInt rank; 5279318fe57SMatthew G. Knepley PetscInt cdim = 1, v; 528552f7358SJed Brown 5299318fe57SMatthew G. Knepley PetscFunctionBegin; 5309566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 5319318fe57SMatthew G. Knepley if (markerSeparate) { 5329318fe57SMatthew G. Knepley markerRight = 2; 5339318fe57SMatthew G. Knepley markerLeft = 1; 5349318fe57SMatthew G. Knepley } 5359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 536c5853193SPierre Jolivet if (rank == 0) { 5379566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numVertices)); 5389566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 5399566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft)); 5409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight)); 5419318fe57SMatthew G. Knepley } 5429566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 5439566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 5449318fe57SMatthew G. Knepley /* Build coordinates */ 5459566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 5469566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 5479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 5489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, 0, numVertices)); 5499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 5509318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 5519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 5529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 5539318fe57SMatthew G. Knepley } 5549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 5559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 5569566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 5579566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 5589566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 5599566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 5609566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 5619566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5629318fe57SMatthew G. Knepley coords[0] = lower[0]; 5639318fe57SMatthew G. Knepley coords[1] = upper[0]; 5649566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 5659566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 5669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 5673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5689318fe57SMatthew G. Knepley } 56926492d91SMatthew G. Knepley 570d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 571d71ae5a4SJacob Faibussowitsch { 5721df21d24SMatthew G. Knepley const PetscInt numVertices = (edges[0] + 1) * (edges[1] + 1); 5731df21d24SMatthew G. Knepley const PetscInt numEdges = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1]; 574552f7358SJed Brown PetscInt markerTop = 1; 575552f7358SJed Brown PetscInt markerBottom = 1; 576552f7358SJed Brown PetscInt markerRight = 1; 577552f7358SJed Brown PetscInt markerLeft = 1; 578552f7358SJed Brown PetscBool markerSeparate = PETSC_FALSE; 579552f7358SJed Brown Vec coordinates; 580552f7358SJed Brown PetscSection coordSection; 581552f7358SJed Brown PetscScalar *coords; 582552f7358SJed Brown PetscInt coordSize; 583552f7358SJed Brown PetscMPIInt rank; 584552f7358SJed Brown PetscInt v, vx, vy; 585552f7358SJed Brown 586552f7358SJed Brown PetscFunctionBegin; 5879566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 588552f7358SJed Brown if (markerSeparate) { 5891df21d24SMatthew G. Knepley markerTop = 3; 5901df21d24SMatthew G. Knepley markerBottom = 1; 5911df21d24SMatthew G. Knepley markerRight = 2; 5921df21d24SMatthew G. Knepley markerLeft = 4; 593552f7358SJed Brown } 5949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 595dd400576SPatrick Sanan if (rank == 0) { 596552f7358SJed Brown PetscInt e, ex, ey; 597552f7358SJed Brown 5989566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices)); 59948a46eb9SPierre Jolivet for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 6009566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 601552f7358SJed Brown for (vx = 0; vx <= edges[0]; vx++) { 602552f7358SJed Brown for (ey = 0; ey < edges[1]; ey++) { 603552f7358SJed Brown PetscInt edge = vx * edges[1] + ey + edges[0] * (edges[1] + 1); 604552f7358SJed Brown PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges; 605da80777bSKarl Rupp PetscInt cone[2]; 606552f7358SJed Brown 6079371c9d4SSatish Balay cone[0] = vertex; 6089371c9d4SSatish Balay cone[1] = vertex + edges[0] + 1; 6099566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 610552f7358SJed Brown if (vx == edges[0]) { 6119566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 6129566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 613552f7358SJed Brown if (ey == edges[1] - 1) { 6149566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 6159566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 616552f7358SJed Brown } 617552f7358SJed Brown } else if (vx == 0) { 6189566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 6199566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 620552f7358SJed Brown if (ey == edges[1] - 1) { 6219566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 6229566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft)); 623552f7358SJed Brown } 624552f7358SJed Brown } 625552f7358SJed Brown } 626552f7358SJed Brown } 627552f7358SJed Brown for (vy = 0; vy <= edges[1]; vy++) { 628552f7358SJed Brown for (ex = 0; ex < edges[0]; ex++) { 629552f7358SJed Brown PetscInt edge = vy * edges[0] + ex; 630552f7358SJed Brown PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges; 631da80777bSKarl Rupp PetscInt cone[2]; 632552f7358SJed Brown 6339371c9d4SSatish Balay cone[0] = vertex; 6349371c9d4SSatish Balay cone[1] = vertex + 1; 6359566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 636552f7358SJed Brown if (vy == edges[1]) { 6379566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 6389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 639552f7358SJed Brown if (ex == edges[0] - 1) { 6409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 6419566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 642552f7358SJed Brown } 643552f7358SJed Brown } else if (vy == 0) { 6449566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 6459566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 646552f7358SJed Brown if (ex == edges[0] - 1) { 6479566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 6489566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 649552f7358SJed Brown } 650552f7358SJed Brown } 651552f7358SJed Brown } 652552f7358SJed Brown } 653552f7358SJed Brown } 6549566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 6559566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 656552f7358SJed Brown /* Build coordinates */ 6579566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 2)); 6589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 6599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 6609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 6619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 662552f7358SJed Brown for (v = numEdges; v < numEdges + numVertices; ++v) { 6639566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 2)); 6649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 665552f7358SJed Brown } 6669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 6689566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 6699566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 6709566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 6719566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 2)); 6729566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 6739566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 674552f7358SJed Brown for (vy = 0; vy <= edges[1]; ++vy) { 675552f7358SJed Brown for (vx = 0; vx <= edges[0]; ++vx) { 676552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx; 677552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy; 678552f7358SJed Brown } 679552f7358SJed Brown } 6809566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 6819566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 6829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 6833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 684552f7358SJed Brown } 685552f7358SJed Brown 686d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 687d71ae5a4SJacob Faibussowitsch { 6889e8abbc3SMichael Lange PetscInt vertices[3], numVertices; 6897b59f5a9SMichael Lange PetscInt numFaces = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2]; 690c2df9bbfSMatthew G. Knepley PetscInt markerTop = 1; 691c2df9bbfSMatthew G. Knepley PetscInt markerBottom = 1; 692c2df9bbfSMatthew G. Knepley PetscInt markerFront = 1; 693c2df9bbfSMatthew G. Knepley PetscInt markerBack = 1; 694c2df9bbfSMatthew G. Knepley PetscInt markerRight = 1; 695c2df9bbfSMatthew G. Knepley PetscInt markerLeft = 1; 696c2df9bbfSMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 697552f7358SJed Brown Vec coordinates; 698552f7358SJed Brown PetscSection coordSection; 699552f7358SJed Brown PetscScalar *coords; 700552f7358SJed Brown PetscInt coordSize; 701552f7358SJed Brown PetscMPIInt rank; 702552f7358SJed Brown PetscInt v, vx, vy, vz; 7037b59f5a9SMichael Lange PetscInt voffset, iface = 0, cone[4]; 704552f7358SJed Brown 705552f7358SJed Brown PetscFunctionBegin; 7061dca8a05SBarry 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"); 7079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 708c2df9bbfSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 709c2df9bbfSMatthew G. Knepley if (markerSeparate) { 710c2df9bbfSMatthew G. Knepley markerBottom = 1; 711c2df9bbfSMatthew G. Knepley markerTop = 2; 712c2df9bbfSMatthew G. Knepley markerFront = 3; 713c2df9bbfSMatthew G. Knepley markerBack = 4; 714c2df9bbfSMatthew G. Knepley markerRight = 5; 715c2df9bbfSMatthew G. Knepley markerLeft = 6; 716c2df9bbfSMatthew G. Knepley } 7179371c9d4SSatish Balay vertices[0] = faces[0] + 1; 7189371c9d4SSatish Balay vertices[1] = faces[1] + 1; 7199371c9d4SSatish Balay vertices[2] = faces[2] + 1; 7209e8abbc3SMichael Lange numVertices = vertices[0] * vertices[1] * vertices[2]; 721dd400576SPatrick Sanan if (rank == 0) { 722552f7358SJed Brown PetscInt f; 723552f7358SJed Brown 7249566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices)); 72548a46eb9SPierre Jolivet for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 7269566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 7277b59f5a9SMichael Lange 7287b59f5a9SMichael Lange /* Side 0 (Top) */ 7297b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7307b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7317b59f5a9SMichael Lange voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx; 7329371c9d4SSatish Balay cone[0] = voffset; 7339371c9d4SSatish Balay cone[1] = voffset + 1; 7349371c9d4SSatish Balay cone[2] = voffset + vertices[0] + 1; 7359371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 7369566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 737c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop)); 738c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop)); 739c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop)); 740c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop)); 741c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop)); 7427b59f5a9SMichael Lange iface++; 743552f7358SJed Brown } 744552f7358SJed Brown } 7457b59f5a9SMichael Lange 7467b59f5a9SMichael Lange /* Side 1 (Bottom) */ 7477b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7487b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7497b59f5a9SMichael Lange voffset = numFaces + vy * (faces[0] + 1) + vx; 7509371c9d4SSatish Balay cone[0] = voffset + 1; 7519371c9d4SSatish Balay cone[1] = voffset; 7529371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 7539371c9d4SSatish Balay cone[3] = voffset + vertices[0] + 1; 7549566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 755c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom)); 756c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom)); 757c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom)); 758c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom)); 759c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom)); 7607b59f5a9SMichael Lange iface++; 761552f7358SJed Brown } 762552f7358SJed Brown } 7637b59f5a9SMichael Lange 7647b59f5a9SMichael Lange /* Side 2 (Front) */ 7657b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 7667b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7677b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vx; 7689371c9d4SSatish Balay cone[0] = voffset; 7699371c9d4SSatish Balay cone[1] = voffset + 1; 7709371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + 1; 7719371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1]; 7729566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 773c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront)); 774c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront)); 775c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront)); 776c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront)); 777c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront)); 7787b59f5a9SMichael Lange iface++; 779552f7358SJed Brown } 7807b59f5a9SMichael Lange } 7817b59f5a9SMichael Lange 7827b59f5a9SMichael Lange /* Side 3 (Back) */ 7837b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 7847b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7857b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx; 7869371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 7879371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1] + 1; 7889371c9d4SSatish Balay cone[2] = voffset + 1; 7899371c9d4SSatish Balay cone[3] = voffset; 7909566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 791c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack)); 792c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack)); 793c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack)); 794c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack)); 795c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack)); 7967b59f5a9SMichael Lange iface++; 7977b59f5a9SMichael Lange } 7987b59f5a9SMichael Lange } 7997b59f5a9SMichael Lange 8007b59f5a9SMichael Lange /* Side 4 (Left) */ 8017b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8027b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 8037b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0]; 8049371c9d4SSatish Balay cone[0] = voffset; 8059371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1]; 8069371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + vertices[0]; 8079371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 8089566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 809c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft)); 810c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft)); 811c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft)); 812c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft)); 813c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft)); 8147b59f5a9SMichael Lange iface++; 8157b59f5a9SMichael Lange } 8167b59f5a9SMichael Lange } 8177b59f5a9SMichael Lange 8187b59f5a9SMichael Lange /* Side 5 (Right) */ 8197b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8207b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 821aab5bcd8SJed Brown voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0]; 8229371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 8239371c9d4SSatish Balay cone[1] = voffset; 8249371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 8259371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1] + vertices[0]; 8269566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 827c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight)); 828c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight)); 829c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight)); 830c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight)); 831c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight)); 8327b59f5a9SMichael Lange iface++; 8337b59f5a9SMichael Lange } 834552f7358SJed Brown } 835552f7358SJed Brown } 8369566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 8379566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 838552f7358SJed Brown /* Build coordinates */ 8399566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 3)); 8409566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 8429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 8439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 844552f7358SJed Brown for (v = numFaces; v < numFaces + numVertices; ++v) { 8459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 3)); 8469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 847552f7358SJed Brown } 8489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 8499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 8509566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 8519566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 8529566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 8539566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 3)); 8549566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 8559566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 856552f7358SJed Brown for (vz = 0; vz <= faces[2]; ++vz) { 857552f7358SJed Brown for (vy = 0; vy <= faces[1]; ++vy) { 858552f7358SJed Brown for (vx = 0; vx <= faces[0]; ++vx) { 859552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx; 860552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy; 861552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz; 862552f7358SJed Brown } 863552f7358SJed Brown } 864552f7358SJed Brown } 8659566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 8669566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 8679566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 8683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 869552f7358SJed Brown } 870552f7358SJed Brown 871d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) 872d71ae5a4SJacob Faibussowitsch { 8739318fe57SMatthew G. Knepley PetscFunctionBegin; 8749318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 87546139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 8769566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim - 1)); 8779566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim)); 8789318fe57SMatthew G. Knepley switch (dim) { 879d71ae5a4SJacob Faibussowitsch case 1: 880d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces)); 881d71ae5a4SJacob Faibussowitsch break; 882d71ae5a4SJacob Faibussowitsch case 2: 883d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces)); 884d71ae5a4SJacob Faibussowitsch break; 885d71ae5a4SJacob Faibussowitsch case 3: 886d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces)); 887d71ae5a4SJacob Faibussowitsch break; 888d71ae5a4SJacob Faibussowitsch default: 889d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim); 8909318fe57SMatthew G. Knepley } 89146139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 8929566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 8933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8949318fe57SMatthew G. Knepley } 8959318fe57SMatthew G. Knepley 8969318fe57SMatthew G. Knepley /*@C 8979318fe57SMatthew G. Knepley DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra). 8989318fe57SMatthew G. Knepley 8999318fe57SMatthew G. Knepley Collective 9009318fe57SMatthew G. Knepley 9019318fe57SMatthew G. Knepley Input Parameters: 902a1cb98faSBarry Smith + comm - The communicator for the `DM` object 90320f4b53cSBarry Smith . dim - The spatial dimension of the box, so the resulting mesh is has dimension `dim`-1 90420f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 90520f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 90620f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 9079318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 9089318fe57SMatthew G. Knepley 9099318fe57SMatthew G. Knepley Output Parameter: 910a1cb98faSBarry Smith . dm - The `DM` object 9119318fe57SMatthew G. Knepley 9129318fe57SMatthew G. Knepley Level: beginner 9139318fe57SMatthew G. Knepley 9141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()` 9159318fe57SMatthew G. Knepley @*/ 916d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) 917d71ae5a4SJacob Faibussowitsch { 9189318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 9199318fe57SMatthew G. Knepley PetscReal low[3] = {0, 0, 0}; 9209318fe57SMatthew G. Knepley PetscReal upp[3] = {1, 1, 1}; 9219318fe57SMatthew G. Knepley 9229318fe57SMatthew G. Knepley PetscFunctionBegin; 9239566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 9249566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 9259566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate)); 9263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9279318fe57SMatthew G. Knepley } 9289318fe57SMatthew G. Knepley 929d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd) 930d71ae5a4SJacob Faibussowitsch { 931fdbf62faSLisandro Dalcin PetscInt i, fStart, fEnd, numCells = 0, numVerts = 0; 932fdbf62faSLisandro Dalcin PetscInt numPoints[2], *coneSize, *cones, *coneOrientations; 933fdbf62faSLisandro Dalcin PetscScalar *vertexCoords; 934fdbf62faSLisandro Dalcin PetscReal L, maxCell; 935fdbf62faSLisandro Dalcin PetscBool markerSeparate = PETSC_FALSE; 936fdbf62faSLisandro Dalcin PetscInt markerLeft = 1, faceMarkerLeft = 1; 937fdbf62faSLisandro Dalcin PetscInt markerRight = 1, faceMarkerRight = 2; 938fdbf62faSLisandro Dalcin PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 939fdbf62faSLisandro Dalcin PetscMPIInt rank; 940fdbf62faSLisandro Dalcin 941fdbf62faSLisandro Dalcin PetscFunctionBegin; 9424f572ea9SToby Isaac PetscAssertPointer(dm, 1); 943fdbf62faSLisandro Dalcin 9449566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, 1)); 9459566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 9469566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 947fdbf62faSLisandro Dalcin 9489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 949dd400576SPatrick Sanan if (rank == 0) numCells = segments; 950dd400576SPatrick Sanan if (rank == 0) numVerts = segments + (wrap ? 0 : 1); 951fdbf62faSLisandro Dalcin 9529371c9d4SSatish Balay numPoints[0] = numVerts; 9539371c9d4SSatish Balay numPoints[1] = numCells; 9549566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords)); 9559566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts)); 956ad540459SPierre Jolivet for (i = 0; i < numCells; ++i) coneSize[i] = 2; 957ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0; 9589371c9d4SSatish Balay for (i = 0; i < numCells; ++i) { 9599371c9d4SSatish Balay cones[2 * i] = numCells + i % numVerts; 9609371c9d4SSatish Balay cones[2 * i + 1] = numCells + (i + 1) % numVerts; 9619371c9d4SSatish Balay } 962ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells); 9639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 9649566063dSJacob Faibussowitsch PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords)); 965fdbf62faSLisandro Dalcin 9669566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 9679371c9d4SSatish Balay if (markerSeparate) { 9689371c9d4SSatish Balay markerLeft = faceMarkerLeft; 9699371c9d4SSatish Balay markerRight = faceMarkerRight; 9709371c9d4SSatish Balay } 971dd400576SPatrick Sanan if (!wrap && rank == 0) { 9729566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 9739566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft)); 9749566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight)); 9759566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft)); 9769566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight)); 977fdbf62faSLisandro Dalcin } 978fdbf62faSLisandro Dalcin if (wrap) { 979fdbf62faSLisandro Dalcin L = upper - lower; 980fdbf62faSLisandro Dalcin maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments)); 9814fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L)); 982fdbf62faSLisandro Dalcin } 9839566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 9843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 985fdbf62faSLisandro Dalcin } 986fdbf62faSLisandro Dalcin 9874054ae39SJames Wright // Creates "Face Sets" label based on the standard box labeling conventions 988d7d2d1d2SJames Wright static PetscErrorCode DMPlexSetBoxLabel_Internal(DM dm, const DMBoundaryType periodicity[]) 9894054ae39SJames Wright { 9906ff49feeSJames Wright DM cdm; 9916ff49feeSJames Wright PetscSection csection; 9926ff49feeSJames Wright Vec coordinates; 9934054ae39SJames Wright DMLabel label; 9946ff49feeSJames Wright IS faces_is; 9952b4f33d9SJames Wright PetscInt dim, num_face = 0; 9964054ae39SJames Wright const PetscInt *faces; 9974054ae39SJames Wright PetscInt faceMarkerBottom, faceMarkerTop, faceMarkerFront, faceMarkerBack, faceMarkerRight, faceMarkerLeft; 9984054ae39SJames Wright 9994054ae39SJames Wright PetscFunctionBeginUser; 10004054ae39SJames Wright PetscCall(DMGetDimension(dm, &dim)); 1001d7c1f440SPierre 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); 10024054ae39SJames Wright // Get Face Sets label 10034054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 10044054ae39SJames Wright if (label) { 10054054ae39SJames Wright PetscCall(DMLabelReset(label)); 10064054ae39SJames Wright } else { 10074054ae39SJames Wright PetscCall(DMCreateLabel(dm, "Face Sets")); 10084054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 10094054ae39SJames Wright } 10104054ae39SJames Wright PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label)); 10116ff49feeSJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", 1, &faces_is)); 10124054ae39SJames Wright 10134054ae39SJames Wright switch (dim) { 10144054ae39SJames Wright case 2: 10154054ae39SJames Wright faceMarkerTop = 3; 10164054ae39SJames Wright faceMarkerBottom = 1; 10174054ae39SJames Wright faceMarkerRight = 2; 10184054ae39SJames Wright faceMarkerLeft = 4; 10194054ae39SJames Wright break; 10204054ae39SJames Wright case 3: 10214054ae39SJames Wright faceMarkerBottom = 1; 10224054ae39SJames Wright faceMarkerTop = 2; 10234054ae39SJames Wright faceMarkerFront = 3; 10244054ae39SJames Wright faceMarkerBack = 4; 10254054ae39SJames Wright faceMarkerRight = 5; 10264054ae39SJames Wright faceMarkerLeft = 6; 10274054ae39SJames Wright break; 10284054ae39SJames Wright default: 10294054ae39SJames Wright SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 10304054ae39SJames Wright } 10314054ae39SJames Wright 10322b4f33d9SJames Wright if (faces_is) PetscCall(ISGetLocalSize(faces_is, &num_face)); 10332b4f33d9SJames Wright if (faces_is) PetscCall(ISGetIndices(faces_is, &faces)); 10346ff49feeSJames Wright PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 10356ff49feeSJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 10366ff49feeSJames Wright PetscCall(DMGetLocalSection(cdm, &csection)); 10374054ae39SJames Wright for (PetscInt f = 0; f < num_face; ++f) { 10386ff49feeSJames Wright PetscScalar *coords = NULL; 10396ff49feeSJames Wright PetscInt face = faces[f], flip = 1, label_value = -1, coords_size; 10404054ae39SJames Wright 10414054ae39SJames Wright { // Determine if orientation of face is flipped 10424054ae39SJames Wright PetscInt num_cells_support, num_faces, start = -1; 10434054ae39SJames Wright const PetscInt *orients, *cell_faces, *cells; 10444054ae39SJames Wright 10454054ae39SJames Wright PetscCall(DMPlexGetSupport(dm, face, &cells)); 10464054ae39SJames Wright PetscCall(DMPlexGetSupportSize(dm, face, &num_cells_support)); 10474054ae39SJames 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); 10484054ae39SJames Wright PetscCall(DMPlexGetCone(dm, cells[0], &cell_faces)); 10494054ae39SJames Wright PetscCall(DMPlexGetConeSize(dm, cells[0], &num_faces)); 10504054ae39SJames Wright for (PetscInt i = 0; i < num_faces; i++) { 10514054ae39SJames Wright if (cell_faces[i] == face) start = i; 10524054ae39SJames Wright } 10534054ae39SJames Wright PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Could not find face %" PetscInt_FMT " in cone of its support", face); 10544054ae39SJames Wright PetscCall(DMPlexGetConeOrientation(dm, cells[0], &orients)); 10554054ae39SJames Wright if (orients[start] < 0) flip = -1; 10564054ae39SJames Wright } 10574054ae39SJames Wright 10586ff49feeSJames Wright // Cannot use DMPlexComputeCellGeometryFVM() for high-order geometry, so must calculate normal vectors manually 10596ff49feeSJames Wright // Use the vertices (depth 0) of coordinate DM to calculate normal vector 10606ff49feeSJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 10614054ae39SJames Wright switch (dim) { 10624054ae39SJames Wright case 2: { 10636ff49feeSJames Wright PetscScalar vec[2]; 10646ff49feeSJames Wright 10656ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) vec[d] = flip * (PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d])); 10666ff49feeSJames Wright PetscScalar normal[] = {vec[1], -vec[0]}; 10676ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 10686ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 10694054ae39SJames Wright } else { 10706ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerTop : faceMarkerBottom; 10714054ae39SJames Wright } 10724054ae39SJames Wright } break; 10734054ae39SJames Wright case 3: { 10746ff49feeSJames Wright PetscScalar vec1[3], vec2[3], normal[3]; 10756ff49feeSJames Wright 10766ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) { 10776ff49feeSJames Wright vec1[d] = PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]); 10786ff49feeSJames Wright vec2[d] = PetscRealPart(coords[2 * dim + d]) - PetscRealPart(coords[1 * dim + d]); 10796ff49feeSJames Wright } 10806ff49feeSJames Wright 10816ff49feeSJames Wright // Calculate normal vector via cross-product 10826ff49feeSJames Wright normal[0] = flip * ((vec1[1] * vec2[2]) - (vec1[2] * vec2[1])); 10836ff49feeSJames Wright normal[1] = flip * ((vec1[2] * vec2[0]) - (vec1[0] * vec2[2])); 10846ff49feeSJames Wright normal[2] = flip * ((vec1[0] * vec2[1]) - (vec1[1] * vec2[0])); 10856ff49feeSJames Wright 10866ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 10876ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[2])) { 10886ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 10894054ae39SJames Wright } else { 10906ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 10914054ae39SJames Wright } 10924054ae39SJames Wright } else { 10936ff49feeSJames Wright if (PetscAbsScalar(normal[1]) > PetscAbsScalar(normal[2])) { 10946ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerBack : faceMarkerFront; 10954054ae39SJames Wright } else { 10966ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 10974054ae39SJames Wright } 10984054ae39SJames Wright } 10994054ae39SJames Wright } break; 11004054ae39SJames Wright } 11014054ae39SJames Wright 11024054ae39SJames Wright PetscInt previous_label_value; // always 1 due to DMPlexMarkBoundaryFaces call above 11034054ae39SJames Wright PetscCall(DMGetLabelValue(dm, "Face Sets", face, &previous_label_value)); 11044054ae39SJames Wright PetscCall(DMClearLabelValue(dm, "Face Sets", face, previous_label_value)); 11054054ae39SJames Wright PetscCall(DMSetLabelValue(dm, "Face Sets", face, label_value)); 11066ff49feeSJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 11074054ae39SJames Wright } 11082b4f33d9SJames Wright if (faces_is) PetscCall(ISRestoreIndices(faces_is, &faces)); 11096ff49feeSJames Wright PetscCall(ISDestroy(&faces_is)); 1110d7d2d1d2SJames Wright 1111d7d2d1d2SJames Wright // Create Isoperiodic SF from newly-created face labels 1112d7d2d1d2SJames Wright PetscSF periodicsfs[3]; 1113d7d2d1d2SJames Wright PetscInt periodic_sf_index = 0; 1114d7d2d1d2SJames Wright PetscScalar transform[3][4][4] = {{{0.}}}; 1115d7d2d1d2SJames Wright for (PetscInt d = 0; d < dim; d++) { 1116d7d2d1d2SJames Wright IS donor_is, periodic_is; 1117d7d2d1d2SJames Wright const PetscInt *donor_faces = NULL, *periodic_faces = NULL; 1118d7d2d1d2SJames Wright PetscInt num_donor = 0, num_periodic = 0; 1119d7d2d1d2SJames Wright PetscSF centroidsf; 1120d7d2d1d2SJames Wright PetscReal donor_to_periodic_distance; 1121d7d2d1d2SJames Wright const PetscInt face_pairings[2][3][2] = { 1122d7d2d1d2SJames Wright // 2D face pairings, {donor, periodic} 1123d7d2d1d2SJames Wright {{4, 2}, {1, 3}}, 1124d7d2d1d2SJames Wright // 3D face pairings 1125d7d2d1d2SJames Wright {{5, 6}, {3, 4}, {1, 2}} 1126d7d2d1d2SJames Wright }; 1127d7d2d1d2SJames Wright 1128d7d2d1d2SJames Wright if (periodicity[d] != DM_BOUNDARY_PERIODIC) continue; 1129d7d2d1d2SJames Wright { 1130d7d2d1d2SJames Wright // Compute centroidsf, which is the mapping from donor faces to periodic faces 1131d7d2d1d2SJames Wright // Matches the centroid of the faces together, ignoring the periodic direction component (which should not match between donor and periodic face) 1132d7d2d1d2SJames Wright PetscInt coords_size, centroid_comps = dim - 1; 1133d7d2d1d2SJames Wright PetscScalar *coords = NULL; 1134d7d2d1d2SJames Wright PetscReal *donor_centroids, *periodic_centroids; 1135d7d2d1d2SJames 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 1136d7d2d1d2SJames Wright 1137d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][0], &donor_is)); 1138d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][1], &periodic_is)); 1139d7d2d1d2SJames Wright if (donor_is) { 1140d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(donor_is, &num_donor)); 1141d7d2d1d2SJames Wright PetscCall(ISGetIndices(donor_is, &donor_faces)); 1142d7d2d1d2SJames Wright } 1143d7d2d1d2SJames Wright if (periodic_is) { 1144d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(periodic_is, &num_periodic)); 1145d7d2d1d2SJames Wright PetscCall(ISGetIndices(periodic_is, &periodic_faces)); 1146d7d2d1d2SJames Wright } 1147d7d2d1d2SJames Wright PetscCall(PetscCalloc2(num_donor * centroid_comps, &donor_centroids, num_periodic * centroid_comps, &periodic_centroids)); 1148d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_donor; f++) { 1149d7d2d1d2SJames Wright PetscInt face = donor_faces[f], num_coords; 1150d7d2d1d2SJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 1151d7d2d1d2SJames Wright num_coords = coords_size / dim; 1152d7d2d1d2SJames Wright for (PetscInt c = 0; c < num_coords; c++) { 1153d7d2d1d2SJames Wright PetscInt comp_index = 0; 1154d7d2d1d2SJames Wright loc_periodic[0] = PetscRealPart(coords[c * dim + d]); 1155d7d2d1d2SJames Wright for (PetscInt i = 0; i < dim; i++) { 1156d7d2d1d2SJames Wright if (i == d) continue; // Periodic direction not used for centroid calculation 1157d7d2d1d2SJames Wright donor_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords; 1158d7d2d1d2SJames Wright comp_index++; 1159d7d2d1d2SJames Wright } 1160d7d2d1d2SJames Wright } 1161d7d2d1d2SJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 1162d7d2d1d2SJames Wright } 1163d7d2d1d2SJames Wright 1164d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_periodic; f++) { 1165d7d2d1d2SJames Wright PetscInt face = periodic_faces[f], num_coords; 1166d7d2d1d2SJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 1167d7d2d1d2SJames Wright num_coords = coords_size / dim; 1168d7d2d1d2SJames Wright for (PetscInt c = 0; c < num_coords; c++) { 1169d7d2d1d2SJames Wright PetscInt comp_index = 0; 1170d7d2d1d2SJames Wright loc_periodic[1] = PetscRealPart(coords[c * dim + d]); 1171d7d2d1d2SJames Wright for (PetscInt i = 0; i < dim; i++) { 1172d7d2d1d2SJames Wright if (i == d) continue; // Periodic direction not used for centroid calculation 1173d7d2d1d2SJames Wright periodic_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords; 1174d7d2d1d2SJames Wright comp_index++; 1175d7d2d1d2SJames Wright } 1176d7d2d1d2SJames Wright } 1177d7d2d1d2SJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 1178d7d2d1d2SJames Wright } 1179d7d2d1d2SJames Wright PetscCallMPI(MPIU_Allreduce(loc_periodic, loc_periodic_global, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm))); 1180d7d2d1d2SJames Wright donor_to_periodic_distance = loc_periodic_global[1] - loc_periodic_global[0]; 1181d7d2d1d2SJames Wright 1182d7d2d1d2SJames Wright PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), ¢roidsf)); 1183d7d2d1d2SJames Wright PetscCall(PetscSFSetGraphFromCoordinates(centroidsf, num_donor, num_periodic, centroid_comps, 1e-10, donor_centroids, periodic_centroids)); 1184d7d2d1d2SJames Wright PetscCall(PetscSFViewFromOptions(centroidsf, NULL, "-dm_plex_box_label_centroid_sf_view")); 1185d7d2d1d2SJames Wright PetscCall(PetscFree2(donor_centroids, periodic_centroids)); 1186d7d2d1d2SJames Wright } 1187d7d2d1d2SJames Wright 1188d7d2d1d2SJames Wright { // Create Isoperiodic SF using centroidsSF 1189d7d2d1d2SJames Wright PetscInt pStart, pEnd; 1190d7d2d1d2SJames Wright PetscInt *leaf_faces; 1191d7d2d1d2SJames Wright const PetscSFNode *firemote; 1192d7d2d1d2SJames Wright PetscSFNode *isoperiodic_leaves; 1193d7d2d1d2SJames Wright 1194d7d2d1d2SJames Wright PetscCall(PetscMalloc1(num_periodic, &leaf_faces)); 1195d7d2d1d2SJames Wright PetscCall(PetscSFBcastBegin(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE)); 1196d7d2d1d2SJames Wright PetscCall(PetscSFBcastEnd(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE)); 1197d7d2d1d2SJames Wright 1198d7d2d1d2SJames Wright PetscCall(PetscMalloc1(num_periodic, &isoperiodic_leaves)); 1199d7d2d1d2SJames Wright PetscCall(PetscSFGetGraph(centroidsf, NULL, NULL, NULL, &firemote)); 1200d7d2d1d2SJames Wright for (PetscInt l = 0; l < num_periodic; ++l) { 1201d7d2d1d2SJames Wright isoperiodic_leaves[l].index = leaf_faces[l]; 1202d7d2d1d2SJames Wright isoperiodic_leaves[l].rank = firemote[l].rank; 1203d7d2d1d2SJames Wright } 1204d7d2d1d2SJames Wright 1205d7d2d1d2SJames Wright PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 1206d7d2d1d2SJames Wright PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &periodicsfs[periodic_sf_index])); 1207d7d2d1d2SJames Wright PetscCall(PetscSFSetGraph(periodicsfs[periodic_sf_index], pEnd - pStart, num_periodic, (PetscInt *)periodic_faces, PETSC_COPY_VALUES, isoperiodic_leaves, PETSC_OWN_POINTER)); 1208d7d2d1d2SJames Wright PetscCall(PetscSFViewFromOptions(periodicsfs[periodic_sf_index], NULL, "-dm_plex_box_label_periodic_sf_view")); 1209d7d2d1d2SJames Wright PetscCall(PetscFree(leaf_faces)); 1210d7d2d1d2SJames Wright } 1211d7d2d1d2SJames Wright 1212d7d2d1d2SJames Wright transform[periodic_sf_index][0][0] = 1; 1213d7d2d1d2SJames Wright transform[periodic_sf_index][1][1] = 1; 1214d7d2d1d2SJames Wright transform[periodic_sf_index][2][2] = 1; 1215d7d2d1d2SJames Wright transform[periodic_sf_index][3][3] = 1; 1216d7d2d1d2SJames Wright transform[periodic_sf_index][d][3] = donor_to_periodic_distance; 1217d7d2d1d2SJames Wright 1218d7d2d1d2SJames Wright periodic_sf_index++; 1219d7d2d1d2SJames Wright PetscCall(PetscSFDestroy(¢roidsf)); 1220d7d2d1d2SJames Wright if (donor_is) { 1221d7d2d1d2SJames Wright PetscCall(ISRestoreIndices(donor_is, &donor_faces)); 1222d7d2d1d2SJames Wright PetscCall(ISDestroy(&donor_is)); 1223d7d2d1d2SJames Wright } 1224d7d2d1d2SJames Wright if (periodic_is) { 1225d7d2d1d2SJames Wright PetscCall(ISRestoreIndices(periodic_is, &periodic_faces)); 1226d7d2d1d2SJames Wright PetscCall(ISDestroy(&periodic_is)); 1227d7d2d1d2SJames Wright } 1228d7d2d1d2SJames Wright PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][0])); 1229d7d2d1d2SJames Wright PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][1])); 1230d7d2d1d2SJames Wright } 1231d7d2d1d2SJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(dm, periodic_sf_index, periodicsfs)); 1232d7d2d1d2SJames Wright PetscCall(DMPlexSetIsoperiodicFaceTransform(dm, periodic_sf_index, (const PetscScalar *)transform)); 1233d7d2d1d2SJames Wright for (PetscInt p = 0; p < periodic_sf_index; p++) PetscCall(PetscSFDestroy(&periodicsfs[p])); 1234d7d2d1d2SJames Wright 1235d7d2d1d2SJames Wright { // Update coordinate DM with new Face Sets label 1236d7d2d1d2SJames Wright DM cdm; 1237d7d2d1d2SJames Wright DMLabel oldFaceSets, newFaceSets; 1238d7d2d1d2SJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 1239d7d2d1d2SJames Wright PetscCall(DMGetLabel(cdm, "Face Sets", &oldFaceSets)); 1240d7d2d1d2SJames Wright if (oldFaceSets) PetscCall(DMRemoveLabelBySelf(cdm, &oldFaceSets, PETSC_FALSE)); 1241d7d2d1d2SJames Wright PetscCall(DMLabelDuplicate(label, &newFaceSets)); 1242d7d2d1d2SJames Wright PetscCall(DMAddLabel(cdm, newFaceSets)); 1243d7d2d1d2SJames Wright PetscCall(DMLabelDestroy(&newFaceSets)); 1244d7d2d1d2SJames Wright } 12454054ae39SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 12464054ae39SJames Wright } 12474054ae39SJames Wright 1248d698cf03SStefano Zampini static PetscErrorCode DMPlexCreateSquareMesh_Simplex_CrissCross(DM dm, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType bd[]) 1249d698cf03SStefano Zampini { 1250d698cf03SStefano Zampini PetscInt markerTop = 1, faceMarkerTop = 3; 1251d698cf03SStefano Zampini PetscInt markerBottom = 1, faceMarkerBottom = 1; 1252d698cf03SStefano Zampini PetscInt markerRight = 1, faceMarkerRight = 2; 1253d698cf03SStefano Zampini PetscInt markerLeft = 1, faceMarkerLeft = 4; 1254d698cf03SStefano Zampini PetscBool markerSeparate = PETSC_FALSE; 1255d698cf03SStefano Zampini DMBoundaryType bdX = bd[0], bdY = bd[1]; 1256d698cf03SStefano Zampini PetscMPIInt rank; 1257d698cf03SStefano Zampini 1258d698cf03SStefano Zampini PetscFunctionBegin; 1259d698cf03SStefano Zampini PetscCheck(bdX == DM_BOUNDARY_NONE || bdX == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdX]); 1260d698cf03SStefano Zampini PetscCheck(bdY == DM_BOUNDARY_NONE || bdY == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdY]); 1261d698cf03SStefano Zampini PetscCall(DMSetDimension(dm, 2)); 1262d698cf03SStefano Zampini PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1263d698cf03SStefano Zampini PetscCall(DMCreateLabel(dm, "marker")); 1264d698cf03SStefano Zampini PetscCall(DMCreateLabel(dm, "Face Sets")); 1265d698cf03SStefano Zampini PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 1266d698cf03SStefano Zampini if (markerSeparate) { 1267d698cf03SStefano Zampini markerBottom = faceMarkerBottom; 1268d698cf03SStefano Zampini markerTop = faceMarkerTop; 1269d698cf03SStefano Zampini markerRight = faceMarkerRight; 1270d698cf03SStefano Zampini markerLeft = faceMarkerLeft; 1271d698cf03SStefano Zampini } 1272d698cf03SStefano Zampini { 1273d698cf03SStefano Zampini const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 1274d698cf03SStefano Zampini const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 1275d698cf03SStefano Zampini const PetscInt numZEdges = rank == 0 ? 4 * edges[0] * edges[1] : 0; /* Z-edges are the 4 internal edges per cell */ 1276d698cf03SStefano Zampini const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC ? edges[0] : edges[0] + 1) : 0; 1277d698cf03SStefano Zampini const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC ? edges[1] : edges[1] + 1) : 0; 1278d698cf03SStefano Zampini const PetscInt numZVertices = rank == 0 ? edges[0] * edges[1] : 0; 1279d698cf03SStefano Zampini const PetscInt numCells = 4 * numXEdges * numYEdges; 1280d698cf03SStefano Zampini const PetscInt numTotXEdges = numXEdges * numYVertices; 1281d698cf03SStefano Zampini const PetscInt numTotYEdges = numYEdges * numXVertices; 1282d698cf03SStefano Zampini const PetscInt numVertices = numXVertices * numYVertices + numZVertices; 1283d698cf03SStefano Zampini const PetscInt numEdges = numTotXEdges + numTotYEdges + numZEdges; 1284d698cf03SStefano Zampini const PetscInt firstVertex = numCells; 1285d698cf03SStefano Zampini const PetscInt firstXEdge = numCells + numVertices; 1286d698cf03SStefano Zampini const PetscInt firstYEdge = firstXEdge + numTotXEdges; 1287d698cf03SStefano Zampini const PetscInt firstZEdge = firstYEdge + numTotYEdges; 1288d698cf03SStefano Zampini Vec coordinates; 1289d698cf03SStefano Zampini PetscSection coordSection; 1290d698cf03SStefano Zampini PetscScalar *coords; 1291d698cf03SStefano Zampini PetscInt coordSize; 1292d698cf03SStefano Zampini PetscInt v, vx, vy; 1293d698cf03SStefano Zampini PetscInt c, e, ex, ey; 1294d698cf03SStefano Zampini 1295d698cf03SStefano Zampini PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVertices)); 1296d698cf03SStefano Zampini for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 3)); 1297d698cf03SStefano Zampini for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 1298d698cf03SStefano Zampini PetscCall(DMSetUp(dm)); 1299d698cf03SStefano Zampini 1300d698cf03SStefano Zampini /* Build cells and Z-edges */ 1301d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ++ey) { 1302d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ++ex) { 1303d698cf03SStefano Zampini const PetscInt exp1 = (ex + 1) % numXVertices; 1304d698cf03SStefano Zampini const PetscInt eyp1 = (ey + 1) % numYVertices; 1305d698cf03SStefano Zampini const PetscInt ez = firstZEdge + 4 * (ey * numXEdges + ex); 1306d698cf03SStefano Zampini const PetscInt vc = firstVertex + numXVertices * numYVertices + ey * numXEdges + ex; 1307d698cf03SStefano Zampini const PetscInt v0 = firstVertex + ey * numXVertices + ex; 1308d698cf03SStefano Zampini const PetscInt v1 = firstVertex + ey * numXVertices + exp1; 1309d698cf03SStefano Zampini const PetscInt v2 = firstVertex + eyp1 * numXVertices + exp1; 1310d698cf03SStefano Zampini const PetscInt v3 = firstVertex + eyp1 * numXVertices + ex; 1311d698cf03SStefano Zampini const PetscInt e0 = firstXEdge + ey * numXEdges + ex; 1312d698cf03SStefano Zampini const PetscInt e1 = firstYEdge + exp1 * numYEdges + ey; 1313d698cf03SStefano Zampini const PetscInt e2 = firstXEdge + eyp1 * numXEdges + ex; 1314d698cf03SStefano Zampini const PetscInt e3 = firstYEdge + ex * numYEdges + ey; 1315d698cf03SStefano Zampini 1316d698cf03SStefano Zampini const PetscInt cones[] = {ez, e0, ez + 1, ez + 1, e1, ez + 2, ez + 2, e2, ez + 3, ez + 3, e3, ez}; 1317d698cf03SStefano Zampini const PetscInt ornts[] = {-1, 0, 0, -1, 0, 0, -1, -1, 0, -1, -1, 0}; 1318d698cf03SStefano Zampini const PetscInt verts[] = {v0, vc, v1, vc, v2, vc, v3, vc}; 1319d698cf03SStefano Zampini 1320d698cf03SStefano Zampini for (c = 0; c < 4; c++) { 1321d698cf03SStefano Zampini PetscInt cell = 4 * (ey * numXEdges + ex) + c; 1322d698cf03SStefano Zampini PetscInt edge = ez + c; 1323d698cf03SStefano Zampini 1324d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, cell, cones + 3 * c)); 1325d698cf03SStefano Zampini PetscCall(DMPlexSetConeOrientation(dm, cell, ornts + 3 * c)); 1326d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, verts + 2 * c)); 1327d698cf03SStefano Zampini } 1328d698cf03SStefano Zampini } 1329d698cf03SStefano Zampini } 1330d698cf03SStefano Zampini 1331d698cf03SStefano Zampini /* Build Y edges*/ 1332d698cf03SStefano Zampini for (vx = 0; vx < numXVertices; vx++) { 1333d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ey++) { 1334d698cf03SStefano Zampini const PetscInt edge = firstYEdge + vx * numYEdges + ey; 1335d698cf03SStefano Zampini const PetscInt v0 = firstVertex + ey * numXVertices + vx; 1336d698cf03SStefano Zampini const PetscInt v1 = firstVertex + ((ey + 1) % numYVertices) * numXVertices + vx; 1337d698cf03SStefano Zampini const PetscInt cone[] = {v0, v1}; 1338d698cf03SStefano Zampini 1339d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, cone)); 1340d698cf03SStefano Zampini if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 1341d698cf03SStefano Zampini if (vx == numXVertices - 1) { 1342d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 1343d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1344d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1345d698cf03SStefano Zampini if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1346d698cf03SStefano Zampini } else if (vx == 0) { 1347d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 1348d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1349d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1350d698cf03SStefano Zampini if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 1351d698cf03SStefano Zampini } 1352d698cf03SStefano Zampini } 1353d698cf03SStefano Zampini } 1354d698cf03SStefano Zampini } 1355d698cf03SStefano Zampini 1356d698cf03SStefano Zampini /* Build X edges*/ 1357d698cf03SStefano Zampini for (vy = 0; vy < numYVertices; vy++) { 1358d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ex++) { 1359d698cf03SStefano Zampini const PetscInt edge = firstXEdge + vy * numXEdges + ex; 1360d698cf03SStefano Zampini const PetscInt v0 = firstVertex + vy * numXVertices + ex; 1361d698cf03SStefano Zampini const PetscInt v1 = firstVertex + vy * numXVertices + (ex + 1) % numXVertices; 1362d698cf03SStefano Zampini const PetscInt cone[] = {v0, v1}; 1363d698cf03SStefano Zampini 1364d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, cone)); 1365d698cf03SStefano Zampini if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 1366d698cf03SStefano Zampini if (vy == numYVertices - 1) { 1367d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 1368d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1369d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1370d698cf03SStefano Zampini if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1371d698cf03SStefano Zampini } else if (vy == 0) { 1372d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 1373d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1374d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1375d698cf03SStefano Zampini if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 1376d698cf03SStefano Zampini } 1377d698cf03SStefano Zampini } 1378d698cf03SStefano Zampini } 1379d698cf03SStefano Zampini } 1380d698cf03SStefano Zampini 1381d698cf03SStefano Zampini /* Compute support, stratify, and celltype label */ 1382d698cf03SStefano Zampini PetscCall(DMPlexSymmetrize(dm)); 1383d698cf03SStefano Zampini PetscCall(DMPlexStratify(dm)); 1384d698cf03SStefano Zampini PetscCall(DMPlexComputeCellTypes(dm)); 1385d698cf03SStefano Zampini 1386d698cf03SStefano Zampini /* Build coordinates */ 1387d698cf03SStefano Zampini PetscCall(DMGetCoordinateSection(dm, &coordSection)); 1388d698cf03SStefano Zampini PetscCall(PetscSectionSetNumFields(coordSection, 1)); 1389d698cf03SStefano Zampini PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 1390d698cf03SStefano Zampini PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 1391d698cf03SStefano Zampini for (v = firstVertex; v < firstVertex + numVertices; ++v) { 1392d698cf03SStefano Zampini PetscCall(PetscSectionSetDof(coordSection, v, 2)); 1393d698cf03SStefano Zampini PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 1394d698cf03SStefano Zampini } 1395d698cf03SStefano Zampini PetscCall(PetscSectionSetUp(coordSection)); 1396d698cf03SStefano Zampini PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 1397d698cf03SStefano Zampini PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 1398d698cf03SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 1399d698cf03SStefano Zampini PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 1400d698cf03SStefano Zampini PetscCall(VecSetBlockSize(coordinates, 2)); 1401d698cf03SStefano Zampini PetscCall(VecSetType(coordinates, VECSTANDARD)); 1402d698cf03SStefano Zampini PetscCall(VecGetArray(coordinates, &coords)); 1403d698cf03SStefano Zampini for (vy = 0; vy < numYVertices; ++vy) { 1404d698cf03SStefano Zampini for (vx = 0; vx < numXVertices; ++vx) { 1405d698cf03SStefano Zampini coords[2 * (vy * numXVertices + vx) + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 1406d698cf03SStefano Zampini coords[2 * (vy * numXVertices + vx) + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1407d698cf03SStefano Zampini } 1408d698cf03SStefano Zampini } 1409d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ++ey) { 1410d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ++ex) { 1411d698cf03SStefano Zampini const PetscInt c = ey * numXEdges + ex + numYVertices * numXVertices; 1412d698cf03SStefano Zampini 1413d698cf03SStefano Zampini coords[2 * c + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * (ex + 0.5); 1414d698cf03SStefano Zampini coords[2 * c + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * (ey + 0.5); 1415d698cf03SStefano Zampini } 1416d698cf03SStefano Zampini } 1417d698cf03SStefano Zampini PetscCall(VecRestoreArray(coordinates, &coords)); 1418d698cf03SStefano Zampini PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 1419d698cf03SStefano Zampini PetscCall(VecDestroy(&coordinates)); 1420d698cf03SStefano Zampini 1421d698cf03SStefano Zampini /* handle periodic BC */ 1422d698cf03SStefano Zampini if (bdX == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_PERIODIC) { 1423d698cf03SStefano Zampini PetscReal L[2] = {-1., -1.}; 1424d698cf03SStefano Zampini PetscReal maxCell[2] = {-1., -1.}; 1425d698cf03SStefano Zampini 1426d698cf03SStefano Zampini for (PetscInt d = 0; d < 2; ++d) { 1427d698cf03SStefano Zampini if (bd[d] != DM_BOUNDARY_NONE) { 1428d698cf03SStefano Zampini L[d] = upper[d] - lower[d]; 1429d698cf03SStefano Zampini maxCell[d] = 1.1 * (L[d] / PetscMax(1, edges[d])); 1430d698cf03SStefano Zampini } 1431d698cf03SStefano Zampini } 1432d698cf03SStefano Zampini PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1433d698cf03SStefano Zampini } 1434d698cf03SStefano Zampini } 1435d698cf03SStefano Zampini PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 1436d698cf03SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1437d698cf03SStefano Zampini } 1438d698cf03SStefano Zampini 1439d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 1440d71ae5a4SJacob Faibussowitsch { 14419318fe57SMatthew G. Knepley DM boundary, vol; 1442c22d3578SMatthew G. Knepley DMLabel bdlabel; 1443d698cf03SStefano Zampini PetscBool crisscross = PETSC_FALSE; 1444d6218766SMatthew G. Knepley 1445d6218766SMatthew G. Knepley PetscFunctionBegin; 14464f572ea9SToby Isaac PetscAssertPointer(dm, 1); 1447d698cf03SStefano Zampini if (dim == 2) PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_box_crisscross", &crisscross, NULL)); 1448d698cf03SStefano Zampini if (crisscross) { 1449d698cf03SStefano Zampini PetscCall(DMPlexCreateSquareMesh_Simplex_CrissCross(dm, faces, lower, upper, periodicity)); 1450d698cf03SStefano Zampini } else { 1451c22d3578SMatthew 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"); 14529566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary)); 14539566063dSJacob Faibussowitsch PetscCall(DMSetType(boundary, DMPLEX)); 1454d698cf03SStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)boundary, ((PetscObject)dm)->prefix)); 14559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 14569566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 1457c22d3578SMatthew G. Knepley PetscCall(DMGetLabel(vol, "marker", &bdlabel)); 1458c22d3578SMatthew G. Knepley if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel)); 14595de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol)); 146069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 1461d698cf03SStefano Zampini PetscCall(DMDestroy(&boundary)); 1462d698cf03SStefano Zampini } 14634054ae39SJames Wright if (interpolate) { 14644054ae39SJames Wright PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 1465d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, periodicity)); 14664054ae39SJames Wright } 14673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1468d6218766SMatthew G. Knepley } 1469d6218766SMatthew G. Knepley 1470d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 1471d71ae5a4SJacob Faibussowitsch { 1472ed0e4b50SMatthew G. Knepley DMLabel cutLabel = NULL; 1473f4eb4c5dSMatthew G. Knepley PetscInt markerTop = 1, faceMarkerTop = 1; 1474f4eb4c5dSMatthew G. Knepley PetscInt markerBottom = 1, faceMarkerBottom = 1; 1475f4eb4c5dSMatthew G. Knepley PetscInt markerFront = 1, faceMarkerFront = 1; 1476f4eb4c5dSMatthew G. Knepley PetscInt markerBack = 1, faceMarkerBack = 1; 1477f4eb4c5dSMatthew G. Knepley PetscInt markerRight = 1, faceMarkerRight = 1; 1478f4eb4c5dSMatthew G. Knepley PetscInt markerLeft = 1, faceMarkerLeft = 1; 14793dfda0b1SToby Isaac PetscInt dim; 1480d8211ee3SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 14813dfda0b1SToby Isaac PetscMPIInt rank; 14823dfda0b1SToby Isaac 14833dfda0b1SToby Isaac PetscFunctionBegin; 14849566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 14859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 14869566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 14879566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 14889566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 14899371c9d4SSatish 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) { 14909371c9d4SSatish Balay if (cutMarker) { 14919371c9d4SSatish Balay PetscCall(DMCreateLabel(dm, "periodic_cut")); 14929371c9d4SSatish Balay PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 14939371c9d4SSatish Balay } 1494d8211ee3SMatthew G. Knepley } 14953dfda0b1SToby Isaac switch (dim) { 14963dfda0b1SToby Isaac case 2: 1497f4eb4c5dSMatthew G. Knepley faceMarkerTop = 3; 1498f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1499f4eb4c5dSMatthew G. Knepley faceMarkerRight = 2; 1500f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 4; 15013dfda0b1SToby Isaac break; 15023dfda0b1SToby Isaac case 3: 1503f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1504f4eb4c5dSMatthew G. Knepley faceMarkerTop = 2; 1505f4eb4c5dSMatthew G. Knepley faceMarkerFront = 3; 1506f4eb4c5dSMatthew G. Knepley faceMarkerBack = 4; 1507f4eb4c5dSMatthew G. Knepley faceMarkerRight = 5; 1508f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 6; 15093dfda0b1SToby Isaac break; 1510d71ae5a4SJacob Faibussowitsch default: 1511d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 15123dfda0b1SToby Isaac } 15139566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 1514f4eb4c5dSMatthew G. Knepley if (markerSeparate) { 1515f4eb4c5dSMatthew G. Knepley markerBottom = faceMarkerBottom; 1516f4eb4c5dSMatthew G. Knepley markerTop = faceMarkerTop; 1517f4eb4c5dSMatthew G. Knepley markerFront = faceMarkerFront; 1518f4eb4c5dSMatthew G. Knepley markerBack = faceMarkerBack; 1519f4eb4c5dSMatthew G. Knepley markerRight = faceMarkerRight; 1520f4eb4c5dSMatthew G. Knepley markerLeft = faceMarkerLeft; 15213dfda0b1SToby Isaac } 15223dfda0b1SToby Isaac { 1523dd400576SPatrick Sanan const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 1524dd400576SPatrick Sanan const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 1525dd400576SPatrick Sanan const PetscInt numZEdges = rank == 0 ? edges[2] : 0; 1526dd400576SPatrick Sanan const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0; 1527dd400576SPatrick Sanan const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0; 1528dd400576SPatrick Sanan const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0; 15293dfda0b1SToby Isaac const PetscInt numCells = numXEdges * numYEdges * numZEdges; 15303dfda0b1SToby Isaac const PetscInt numXFaces = numYEdges * numZEdges; 15313dfda0b1SToby Isaac const PetscInt numYFaces = numXEdges * numZEdges; 15323dfda0b1SToby Isaac const PetscInt numZFaces = numXEdges * numYEdges; 15333dfda0b1SToby Isaac const PetscInt numTotXFaces = numXVertices * numXFaces; 15343dfda0b1SToby Isaac const PetscInt numTotYFaces = numYVertices * numYFaces; 15353dfda0b1SToby Isaac const PetscInt numTotZFaces = numZVertices * numZFaces; 15363dfda0b1SToby Isaac const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 15373dfda0b1SToby Isaac const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices; 15383dfda0b1SToby Isaac const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices; 15393dfda0b1SToby Isaac const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices; 15403dfda0b1SToby Isaac const PetscInt numVertices = numXVertices * numYVertices * numZVertices; 15413dfda0b1SToby Isaac const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 15423dfda0b1SToby Isaac const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 15433dfda0b1SToby Isaac const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 15443dfda0b1SToby Isaac const PetscInt firstYFace = firstXFace + numTotXFaces; 15453dfda0b1SToby Isaac const PetscInt firstZFace = firstYFace + numTotYFaces; 15463dfda0b1SToby Isaac const PetscInt firstXEdge = numCells + numFaces + numVertices; 15473dfda0b1SToby Isaac const PetscInt firstYEdge = firstXEdge + numTotXEdges; 15483dfda0b1SToby Isaac const PetscInt firstZEdge = firstYEdge + numTotYEdges; 15493dfda0b1SToby Isaac Vec coordinates; 15503dfda0b1SToby Isaac PetscSection coordSection; 15513dfda0b1SToby Isaac PetscScalar *coords; 15523dfda0b1SToby Isaac PetscInt coordSize; 15533dfda0b1SToby Isaac PetscInt v, vx, vy, vz; 15543dfda0b1SToby Isaac PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 15553dfda0b1SToby Isaac 15569566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices)); 155748a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 155848a46eb9SPierre Jolivet for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 155948a46eb9SPierre Jolivet for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 15609566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 15613dfda0b1SToby Isaac /* Build cells */ 15623dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 15633dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 15643dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 15653dfda0b1SToby Isaac PetscInt cell = (fz * numYEdges + fy) * numXEdges + fx; 15663dfda0b1SToby Isaac PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 15673dfda0b1SToby Isaac PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices); 15683dfda0b1SToby Isaac PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 15693dfda0b1SToby Isaac PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices); 15703dfda0b1SToby Isaac PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 15713dfda0b1SToby Isaac PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices); 15723dfda0b1SToby Isaac /* B, T, F, K, R, L */ 1573b5a892a1SMatthew G. Knepley PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */ 157442206facSLisandro Dalcin PetscInt cone[6]; 15753dfda0b1SToby Isaac 15763dfda0b1SToby Isaac /* no boundary twisting in 3D */ 15779371c9d4SSatish Balay cone[0] = faceB; 15789371c9d4SSatish Balay cone[1] = faceT; 15799371c9d4SSatish Balay cone[2] = faceF; 15809371c9d4SSatish Balay cone[3] = faceK; 15819371c9d4SSatish Balay cone[4] = faceR; 15829371c9d4SSatish Balay cone[5] = faceL; 15839566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, cell, cone)); 15849566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, cell, ornt)); 15859566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 15869566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 15879566063dSJacob Faibussowitsch if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 15883dfda0b1SToby Isaac } 15893dfda0b1SToby Isaac } 15903dfda0b1SToby Isaac } 15913dfda0b1SToby Isaac /* Build x faces */ 15923dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 15933dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 15943dfda0b1SToby Isaac for (fx = 0; fx < numXVertices; ++fx) { 15953dfda0b1SToby Isaac PetscInt face = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 15963dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 15973dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz; 15983dfda0b1SToby Isaac PetscInt edgeB = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 15993dfda0b1SToby Isaac PetscInt edgeT = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy; 1600b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16013dfda0b1SToby Isaac PetscInt cone[4]; 16023dfda0b1SToby Isaac 16033dfda0b1SToby Isaac if (dim == 3) { 16043dfda0b1SToby Isaac /* markers */ 16053dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 16063dfda0b1SToby Isaac if (fx == numXVertices - 1) { 16079566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 16089566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerRight)); 16099371c9d4SSatish Balay } else if (fx == 0) { 16109566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 16119566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft)); 16123dfda0b1SToby Isaac } 16133dfda0b1SToby Isaac } 16143dfda0b1SToby Isaac } 16159371c9d4SSatish Balay cone[0] = edgeB; 16169371c9d4SSatish Balay cone[1] = edgeR; 16179371c9d4SSatish Balay cone[2] = edgeT; 16189371c9d4SSatish Balay cone[3] = edgeL; 16199566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 16209566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 16213dfda0b1SToby Isaac } 16223dfda0b1SToby Isaac } 16233dfda0b1SToby Isaac } 16243dfda0b1SToby Isaac /* Build y faces */ 16253dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 162642206facSLisandro Dalcin for (fx = 0; fx < numXEdges; ++fx) { 16273dfda0b1SToby Isaac for (fy = 0; fy < numYVertices; ++fy) { 16283dfda0b1SToby Isaac PetscInt face = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 16293dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 16303dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz; 16313dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 16323dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx; 1633b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16343dfda0b1SToby Isaac PetscInt cone[4]; 16353dfda0b1SToby Isaac 16363dfda0b1SToby Isaac if (dim == 3) { 16373dfda0b1SToby Isaac /* markers */ 16383dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 16393dfda0b1SToby Isaac if (fy == numYVertices - 1) { 16409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 16419566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBack)); 16429371c9d4SSatish Balay } else if (fy == 0) { 16439566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 16449566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerFront)); 16453dfda0b1SToby Isaac } 16463dfda0b1SToby Isaac } 16473dfda0b1SToby Isaac } 16489371c9d4SSatish Balay cone[0] = edgeB; 16499371c9d4SSatish Balay cone[1] = edgeR; 16509371c9d4SSatish Balay cone[2] = edgeT; 16519371c9d4SSatish Balay cone[3] = edgeL; 16529566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 16539566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 16543dfda0b1SToby Isaac } 16553dfda0b1SToby Isaac } 16563dfda0b1SToby Isaac } 16573dfda0b1SToby Isaac /* Build z faces */ 16583dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 16593dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 16603dfda0b1SToby Isaac for (fz = 0; fz < numZVertices; fz++) { 16613dfda0b1SToby Isaac PetscInt face = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 16623dfda0b1SToby Isaac PetscInt edgeL = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 16633dfda0b1SToby Isaac PetscInt edgeR = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy; 16643dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 16653dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx; 1666b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16673dfda0b1SToby Isaac PetscInt cone[4]; 16683dfda0b1SToby Isaac 16693dfda0b1SToby Isaac if (dim == 2) { 16709371c9d4SSatish Balay if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) { 16719371c9d4SSatish Balay edgeR += numYEdges - 1 - 2 * fy; 16729371c9d4SSatish Balay ornt[1] = -1; 16739371c9d4SSatish Balay } 16749371c9d4SSatish Balay if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) { 16759371c9d4SSatish Balay edgeT += numXEdges - 1 - 2 * fx; 16769371c9d4SSatish Balay ornt[2] = 0; 16779371c9d4SSatish Balay } 16789566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 16799566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 1680d1c88043SMatthew G. Knepley } else { 16813dfda0b1SToby Isaac /* markers */ 16823dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 16833dfda0b1SToby Isaac if (fz == numZVertices - 1) { 16849566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 16859566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerTop)); 16869371c9d4SSatish Balay } else if (fz == 0) { 16879566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 16889566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom)); 16893dfda0b1SToby Isaac } 16903dfda0b1SToby Isaac } 16913dfda0b1SToby Isaac } 16929371c9d4SSatish Balay cone[0] = edgeB; 16939371c9d4SSatish Balay cone[1] = edgeR; 16949371c9d4SSatish Balay cone[2] = edgeT; 16959371c9d4SSatish Balay cone[3] = edgeL; 16969566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 16979566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 16983dfda0b1SToby Isaac } 16993dfda0b1SToby Isaac } 17003dfda0b1SToby Isaac } 17013dfda0b1SToby Isaac /* Build Z edges*/ 17023dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 17033dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 17043dfda0b1SToby Isaac for (ez = 0; ez < numZEdges; ez++) { 17053dfda0b1SToby Isaac const PetscInt edge = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez; 17063dfda0b1SToby Isaac const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx; 17073dfda0b1SToby Isaac const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx; 17083dfda0b1SToby Isaac PetscInt cone[2]; 17093dfda0b1SToby Isaac 17109371c9d4SSatish Balay cone[0] = vertexB; 17119371c9d4SSatish Balay cone[1] = vertexT; 1712c2df9bbfSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, edge, cone)); 17133dfda0b1SToby Isaac if (dim == 3) { 17143dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 17153dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17169566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1717c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1718c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1719c2df9bbfSMatthew G. Knepley } else if (vx == 0) { 17209566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1721c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1722c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 17233dfda0b1SToby Isaac } 17243dfda0b1SToby Isaac } 17253dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 17263dfda0b1SToby Isaac if (vy == numYVertices - 1) { 17279566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1728c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1729c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1730c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 17319566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1732c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1733c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 17343dfda0b1SToby Isaac } 17353dfda0b1SToby Isaac } 17363dfda0b1SToby Isaac } 17373dfda0b1SToby Isaac } 17383dfda0b1SToby Isaac } 17393dfda0b1SToby Isaac } 17403dfda0b1SToby Isaac /* Build Y edges*/ 17413dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 17423dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 17433dfda0b1SToby Isaac for (ey = 0; ey < numYEdges; ey++) { 17443dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx; 17453dfda0b1SToby Isaac const PetscInt edge = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey; 17463dfda0b1SToby Isaac const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx; 17473dfda0b1SToby Isaac const PetscInt vertexK = firstVertex + nextv; 17483dfda0b1SToby Isaac PetscInt cone[2]; 17493dfda0b1SToby Isaac 17509371c9d4SSatish Balay cone[0] = vertexF; 17519371c9d4SSatish Balay cone[1] = vertexK; 17529566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 17533dfda0b1SToby Isaac if (dim == 2) { 17543dfda0b1SToby Isaac if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 17553dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17569566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 17579566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 17589566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1759c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1760d8211ee3SMatthew G. Knepley } else if (vx == 0) { 17619566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 17629566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 17639566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1764c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 17653dfda0b1SToby Isaac } 1766d8211ee3SMatthew G. Knepley } else { 17674c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 17689566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 17699566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1770c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 17713dfda0b1SToby Isaac } 1772d8211ee3SMatthew G. Knepley } 1773d8211ee3SMatthew G. Knepley } else { 17743dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 17753dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17769566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1777c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1778c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1779d8211ee3SMatthew G. Knepley } else if (vx == 0) { 17809566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1781c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1782c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 17833dfda0b1SToby Isaac } 17843dfda0b1SToby Isaac } 17853dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 17863dfda0b1SToby Isaac if (vz == numZVertices - 1) { 17879566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1788c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1789c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1790d8211ee3SMatthew G. Knepley } else if (vz == 0) { 17919566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1792c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1793c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 17943dfda0b1SToby Isaac } 17953dfda0b1SToby Isaac } 17963dfda0b1SToby Isaac } 17973dfda0b1SToby Isaac } 17983dfda0b1SToby Isaac } 17993dfda0b1SToby Isaac } 18003dfda0b1SToby Isaac /* Build X edges*/ 18013dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 18023dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 18033dfda0b1SToby Isaac for (ex = 0; ex < numXEdges; ex++) { 18043dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices; 18053dfda0b1SToby Isaac const PetscInt edge = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex; 18063dfda0b1SToby Isaac const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex; 18073dfda0b1SToby Isaac const PetscInt vertexR = firstVertex + nextv; 18083dfda0b1SToby Isaac PetscInt cone[2]; 18093dfda0b1SToby Isaac 18109371c9d4SSatish Balay cone[0] = vertexL; 18119371c9d4SSatish Balay cone[1] = vertexR; 18129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 18133dfda0b1SToby Isaac if (dim == 2) { 18143dfda0b1SToby Isaac if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 18153dfda0b1SToby Isaac if (vy == numYVertices - 1) { 18169566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 18179566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 18189566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1819c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1820d8211ee3SMatthew G. Knepley } else if (vy == 0) { 18219566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 18229566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 18239566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1824c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 18253dfda0b1SToby Isaac } 1826d8211ee3SMatthew G. Knepley } else { 18274c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 18289566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 18299566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1830c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 18313dfda0b1SToby Isaac } 1832d8211ee3SMatthew G. Knepley } 1833d8211ee3SMatthew G. Knepley } else { 18343dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 18353dfda0b1SToby Isaac if (vy == numYVertices - 1) { 18369566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1837c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1838c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1839c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 18409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1841c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1842c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 18433dfda0b1SToby Isaac } 18443dfda0b1SToby Isaac } 18453dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 18463dfda0b1SToby Isaac if (vz == numZVertices - 1) { 18479566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1848c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1849c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1850c2df9bbfSMatthew G. Knepley } else if (vz == 0) { 18519566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1852c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1853c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 18543dfda0b1SToby Isaac } 18553dfda0b1SToby Isaac } 18563dfda0b1SToby Isaac } 18573dfda0b1SToby Isaac } 18583dfda0b1SToby Isaac } 18593dfda0b1SToby Isaac } 18609566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 18619566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 18623dfda0b1SToby Isaac /* Build coordinates */ 18639566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 18649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 18659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 18669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 18673dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex + numVertices; ++v) { 18689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 18699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 18703dfda0b1SToby Isaac } 18719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 18729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 18739566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 18749566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 18759566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 18769566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 18779566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 18789566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 18793dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; ++vz) { 18803dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; ++vy) { 18813dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; ++vx) { 18823dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 18833dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1884ad540459SPierre Jolivet if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz; 18853dfda0b1SToby Isaac } 18863dfda0b1SToby Isaac } 18873dfda0b1SToby Isaac } 18889566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 18899566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 18909566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 18913dfda0b1SToby Isaac } 18923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18933dfda0b1SToby Isaac } 18943dfda0b1SToby Isaac 1895d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1896d71ae5a4SJacob Faibussowitsch { 18979318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 18989318fe57SMatthew G. Knepley PetscInt fac[3] = {0, 0, 0}, d; 1899552f7358SJed Brown 1900552f7358SJed Brown PetscFunctionBegin; 19014f572ea9SToby Isaac PetscAssertPointer(dm, 1); 19029318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 19039566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 19049371c9d4SSatish Balay for (d = 0; d < dim; ++d) { 19059371c9d4SSatish Balay fac[d] = faces[d]; 19069371c9d4SSatish Balay bdt[d] = periodicity[d]; 19079371c9d4SSatish Balay } 19089566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2])); 19099371c9d4SSatish 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))) { 19106858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 19116858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1912552f7358SJed Brown 19139318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19146858538eSMatthew G. Knepley if (periodicity[d] != DM_BOUNDARY_NONE) { 19159318fe57SMatthew G. Knepley L[d] = upper[d] - lower[d]; 19169318fe57SMatthew G. Knepley maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d])); 1917768d5fceSMatthew G. Knepley } 19186858538eSMatthew G. Knepley } 19194fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1920768d5fceSMatthew G. Knepley } 19219566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 19223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19239318fe57SMatthew G. Knepley } 19249318fe57SMatthew G. Knepley 19255dca41c3SJed 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) 1926d71ae5a4SJacob Faibussowitsch { 19279318fe57SMatthew G. Knepley PetscFunctionBegin; 192846139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 19295dca41c3SJed Brown if (shape == DM_SHAPE_ZBOX) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 19306725e60dSJed Brown else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 19319566063dSJacob Faibussowitsch else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 19329566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity)); 19339318fe57SMatthew G. Knepley if (!interpolate && dim > 1 && !simplex) { 1934768d5fceSMatthew G. Knepley DM udm; 1935768d5fceSMatthew G. Knepley 19369566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 19379566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, udm)); 193869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 1939768d5fceSMatthew G. Knepley } 194046139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 19413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1942c8c68bd8SToby Isaac } 1943c8c68bd8SToby Isaac 19445d83a8b1SBarry Smith /*@ 1945768d5fceSMatthew G. Knepley DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 1946768d5fceSMatthew G. Knepley 1947d083f849SBarry Smith Collective 1948768d5fceSMatthew G. Knepley 1949768d5fceSMatthew G. Knepley Input Parameters: 1950a1cb98faSBarry Smith + comm - The communicator for the `DM` object 1951768d5fceSMatthew G. Knepley . dim - The spatial dimension 1952a1cb98faSBarry Smith . simplex - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells 195320f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 195420f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 195520f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 195620f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 195742108689Sksagiyam . interpolate - Flag to create intermediate mesh pieces (edges, faces) 195842108689Sksagiyam . localizationHeight - Flag to localize edges and faces in addition to cells; only significant for periodic meshes 195942108689Sksagiyam - sparseLocalize - Flag to localize coordinates only for cells near the periodic boundary; only significant for periodic meshes 1960768d5fceSMatthew G. Knepley 1961768d5fceSMatthew G. Knepley Output Parameter: 1962a1cb98faSBarry Smith . dm - The `DM` object 1963768d5fceSMatthew G. Knepley 1964768d5fceSMatthew G. Knepley Level: beginner 1965768d5fceSMatthew G. Knepley 1966a1cb98faSBarry Smith Note: 1967a1cb98faSBarry Smith To customize this mesh using options, use 1968a1cb98faSBarry Smith .vb 1969a1cb98faSBarry Smith DMCreate(comm, &dm); 1970a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 1971a1cb98faSBarry Smith DMSetFromOptions(dm); 1972a1cb98faSBarry Smith .ve 1973a1cb98faSBarry Smith and use the options in `DMSetFromOptions()`. 1974a1cb98faSBarry Smith 1975a4e35b19SJacob Faibussowitsch Here is the numbering returned for 2 faces in each direction for tensor cells\: 1976a1cb98faSBarry Smith .vb 1977a1cb98faSBarry Smith 10---17---11---18----12 1978a1cb98faSBarry Smith | | | 1979a1cb98faSBarry Smith | | | 1980a1cb98faSBarry Smith 20 2 22 3 24 1981a1cb98faSBarry Smith | | | 1982a1cb98faSBarry Smith | | | 1983a1cb98faSBarry Smith 7---15----8---16----9 1984a1cb98faSBarry Smith | | | 1985a1cb98faSBarry Smith | | | 1986a1cb98faSBarry Smith 19 0 21 1 23 1987a1cb98faSBarry Smith | | | 1988a1cb98faSBarry Smith | | | 1989a1cb98faSBarry Smith 4---13----5---14----6 1990a1cb98faSBarry Smith .ve 1991a1cb98faSBarry Smith and for simplicial cells 1992a1cb98faSBarry Smith .vb 1993a1cb98faSBarry Smith 14----8---15----9----16 1994a1cb98faSBarry Smith |\ 5 |\ 7 | 1995a1cb98faSBarry Smith | \ | \ | 1996a1cb98faSBarry Smith 13 2 14 3 15 1997a1cb98faSBarry Smith | 4 \ | 6 \ | 1998a1cb98faSBarry Smith | \ | \ | 1999a1cb98faSBarry Smith 11----6---12----7----13 2000a1cb98faSBarry Smith |\ |\ | 2001a1cb98faSBarry Smith | \ 1 | \ 3 | 2002a1cb98faSBarry Smith 10 0 11 1 12 2003a1cb98faSBarry Smith | 0 \ | 2 \ | 2004a1cb98faSBarry Smith | \ | \ | 2005a1cb98faSBarry Smith 8----4----9----5----10 2006a1cb98faSBarry Smith .ve 2007a1cb98faSBarry Smith 20081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 2009768d5fceSMatthew G. Knepley @*/ 201042108689Sksagiyam 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) 2011d71ae5a4SJacob Faibussowitsch { 20129318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 2013fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 2014fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 2015fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 2016552f7358SJed Brown 2017768d5fceSMatthew G. Knepley PetscFunctionBegin; 20189566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 20199566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 20205dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(*dm, DM_SHAPE_BOX, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 202142108689Sksagiyam if (periodicity) { 202242108689Sksagiyam DM cdm; 202342108689Sksagiyam 202442108689Sksagiyam PetscCall(DMGetCoordinateDM(*dm, &cdm)); 202542108689Sksagiyam PetscCall(DMPlexSetMaxProjectionHeight(cdm, localizationHeight)); 202642108689Sksagiyam PetscCall(DMSetSparseLocalize(*dm, sparseLocalize)); 202742108689Sksagiyam PetscCall(DMLocalizeCoordinates(*dm)); 202842108689Sksagiyam } 20293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20309318fe57SMatthew G. Knepley } 2031fdbf62faSLisandro Dalcin 2032d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 2033d71ae5a4SJacob Faibussowitsch { 20349318fe57SMatthew G. Knepley DM bdm, vol; 20359318fe57SMatthew G. Knepley PetscInt i; 20369318fe57SMatthew G. Knepley 20379318fe57SMatthew G. Knepley PetscFunctionBegin; 20381fcf445aSMatthew G. Knepley // TODO Now we can support periodicity 203908401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 20409566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 20419566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 20429566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 204346139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, bdm, 0, 0, 0)); 20449566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 20451fcf445aSMatthew G. Knepley PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, NULL, NULL, &vol)); 204646139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, bdm, 0, 0, 0)); 20479566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 204869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 20499318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 20509318fe57SMatthew G. Knepley Vec v; 20519318fe57SMatthew G. Knepley PetscScalar *x; 20529318fe57SMatthew G. Knepley PetscInt cDim, n; 20539318fe57SMatthew G. Knepley 20549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 20559566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 20569566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 20579566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 20589318fe57SMatthew G. Knepley x += cDim; 20599318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 20609566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 20619566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 20629318fe57SMatthew G. Knepley } 20633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2064552f7358SJed Brown } 2065552f7358SJed Brown 206600dabe28SStefano Zampini /*@ 206739f4f5dbSPierre Jolivet DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tessellating the (x,y) plane and extruding in the third direction using wedge cells. 206800dabe28SStefano Zampini 2069d083f849SBarry Smith Collective 207000dabe28SStefano Zampini 207100dabe28SStefano Zampini Input Parameters: 2072a1cb98faSBarry Smith + comm - The communicator for the `DM` object 207320f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1, 1, 1) 207420f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 207520f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 207620f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 2077a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 207800dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 207900dabe28SStefano Zampini 208000dabe28SStefano Zampini Output Parameter: 2081a1cb98faSBarry Smith . dm - The `DM` object 208200dabe28SStefano Zampini 208300dabe28SStefano Zampini Level: beginner 208400dabe28SStefano Zampini 20851cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 208600dabe28SStefano Zampini @*/ 2087d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 2088d71ae5a4SJacob Faibussowitsch { 20899318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 209000dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 209100dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 209200dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 209300dabe28SStefano Zampini 209400dabe28SStefano Zampini PetscFunctionBegin; 20959566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 20969566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 20979566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 2098d410b0cfSMatthew G. Knepley if (!interpolate) { 2099d410b0cfSMatthew G. Knepley DM udm; 210000dabe28SStefano Zampini 21019566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 210269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 210300dabe28SStefano Zampini } 21047ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 21053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 210600dabe28SStefano Zampini } 210700dabe28SStefano Zampini 2108cfb853baSMatthew G. Knepley /* 2109cfb853baSMatthew 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. 2110cfb853baSMatthew G. Knepley 2111cfb853baSMatthew G. Knepley Input Parameters: 2112cfb853baSMatthew G. Knepley + len - The length of the tuple 2113cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max) 2114cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition 2115cfb853baSMatthew G. Knepley 2116cfb853baSMatthew G. Knepley Output Parameter: 211720f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max` 2118cfb853baSMatthew G. Knepley 2119cfb853baSMatthew G. Knepley Level: developer 2120cfb853baSMatthew G. Knepley 212120f4b53cSBarry Smith Note: 212220f4b53cSBarry Smith Ordering is lexicographic with lowest index as least significant in ordering. 212320f4b53cSBarry 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}. 212420f4b53cSBarry Smith 2125cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal() 2126cfb853baSMatthew G. Knepley */ 2127cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[]) 2128cfb853baSMatthew G. Knepley { 2129cfb853baSMatthew G. Knepley PetscInt i; 2130cfb853baSMatthew G. Knepley 2131cfb853baSMatthew G. Knepley PetscFunctionBegin; 2132cfb853baSMatthew G. Knepley for (i = 0; i < len; ++i) { 2133cfb853baSMatthew G. Knepley if (tup[i] < max[i] - 1) { 2134cfb853baSMatthew G. Knepley break; 2135cfb853baSMatthew G. Knepley } else { 2136cfb853baSMatthew G. Knepley tup[i] = 0; 2137cfb853baSMatthew G. Knepley } 2138cfb853baSMatthew G. Knepley } 2139cfb853baSMatthew G. Knepley if (i == len) tup[i - 1] = max[i - 1]; 2140cfb853baSMatthew G. Knepley else ++tup[i]; 21413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2142cfb853baSMatthew G. Knepley } 2143cfb853baSMatthew G. Knepley 2144cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[]) 2145cfb853baSMatthew G. Knepley { 21468d2ec52aSSatish Balay PetscInt idx = tup[len - 1]; 2147cfb853baSMatthew G. Knepley 21488d2ec52aSSatish Balay for (PetscInt i = len - 2; i >= 0; --i) { 2149cfb853baSMatthew G. Knepley idx *= max[i]; 2150cfb853baSMatthew G. Knepley idx += tup[i]; 2151cfb853baSMatthew G. Knepley } 2152cfb853baSMatthew G. Knepley return idx; 2153cfb853baSMatthew G. Knepley } 2154cfb853baSMatthew G. Knepley 21558d2ec52aSSatish Balay static void IndexToTuple_Private(PetscInt len, const PetscInt max[], PetscInt idx, PetscInt tup[]) 2156cfb853baSMatthew G. Knepley { 21578d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21588d2ec52aSSatish Balay tup[i] = idx % max[i]; 21598d2ec52aSSatish Balay idx = (idx - tup[i]) / max[i]; 21608d2ec52aSSatish Balay } 21618d2ec52aSSatish Balay } 21628d2ec52aSSatish Balay 21638d2ec52aSSatish Balay static void TupleToRanks_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt tup[], PetscInt ranks[]) 21648d2ec52aSSatish Balay { 21658d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21668d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 21678d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 21688d2ec52aSSatish Balay const PetscInt idx = (tup[i] < 0 ? max[i] + tup[i] : tup[i]) % max[i]; 21698d2ec52aSSatish Balay 21708d2ec52aSSatish Balay if (idx < rem * (div + 1)) ranks[i] = idx / (div + 1); 21718d2ec52aSSatish Balay else ranks[i] = rem + (idx - rem * (div + 1)) / div; 21728d2ec52aSSatish Balay } 21738d2ec52aSSatish Balay } 21748d2ec52aSSatish Balay 21758d2ec52aSSatish Balay static void RanksToSizes_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt ranks[], PetscInt sizes[]) 21768d2ec52aSSatish Balay { 21778d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21788d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 21798d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 21808d2ec52aSSatish Balay 21818d2ec52aSSatish Balay sizes[i] = ranks[i] < rem ? div + 1 : div; 21828d2ec52aSSatish Balay } 21838d2ec52aSSatish Balay } 21848d2ec52aSSatish Balay 21858d2ec52aSSatish Balay /* 21868d2ec52aSSatish 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. 21878d2ec52aSSatish Balay 21888d2ec52aSSatish 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. 21898d2ec52aSSatish Balay 21908d2ec52aSSatish 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. 2191dfe9cfe5SMatthew Knepley 2192dfe9cfe5SMatthew Knepley Parallel Layout: 2193dfe9cfe5SMatthew Knepley 2194dfe9cfe5SMatthew 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. 21958d2ec52aSSatish Balay */ 21968d2ec52aSSatish Balay static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], PetscInt overlap, const DMBoundaryType bd[]) 21978d2ec52aSSatish Balay { 21988d2ec52aSSatish Balay const PetscInt debug = ((DM_Plex *)dm->data)->printAdj; 21998d2ec52aSSatish Balay PetscSF sf; 2200cfb853baSMatthew G. Knepley Vec coordinates; 2201cfb853baSMatthew G. Knepley PetscSection coordSection; 2202cfb853baSMatthew G. Knepley DMLabel cutLabel = NULL; 2203cfb853baSMatthew G. Knepley PetscBool cutMarker = PETSC_FALSE; 2204cfb853baSMatthew G. Knepley PetscBool periodic = PETSC_FALSE; 22058d2ec52aSSatish Balay PetscInt numCells = 1; 22068d2ec52aSSatish Balay PetscInt numVertices = 1; 22078d2ec52aSSatish Balay PetscSFNode *remotes; 2208cfb853baSMatthew G. Knepley PetscScalar *coords; 22098d2ec52aSSatish Balay PetscInt *procs; // The number of processes along each dimension 22108d2ec52aSSatish Balay PetscInt *lrank; // Rank in each dimension, lrank[d] \in [0, procs[d]) 22118d2ec52aSSatish Balay PetscInt *ledges; // The number of edges along each dimension for this process 22128d2ec52aSSatish Balay PetscInt *vstart; // The first vertex along each dimension on this processes 22138d2ec52aSSatish Balay PetscInt *vertices; // The number of vertices along each dimension on this process 22148d2ec52aSSatish Balay PetscInt *rvert; // The global (not local) vertex number along each dimension 22158d2ec52aSSatish Balay PetscInt *rrank; // The rank along each dimension for the process owning rvert[] 22168d2ec52aSSatish Balay PetscInt *rvertices; // The number of vertices along each dimension for the process rrank[] 22178d2ec52aSSatish Balay PetscInt *vert, *vtmp, *supp, cone[2], *leaves; 22188d2ec52aSSatish Balay PetscInt cell = 0, coordSize, Nl = 0, Nl2 = 0; 22198d2ec52aSSatish Balay PetscMPIInt rank, size; 22208d2ec52aSSatish Balay MPI_Comm comm; 2221cfb853baSMatthew G. Knepley 2222cfb853baSMatthew G. Knepley PetscFunctionBegin; 22238d2ec52aSSatish Balay PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 22248d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_rank(comm, &rank)); 22258d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_size(comm, &size)); 2226cfb853baSMatthew G. Knepley PetscCall(DMSetDimension(dm, dim)); 22278d2ec52aSSatish Balay PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 22288d2ec52aSSatish Balay PetscCall(PetscCalloc4(dim, &procs, dim, &lrank, dim, &rrank, 2 * dim, &supp)); 22298d2ec52aSSatish Balay PetscCall(PetscCalloc7(dim, &ledges, dim, &vertices, dim, &rvertices, dim, &vert, dim, &rvert, dim, &vstart, dim, &vtmp)); 2230cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 2231cfb853baSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 22328d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE; 2233cfb853baSMatthew G. Knepley if (periodic && cutMarker) { 2234cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "periodic_cut")); 2235cfb853baSMatthew G. Knepley PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 2236cfb853baSMatthew G. Knepley } 22378d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, comm, PETSC_ERR_SUP, "Hypercubic mesh must be periodic now"); 22388d2ec52aSSatish Balay overlap = overlap == PETSC_DETERMINE ? 1 : overlap; 22398d2ec52aSSatish Balay PetscCheck(overlap >= 1, comm, PETSC_ERR_SUP, "Overlap %" PetscInt_FMT " must be greater than 0", overlap); 22408d2ec52aSSatish Balay if (size > 1) { 22418d2ec52aSSatish Balay PetscInt Npr = 1; 22428d2ec52aSSatish Balay 22438d2ec52aSSatish Balay // Make process grid 22448d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "Process grid:")); 22458d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22468d2ec52aSSatish Balay procs[d] = PetscRintReal(PetscPowReal(size, 1. / dim)); 22478d2ec52aSSatish Balay Npr *= procs[d]; 22488d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, " %" PetscInt_FMT, procs[d])); 22498d2ec52aSSatish Balay } 22508d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "\n")); 22518d2ec52aSSatish Balay PetscCheck(Npr == size, comm, PETSC_ERR_PLIB, "Process grid size %" PetscInt_FMT " != %d comm size", Npr, size); 22528d2ec52aSSatish Balay IndexToTuple_Private(dim, procs, rank, lrank); 22538d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22548d2ec52aSSatish Balay ledges[d] = edges[d] / procs[d] + (edges[d] % procs[d] > lrank[d] ? 1 : 0); 22558d2ec52aSSatish Balay vstart[d] = 0; 22568d2ec52aSSatish Balay for (PetscInt r = 0; r < lrank[d]; ++r) vstart[d] += edges[d] / procs[d] + (edges[d] % procs[d] > r ? 1 : 0); 22578d2ec52aSSatish Balay vstart[d] -= overlap; // For halo 22588d2ec52aSSatish Balay } 22598d2ec52aSSatish Balay } else { 22608d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22618d2ec52aSSatish Balay procs[d] = 1; 22628d2ec52aSSatish Balay ledges[d] = edges[d]; 22638d2ec52aSSatish Balay } 22648d2ec52aSSatish Balay } 22658d2ec52aSSatish Balay // Calculate local patch size 22668d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22678d2ec52aSSatish Balay vertices[d] = ledges[d] + (procs[d] > 1 ? 2 * overlap : 0); 2268cfb853baSMatthew G. Knepley numVertices *= vertices[d]; 2269cfb853baSMatthew G. Knepley } 2270cfb853baSMatthew G. Knepley numCells = numVertices * dim; 2271cfb853baSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 22728d2ec52aSSatish Balay for (PetscInt c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2)); 22738d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim)); 2274cfb853baSMatthew G. Knepley PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */ 2275cfb853baSMatthew G. Knepley /* Build cell cones and vertex supports */ 2276cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "celltype")); 22778d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Topology for rank %d:\n", rank)); 2278cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2279cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells; 2280cfb853baSMatthew G. Knepley PetscInt s = 0; 22818d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2282cfb853baSMatthew G. Knepley 22838d2ec52aSSatish Balay if (debug) { 22848d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 22858d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d])); 22868d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 22878d2ec52aSSatish Balay } 2288cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT)); 22898d2ec52aSSatish Balay // Define edge cones 22908d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22918d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2292cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + 1) % vertices[d]; 2293cfb853baSMatthew G. Knepley cone[0] = vertex; 2294cfb853baSMatthew G. Knepley cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells; 22958d2ec52aSSatish Balay if (debug) { 22968d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ":", cone[1])); 22978d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vtmp[e])); 22988d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 22998d2ec52aSSatish Balay } 2300cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, cell, cone)); 2301cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT)); 23028d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1])); 2303cfb853baSMatthew G. Knepley ++cell; 23048d2ec52aSSatish Balay // Shared vertices are any in the first or last overlap layers 23058d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 2306cfb853baSMatthew G. Knepley } 23078d2ec52aSSatish Balay if (size > 1 && leaf) ++Nl; 23088d2ec52aSSatish Balay // Define vertex supports 23098d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23108d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2311cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + vertices[d] - 1) % vertices[d]; 2312cfb853baSMatthew G. Knepley supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d; 2313cfb853baSMatthew G. Knepley supp[s++] = (vertex - numCells) * dim + d; 2314cfb853baSMatthew G. Knepley PetscCall(DMPlexSetSupport(dm, vertex, supp)); 2315cfb853baSMatthew G. Knepley } 2316cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2317cfb853baSMatthew G. Knepley } 23188d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2319cfb853baSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 23208d2ec52aSSatish Balay // Allocate for SF 23218d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &leaves)); 23228d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &remotes)); 23238d2ec52aSSatish Balay // Build coordinates 2324cfb853baSMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 2325cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(coordSection, 1)); 2326cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 2327cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 23288d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) { 2329cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetDof(coordSection, v, dim)); 2330cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 2331cfb853baSMatthew G. Knepley } 2332cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetUp(coordSection)); 2333cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 23348d2ec52aSSatish Balay PetscCall(VecCreate(comm, &coordinates)); 2335cfb853baSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 2336cfb853baSMatthew G. Knepley PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 2337cfb853baSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinates, dim)); 2338cfb853baSMatthew G. Knepley PetscCall(VecSetType(coordinates, VECSTANDARD)); 2339cfb853baSMatthew G. Knepley PetscCall(VecGetArray(coordinates, &coords)); 23408d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Geometry for rank %d:\n", rank)); 23418d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) vert[d] = 0; 2342cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2343cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert); 23448d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2345cfb853baSMatthew G. Knepley 23468d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23478d2ec52aSSatish Balay coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / edges[d]) * (vert[d] + vstart[d]); 23488d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 23498d2ec52aSSatish Balay } 23508d2ec52aSSatish Balay if (size > 1 && leaf) { 23518d2ec52aSSatish Balay PetscInt rnumCells = 1; 23528d2ec52aSSatish Balay 23538d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) rvert[d] = vert[d] + vstart[d]; 23548d2ec52aSSatish Balay TupleToRanks_Private(dim, edges, procs, rvert, rrank); 23558d2ec52aSSatish Balay leaves[Nl2] = vertex + numCells; 23568d2ec52aSSatish Balay remotes[Nl2].rank = TupleToIndex_Private(dim, procs, rrank); 23578d2ec52aSSatish Balay RanksToSizes_Private(dim, edges, procs, rrank, rvertices); 23588d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23598d2ec52aSSatish Balay rvertices[d] += 2 * overlap; // Add halo 23608d2ec52aSSatish Balay rnumCells *= rvertices[d]; 23618d2ec52aSSatish Balay } 23628d2ec52aSSatish Balay rnumCells *= dim; 23638d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23648d2ec52aSSatish Balay const PetscInt diff = rrank[d] - lrank[d]; 23658d2ec52aSSatish Balay 23668d2ec52aSSatish Balay if (!diff) rvert[d] = vert[d]; // Vertex is local 23678d2ec52aSSatish Balay else if (rvert[d] < 0) rvert[d] = rvertices[d] - 1 + rvert[d]; // Wrap around at the bottom 23688d2ec52aSSatish Balay else if (rvert[d] >= edges[d]) rvert[d] = rvert[d] - edges[d] + 1; // Wrap around at the top 23698d2ec52aSSatish Balay else if (diff == -1) rvert[d] = rvertices[d] - 1 + (vert[d] - overlap); 23708d2ec52aSSatish Balay else if (diff == 1) rvert[d] = (vertices[d] - vert[d] - 1) + overlap; 23718d2ec52aSSatish Balay else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Process distance %" PetscInt_FMT " in direction %" PetscInt_FMT " should not be possible", diff, d); 23728d2ec52aSSatish Balay } 23738d2ec52aSSatish Balay remotes[Nl2].index = TupleToIndex_Private(dim, rvertices, rvert) + rnumCells; 23748d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Shared Vertex %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", leaves[Nl2], remotes[Nl2].rank, remotes[Nl2].index)); 23758d2ec52aSSatish Balay ++Nl2; 23768d2ec52aSSatish Balay } 23778d2ec52aSSatish Balay if (debug) { 23788d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 23798d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d] + vstart[d])); 23808d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %g", (double)PetscRealPart(coords[vertex * dim + d]))); 23818d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 23828d2ec52aSSatish Balay } 2383cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2384cfb853baSMatthew G. Knepley } 23858d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2386cfb853baSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &coords)); 2387cfb853baSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 2388cfb853baSMatthew G. Knepley PetscCall(VecDestroy(&coordinates)); 23898d2ec52aSSatish Balay // Build SF 23908d2ec52aSSatish Balay PetscCheck(Nl == Nl2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Initial number of leaves %" PetscInt_FMT " != %" PetscInt_FMT " final number", Nl, Nl2); 23918d2ec52aSSatish Balay PetscCall(DMGetPointSF(dm, &sf)); 23928d2ec52aSSatish Balay PetscCall(PetscSFSetGraph(sf, numCells + numVertices, Nl, leaves, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 23938d2ec52aSSatish Balay if (debug) PetscCall(PetscSFView(sf, PETSC_VIEWER_STDOUT_WORLD)); 2394cfb853baSMatthew G. Knepley //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper)); 2395cfb853baSMatthew G. Knepley // Attach the extent 2396cfb853baSMatthew G. Knepley { 2397cfb853baSMatthew G. Knepley PetscContainer c; 23988d2ec52aSSatish Balay PetscInt *extent, *lextent; 2399cfb853baSMatthew G. Knepley 2400cfb853baSMatthew G. Knepley PetscCall(PetscMalloc1(dim, &extent)); 24018d2ec52aSSatish Balay PetscCall(PetscMalloc1(dim, &lextent)); 24028d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 24038d2ec52aSSatish Balay extent[d] = edges[d]; 24048d2ec52aSSatish Balay lextent[d] = ledges[d]; 24058d2ec52aSSatish Balay } 2406cfb853baSMatthew G. Knepley PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 240749abdd8aSBarry Smith PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 2408cfb853baSMatthew G. Knepley PetscCall(PetscContainerSetPointer(c, extent)); 2409cfb853baSMatthew G. Knepley PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c)); 2410cfb853baSMatthew G. Knepley PetscCall(PetscContainerDestroy(&c)); 24118d2ec52aSSatish Balay PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 24128d2ec52aSSatish Balay PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 24138d2ec52aSSatish Balay PetscCall(PetscContainerSetPointer(c, lextent)); 24148d2ec52aSSatish Balay PetscCall(PetscObjectCompose((PetscObject)dm, "_lextent", (PetscObject)c)); 24158d2ec52aSSatish Balay PetscCall(PetscContainerDestroy(&c)); 2416cfb853baSMatthew G. Knepley } 24178d2ec52aSSatish Balay PetscCall(PetscFree4(procs, lrank, rrank, supp)); 24188d2ec52aSSatish Balay PetscCall(PetscFree7(ledges, vertices, rvertices, vert, rvert, vstart, vtmp)); 24193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2420cfb853baSMatthew G. Knepley } 2421cfb853baSMatthew G. Knepley 2422cfb853baSMatthew G. Knepley /*@C 2423aaa8cc7dSPierre Jolivet DMPlexCreateHypercubicMesh - Creates a periodic mesh on the tensor product of unit intervals using only vertices and edges. 2424cfb853baSMatthew G. Knepley 2425cfb853baSMatthew G. Knepley Collective 2426cfb853baSMatthew G. Knepley 2427cfb853baSMatthew G. Knepley Input Parameters: 24288d2ec52aSSatish Balay + comm - The communicator for the `DM` object 2429cfb853baSMatthew G. Knepley . dim - The spatial dimension 243020f4b53cSBarry Smith . edges - Number of edges per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 243120f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 24328d2ec52aSSatish Balay . upper - The upper right corner, or `NULL` for (1, 1, 1) 24338d2ec52aSSatish Balay - overlap - The number of vertices in each direction to include in the overlap (default is 1) 2434cfb853baSMatthew G. Knepley 2435cfb853baSMatthew G. Knepley Output Parameter: 2436cfb853baSMatthew G. Knepley . dm - The DM object 2437cfb853baSMatthew G. Knepley 243820f4b53cSBarry Smith Level: beginner 243920f4b53cSBarry Smith 244020f4b53cSBarry Smith Note: 244120f4b53cSBarry Smith If you want to customize this mesh using options, you just need to 244220f4b53cSBarry Smith .vb 244320f4b53cSBarry Smith DMCreate(comm, &dm); 244420f4b53cSBarry Smith DMSetType(dm, DMPLEX); 244520f4b53cSBarry Smith DMSetFromOptions(dm); 244620f4b53cSBarry Smith .ve 244720f4b53cSBarry Smith and use the options on the `DMSetFromOptions()` page. 2448cfb853baSMatthew G. Knepley 2449cfb853baSMatthew G. Knepley The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively, 245020f4b53cSBarry Smith .vb 245120f4b53cSBarry Smith 18--0-19--2-20--4-18 245220f4b53cSBarry Smith | | | | 245320f4b53cSBarry Smith 13 15 17 13 245420f4b53cSBarry Smith | | | | 245520f4b53cSBarry Smith 24-12-25-14-26-16-24 245620f4b53cSBarry Smith | | | | 245720f4b53cSBarry Smith 7 9 11 7 245820f4b53cSBarry Smith | | | | 245920f4b53cSBarry Smith 21--6-22--8-23-10-21 246020f4b53cSBarry Smith | | | | 246120f4b53cSBarry Smith 1 3 5 1 246220f4b53cSBarry Smith | | | | 246320f4b53cSBarry Smith 18--0-19--2-20--4-18 246420f4b53cSBarry Smith .ve 2465cfb853baSMatthew G. Knepley 246676fbde31SPierre Jolivet .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 2467cfb853baSMatthew G. Knepley @*/ 24688d2ec52aSSatish Balay PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], PetscInt overlap, DM *dm) 2469cfb853baSMatthew G. Knepley { 2470cfb853baSMatthew G. Knepley PetscInt *edg; 2471cfb853baSMatthew G. Knepley PetscReal *low, *upp; 2472cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 2473cfb853baSMatthew G. Knepley PetscInt d; 2474cfb853baSMatthew G. Knepley 2475cfb853baSMatthew G. Knepley PetscFunctionBegin; 2476cfb853baSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 2477cfb853baSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 2478cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt)); 2479cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 2480cfb853baSMatthew G. Knepley edg[d] = edges ? edges[d] : 1; 2481cfb853baSMatthew G. Knepley low[d] = lower ? lower[d] : 0.; 2482cfb853baSMatthew G. Knepley upp[d] = upper ? upper[d] : 1.; 2483cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 2484cfb853baSMatthew G. Knepley } 24858d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, overlap, bdt)); 2486cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edg, low, upp, bdt)); 24873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2488cfb853baSMatthew G. Knepley } 2489cfb853baSMatthew G. Knepley 2490cc4c1da9SBarry Smith /*@ 2491a1cb98faSBarry Smith DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database. 2492a9074c1eSMatthew G. Knepley 249320f4b53cSBarry Smith Logically Collective 2494a9074c1eSMatthew G. Knepley 2495a9074c1eSMatthew G. Knepley Input Parameters: 249620f4b53cSBarry Smith + dm - the `DM` context 2497a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 2498a9074c1eSMatthew G. Knepley 2499a1cb98faSBarry Smith Level: advanced 2500a1cb98faSBarry Smith 2501a1cb98faSBarry Smith Note: 2502a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 2503a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 2504a9074c1eSMatthew G. Knepley 25051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()` 2506a9074c1eSMatthew G. Knepley @*/ 2507d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 2508d71ae5a4SJacob Faibussowitsch { 2509a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2510a9074c1eSMatthew G. Knepley 2511a9074c1eSMatthew G. Knepley PetscFunctionBegin; 2512a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25139566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 25149566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 25153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2516a9074c1eSMatthew G. Knepley } 2517a9074c1eSMatthew G. Knepley 25189318fe57SMatthew G. Knepley /* Remap geometry to cylinder 251961a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 252061a622f3SMatthew G. Knepley 25219318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 25229318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 25239318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 25240510c589SMatthew G. Knepley 25259318fe57SMatthew G. Knepley phi = arctan(y/x) 25269318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 25279318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 25280510c589SMatthew G. Knepley 25299318fe57SMatthew G. Knepley so we remap them using 25300510c589SMatthew G. Knepley 25319318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 25329318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 25330510c589SMatthew G. Knepley 25349318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 25359318fe57SMatthew G. Knepley */ 2536d71ae5a4SJacob 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[]) 2537d71ae5a4SJacob Faibussowitsch { 25389318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 25399318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 254022cc497dSMatthew G. Knepley 25419318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 25429318fe57SMatthew G. Knepley f0[0] = u[0]; 25439318fe57SMatthew G. Knepley f0[1] = u[1]; 25449318fe57SMatthew G. Knepley } else { 25459318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 25460510c589SMatthew G. Knepley 25479318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 25489318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 25499318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 25509318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 25519318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 25529318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 25539318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 25549318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 25559318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 25569318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 25579318fe57SMatthew G. Knepley } else { 25589318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 25599318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 25609318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 25619318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 25629318fe57SMatthew G. Knepley } 25639318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 25649318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 25659318fe57SMatthew G. Knepley } 25669318fe57SMatthew G. Knepley f0[2] = u[2]; 25679318fe57SMatthew G. Knepley } 25680510c589SMatthew G. Knepley 256949704ca5SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ, PetscInt Nr) 2570d71ae5a4SJacob Faibussowitsch { 25710510c589SMatthew G. Knepley const PetscInt dim = 3; 25729318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 2573d8c47e87SMatthew G. Knepley PetscMPIInt rank; 25740510c589SMatthew G. Knepley 25750510c589SMatthew G. Knepley PetscFunctionBegin; 257646139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 25779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 25789566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 25790510c589SMatthew G. Knepley /* Create topology */ 25800510c589SMatthew G. Knepley { 25810510c589SMatthew G. Knepley PetscInt cone[8], c; 25820510c589SMatthew G. Knepley 2583dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 2584dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 2585006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 2586ae8bcbbbSMatthew G. Knepley numCells *= 3; 2587dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 2588006a8963SMatthew G. Knepley } 25899566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 25909566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 25919566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 2592dd400576SPatrick Sanan if (rank == 0) { 2593006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 25949371c9d4SSatish Balay cone[0] = 15; 25959371c9d4SSatish Balay cone[1] = 18; 25969371c9d4SSatish Balay cone[2] = 17; 25979371c9d4SSatish Balay cone[3] = 16; 25989371c9d4SSatish Balay cone[4] = 31; 25999371c9d4SSatish Balay cone[5] = 32; 26009371c9d4SSatish Balay cone[6] = 33; 26019371c9d4SSatish Balay cone[7] = 34; 26029566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 26039371c9d4SSatish Balay cone[0] = 16; 26049371c9d4SSatish Balay cone[1] = 17; 26059371c9d4SSatish Balay cone[2] = 24; 26069371c9d4SSatish Balay cone[3] = 23; 26079371c9d4SSatish Balay cone[4] = 32; 26089371c9d4SSatish Balay cone[5] = 36; 26099371c9d4SSatish Balay cone[6] = 37; 26109371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 26119566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 26129371c9d4SSatish Balay cone[0] = 18; 26139371c9d4SSatish Balay cone[1] = 27; 26149371c9d4SSatish Balay cone[2] = 24; 26159371c9d4SSatish Balay cone[3] = 17; 26169371c9d4SSatish Balay cone[4] = 34; 26179371c9d4SSatish Balay cone[5] = 33; 26189371c9d4SSatish Balay cone[6] = 37; 26199371c9d4SSatish Balay cone[7] = 38; 26209566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 26219371c9d4SSatish Balay cone[0] = 29; 26229371c9d4SSatish Balay cone[1] = 27; 26239371c9d4SSatish Balay cone[2] = 18; 26249371c9d4SSatish Balay cone[3] = 15; 26259371c9d4SSatish Balay cone[4] = 35; 26269371c9d4SSatish Balay cone[5] = 31; 26279371c9d4SSatish Balay cone[6] = 34; 26289371c9d4SSatish Balay cone[7] = 38; 26299566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 26309371c9d4SSatish Balay cone[0] = 29; 26319371c9d4SSatish Balay cone[1] = 15; 26329371c9d4SSatish Balay cone[2] = 16; 26339371c9d4SSatish Balay cone[3] = 23; 26349371c9d4SSatish Balay cone[4] = 35; 26359371c9d4SSatish Balay cone[5] = 36; 26369371c9d4SSatish Balay cone[6] = 32; 26379371c9d4SSatish Balay cone[7] = 31; 26389566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2639006a8963SMatthew G. Knepley 26409371c9d4SSatish Balay cone[0] = 31; 26419371c9d4SSatish Balay cone[1] = 34; 26429371c9d4SSatish Balay cone[2] = 33; 26439371c9d4SSatish Balay cone[3] = 32; 26449371c9d4SSatish Balay cone[4] = 19; 26459371c9d4SSatish Balay cone[5] = 22; 26469371c9d4SSatish Balay cone[6] = 21; 26479371c9d4SSatish Balay cone[7] = 20; 26489566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 26499371c9d4SSatish Balay cone[0] = 32; 26509371c9d4SSatish Balay cone[1] = 33; 26519371c9d4SSatish Balay cone[2] = 37; 26529371c9d4SSatish Balay cone[3] = 36; 26539371c9d4SSatish Balay cone[4] = 22; 26549371c9d4SSatish Balay cone[5] = 25; 26559371c9d4SSatish Balay cone[6] = 26; 26569371c9d4SSatish Balay cone[7] = 21; 26579566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 26589371c9d4SSatish Balay cone[0] = 34; 26599371c9d4SSatish Balay cone[1] = 38; 26609371c9d4SSatish Balay cone[2] = 37; 26619371c9d4SSatish Balay cone[3] = 33; 26629371c9d4SSatish Balay cone[4] = 20; 26639371c9d4SSatish Balay cone[5] = 21; 26649371c9d4SSatish Balay cone[6] = 26; 26659371c9d4SSatish Balay cone[7] = 28; 26669566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 26679371c9d4SSatish Balay cone[0] = 35; 26689371c9d4SSatish Balay cone[1] = 38; 26699371c9d4SSatish Balay cone[2] = 34; 26709371c9d4SSatish Balay cone[3] = 31; 26719371c9d4SSatish Balay cone[4] = 30; 26729371c9d4SSatish Balay cone[5] = 19; 26739371c9d4SSatish Balay cone[6] = 20; 26749371c9d4SSatish Balay cone[7] = 28; 26759566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 26769371c9d4SSatish Balay cone[0] = 35; 26779371c9d4SSatish Balay cone[1] = 31; 26789371c9d4SSatish Balay cone[2] = 32; 26799371c9d4SSatish Balay cone[3] = 36; 26809371c9d4SSatish Balay cone[4] = 30; 26819371c9d4SSatish Balay cone[5] = 25; 26829371c9d4SSatish Balay cone[6] = 22; 26839371c9d4SSatish Balay cone[7] = 19; 26849566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 2685ae8bcbbbSMatthew G. Knepley 26869371c9d4SSatish Balay cone[0] = 19; 26879371c9d4SSatish Balay cone[1] = 20; 26889371c9d4SSatish Balay cone[2] = 21; 26899371c9d4SSatish Balay cone[3] = 22; 26909371c9d4SSatish Balay cone[4] = 15; 26919371c9d4SSatish Balay cone[5] = 16; 26929371c9d4SSatish Balay cone[6] = 17; 26939371c9d4SSatish Balay cone[7] = 18; 26949566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 26959371c9d4SSatish Balay cone[0] = 22; 26969371c9d4SSatish Balay cone[1] = 21; 26979371c9d4SSatish Balay cone[2] = 26; 26989371c9d4SSatish Balay cone[3] = 25; 26999371c9d4SSatish Balay cone[4] = 16; 27009371c9d4SSatish Balay cone[5] = 23; 27019371c9d4SSatish Balay cone[6] = 24; 27029371c9d4SSatish Balay cone[7] = 17; 27039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 27049371c9d4SSatish Balay cone[0] = 20; 27059371c9d4SSatish Balay cone[1] = 28; 27069371c9d4SSatish Balay cone[2] = 26; 27079371c9d4SSatish Balay cone[3] = 21; 27089371c9d4SSatish Balay cone[4] = 18; 27099371c9d4SSatish Balay cone[5] = 17; 27109371c9d4SSatish Balay cone[6] = 24; 27119371c9d4SSatish Balay cone[7] = 27; 27129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 27139371c9d4SSatish Balay cone[0] = 30; 27149371c9d4SSatish Balay cone[1] = 28; 27159371c9d4SSatish Balay cone[2] = 20; 27169371c9d4SSatish Balay cone[3] = 19; 27179371c9d4SSatish Balay cone[4] = 29; 27189371c9d4SSatish Balay cone[5] = 15; 27199371c9d4SSatish Balay cone[6] = 18; 27209371c9d4SSatish Balay cone[7] = 27; 27219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 27229371c9d4SSatish Balay cone[0] = 30; 27239371c9d4SSatish Balay cone[1] = 19; 27249371c9d4SSatish Balay cone[2] = 22; 27259371c9d4SSatish Balay cone[3] = 25; 27269371c9d4SSatish Balay cone[4] = 29; 27279371c9d4SSatish Balay cone[5] = 23; 27289371c9d4SSatish Balay cone[6] = 16; 27299371c9d4SSatish Balay cone[7] = 15; 27309566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 2731006a8963SMatthew G. Knepley } else { 27329371c9d4SSatish Balay cone[0] = 5; 27339371c9d4SSatish Balay cone[1] = 8; 27349371c9d4SSatish Balay cone[2] = 7; 27359371c9d4SSatish Balay cone[3] = 6; 27369371c9d4SSatish Balay cone[4] = 9; 27379371c9d4SSatish Balay cone[5] = 12; 27389371c9d4SSatish Balay cone[6] = 11; 27399371c9d4SSatish Balay cone[7] = 10; 27409566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 27419371c9d4SSatish Balay cone[0] = 6; 27429371c9d4SSatish Balay cone[1] = 7; 27439371c9d4SSatish Balay cone[2] = 14; 27449371c9d4SSatish Balay cone[3] = 13; 27459371c9d4SSatish Balay cone[4] = 12; 27469371c9d4SSatish Balay cone[5] = 15; 27479371c9d4SSatish Balay cone[6] = 16; 27489371c9d4SSatish Balay cone[7] = 11; 27499566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 27509371c9d4SSatish Balay cone[0] = 8; 27519371c9d4SSatish Balay cone[1] = 17; 27529371c9d4SSatish Balay cone[2] = 14; 27539371c9d4SSatish Balay cone[3] = 7; 27549371c9d4SSatish Balay cone[4] = 10; 27559371c9d4SSatish Balay cone[5] = 11; 27569371c9d4SSatish Balay cone[6] = 16; 27579371c9d4SSatish Balay cone[7] = 18; 27589566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 27599371c9d4SSatish Balay cone[0] = 19; 27609371c9d4SSatish Balay cone[1] = 17; 27619371c9d4SSatish Balay cone[2] = 8; 27629371c9d4SSatish Balay cone[3] = 5; 27639371c9d4SSatish Balay cone[4] = 20; 27649371c9d4SSatish Balay cone[5] = 9; 27659371c9d4SSatish Balay cone[6] = 10; 27669371c9d4SSatish Balay cone[7] = 18; 27679566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 27689371c9d4SSatish Balay cone[0] = 19; 27699371c9d4SSatish Balay cone[1] = 5; 27709371c9d4SSatish Balay cone[2] = 6; 27719371c9d4SSatish Balay cone[3] = 13; 27729371c9d4SSatish Balay cone[4] = 20; 27739371c9d4SSatish Balay cone[5] = 15; 27749371c9d4SSatish Balay cone[6] = 12; 27759371c9d4SSatish Balay cone[7] = 9; 27769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2777006a8963SMatthew G. Knepley } 2778d8c47e87SMatthew G. Knepley } 27799566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 27809566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 27810510c589SMatthew G. Knepley } 2782dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 27830510c589SMatthew G. Knepley { 27840510c589SMatthew G. Knepley Vec coordinates; 27850510c589SMatthew G. Knepley PetscSection coordSection; 27860510c589SMatthew G. Knepley PetscScalar *coords; 27870510c589SMatthew G. Knepley PetscInt coordSize, v; 27880510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 27890510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 27900510c589SMatthew G. Knepley 27910510c589SMatthew G. Knepley /* Build coordinates */ 27929566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 27939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 27949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 27959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 27960510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 27979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 27989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 27990510c589SMatthew G. Knepley } 28009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 28019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 28029566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 28039566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 28049566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 28059566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 28069566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 28079566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 2808dd400576SPatrick Sanan if (rank == 0) { 28099371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 28109371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 28119371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 28129371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 28139371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 28149371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 28159371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 28169371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 28179371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 28189371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 28199371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 28209371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 28219371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 28229371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 28239371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 28249371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 28259371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 28269371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 28279371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 28289371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 28299371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 28309371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 28319371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 28329371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 28339371c9d4SSatish Balay coords[8 * dim + 0] = dis; 28349371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 28359371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 28369371c9d4SSatish Balay coords[9 * dim + 0] = dis; 28379371c9d4SSatish Balay coords[9 * dim + 1] = dis; 28389371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 28399371c9d4SSatish Balay coords[10 * dim + 0] = dis; 28409371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 28419371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 28429371c9d4SSatish Balay coords[11 * dim + 0] = dis; 28439371c9d4SSatish Balay coords[11 * dim + 1] = dis; 28449371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 28459371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 28469371c9d4SSatish Balay coords[12 * dim + 1] = dis; 28479371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 28489371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 28499371c9d4SSatish Balay coords[13 * dim + 1] = dis; 28509371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 28519371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 28529371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 28539371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 28549371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 28559371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 28569371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 2857ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 28589371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 28599371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 28609371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 28619371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 28629371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 28639371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 28649371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 28659371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 28669371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 28679371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 28689371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 28699371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 28709371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 28719371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 28729371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 28739371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 28749371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 28759371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 28769371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 28779371c9d4SSatish Balay coords[22 * dim + 1] = dis; 28789371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 28799371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 28809371c9d4SSatish Balay coords[23 * dim + 1] = dis; 28819371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 2882ae8bcbbbSMatthew G. Knepley } 2883d8c47e87SMatthew G. Knepley } 28849566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 28859566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 28869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 28870510c589SMatthew G. Knepley } 2888006a8963SMatthew G. Knepley /* Create periodicity */ 2889006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 28906858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 28916858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 2892006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 2893ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 28946858538eSMatthew G. Knepley PetscInt numZCells = 3; 2895006a8963SMatthew G. Knepley 28966858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 28976858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 28984fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 2899006a8963SMatthew G. Knepley } 2900dbc1dc17SMatthew G. Knepley { 29019318fe57SMatthew G. Knepley DM cdm; 29029318fe57SMatthew G. Knepley PetscDS cds; 29039318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 2904dbc1dc17SMatthew G. Knepley 290549704ca5SMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL)); 29069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 29079566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 29089566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 2909dbc1dc17SMatthew G. Knepley } 291046139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 291146139095SJed Brown 29129318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 29139566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 291449704ca5SMatthew G. Knepley 291549704ca5SMatthew G. Knepley char oldprefix[PETSC_MAX_PATH_LEN]; 291649704ca5SMatthew G. Knepley const char *prefix; 291749704ca5SMatthew G. Knepley 291849704ca5SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 291949704ca5SMatthew G. Knepley PetscCall(PetscStrncpy(oldprefix, prefix, PETSC_MAX_PATH_LEN)); 292049704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, "petsc_cyl_ref_")); 292149704ca5SMatthew G. Knepley for (PetscInt r = 0; r < PetscMax(0, Nr); ++r) { 292249704ca5SMatthew G. Knepley DM rdm; 292349704ca5SMatthew G. Knepley 292449704ca5SMatthew G. Knepley PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 292549704ca5SMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &rdm)); 292649704ca5SMatthew G. Knepley } 292749704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldprefix)); 292849704ca5SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, snapToCylinder)); 292949704ca5SMatthew G. Knepley 293049704ca5SMatthew G. Knepley DMLabel bdlabel, edgelabel; 293149704ca5SMatthew G. Knepley IS faceIS; 293249704ca5SMatthew G. Knepley const PetscInt *faces; 293349704ca5SMatthew G. Knepley PetscInt Nf; 293449704ca5SMatthew G. Knepley 293549704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 293649704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 293749704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "generatrix")); 293849704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "generatrix", &edgelabel)); 293949704ca5SMatthew G. Knepley PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 294049704ca5SMatthew G. Knepley // Remove faces on top and bottom 294149704ca5SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(bdlabel, 1, &faceIS)); 2942ba1b3593SJeremy L Thompson if (faceIS) { 294349704ca5SMatthew G. Knepley PetscCall(ISGetLocalSize(faceIS, &Nf)); 294449704ca5SMatthew G. Knepley PetscCall(ISGetIndices(faceIS, &faces)); 294549704ca5SMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 294649704ca5SMatthew G. Knepley PetscReal vol, normal[3]; 294749704ca5SMatthew G. Knepley 294849704ca5SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFVM(dm, faces[f], &vol, NULL, normal)); 294949704ca5SMatthew G. Knepley if (PetscAbsReal(normal[2]) < PETSC_SMALL) PetscCall(DMLabelSetValue(edgelabel, faces[f], 1)); 295049704ca5SMatthew G. Knepley } 295149704ca5SMatthew G. Knepley PetscCall(ISRestoreIndices(faceIS, &faces)); 295249704ca5SMatthew G. Knepley PetscCall(ISDestroy(&faceIS)); 2953ba1b3593SJeremy L Thompson } 295449704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, bdlabel)); 295549704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, edgelabel)); 29563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29570510c589SMatthew G. Knepley } 29580510c589SMatthew G. Knepley 295924119c2aSMatthew G. Knepley /*@ 29609318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 296124119c2aSMatthew G. Knepley 2962d083f849SBarry Smith Collective 296324119c2aSMatthew G. Knepley 296424119c2aSMatthew G. Knepley Input Parameters: 2965a1cb98faSBarry Smith + comm - The communicator for the `DM` object 296649704ca5SMatthew G. Knepley . periodicZ - The boundary type for the Z direction 296749704ca5SMatthew G. Knepley - Nr - The number of refinements to carry out 296824119c2aSMatthew G. Knepley 296924119c2aSMatthew G. Knepley Output Parameter: 297020f4b53cSBarry Smith . dm - The `DM` object 297124119c2aSMatthew G. Knepley 297224119c2aSMatthew G. Knepley Level: beginner 297324119c2aSMatthew G. Knepley 2974a1cb98faSBarry Smith Note: 2975a4e35b19SJacob Faibussowitsch Here is the output numbering looking from the bottom of the cylinder\: 2976a1cb98faSBarry Smith .vb 2977a1cb98faSBarry Smith 17-----14 2978a1cb98faSBarry Smith | | 2979a1cb98faSBarry Smith | 2 | 2980a1cb98faSBarry Smith | | 2981a1cb98faSBarry Smith 17-----8-----7-----14 2982a1cb98faSBarry Smith | | | | 2983a1cb98faSBarry Smith | 3 | 0 | 1 | 2984a1cb98faSBarry Smith | | | | 2985a1cb98faSBarry Smith 19-----5-----6-----13 2986a1cb98faSBarry Smith | | 2987a1cb98faSBarry Smith | 4 | 2988a1cb98faSBarry Smith | | 2989a1cb98faSBarry Smith 19-----13 2990a1cb98faSBarry Smith 2991a1cb98faSBarry Smith and up through the top 2992a1cb98faSBarry Smith 2993a1cb98faSBarry Smith 18-----16 2994a1cb98faSBarry Smith | | 2995a1cb98faSBarry Smith | 2 | 2996a1cb98faSBarry Smith | | 2997a1cb98faSBarry Smith 18----10----11-----16 2998a1cb98faSBarry Smith | | | | 2999a1cb98faSBarry Smith | 3 | 0 | 1 | 3000a1cb98faSBarry Smith | | | | 3001a1cb98faSBarry Smith 20-----9----12-----15 3002a1cb98faSBarry Smith | | 3003a1cb98faSBarry Smith | 4 | 3004a1cb98faSBarry Smith | | 3005a1cb98faSBarry Smith 20-----15 3006a1cb98faSBarry Smith .ve 3007a1cb98faSBarry Smith 30081cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 300924119c2aSMatthew G. Knepley @*/ 301049704ca5SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, PetscInt Nr, DM *dm) 3011d71ae5a4SJacob Faibussowitsch { 30129318fe57SMatthew G. Knepley PetscFunctionBegin; 301349704ca5SMatthew G. Knepley PetscAssertPointer(dm, 4); 30149566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 30159566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 301649704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ, Nr)); 30173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30189318fe57SMatthew G. Knepley } 30199318fe57SMatthew G. Knepley 3020d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 3021d71ae5a4SJacob Faibussowitsch { 302224119c2aSMatthew G. Knepley const PetscInt dim = 3; 3023412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 30249fe9f049SMatthew G. Knepley PetscMPIInt rank; 302524119c2aSMatthew G. Knepley 302624119c2aSMatthew G. Knepley PetscFunctionBegin; 302763a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 302846139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 30299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 30309566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 3031412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 30329566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 303324119c2aSMatthew G. Knepley /* Create topology */ 303424119c2aSMatthew G. Knepley { 303524119c2aSMatthew G. Knepley PetscInt cone[6], c; 303624119c2aSMatthew G. Knepley 3037dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 3038dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 30399566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 30409566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 30419566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 304224119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 30439371c9d4SSatish Balay cone[0] = c + n * 1; 30449371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 30459371c9d4SSatish Balay cone[2] = 0 + 3 * n; 30469371c9d4SSatish Balay cone[3] = c + n * 2; 30479371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 30489371c9d4SSatish Balay cone[5] = 1 + 3 * n; 30499566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 30509566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 305124119c2aSMatthew G. Knepley } 30529566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 30539566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 305424119c2aSMatthew G. Knepley } 305548a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 305624119c2aSMatthew G. Knepley /* Create cylinder geometry */ 305724119c2aSMatthew G. Knepley { 305824119c2aSMatthew G. Knepley Vec coordinates; 305924119c2aSMatthew G. Knepley PetscSection coordSection; 306024119c2aSMatthew G. Knepley PetscScalar *coords; 3061412e9a14SMatthew G. Knepley PetscInt coordSize, c; 306224119c2aSMatthew G. Knepley 306324119c2aSMatthew G. Knepley /* Build coordinates */ 30649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 30659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 30669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 30679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 306824119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 30699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 30709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 307124119c2aSMatthew G. Knepley } 30729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 30739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 30749566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 30759566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 30769566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 30779566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 30789566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 30799566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 308024119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 30819371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 30829371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 30839371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 30849371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 30859371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 30869371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 308724119c2aSMatthew G. Knepley } 3088dd400576SPatrick Sanan if (rank == 0) { 30899371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 30909371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 30919371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 30929371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 30939371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 30949371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 30959fe9f049SMatthew G. Knepley } 30969566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 30979566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 30989566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 309924119c2aSMatthew G. Knepley } 310046139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 31019318fe57SMatthew G. Knepley /* Interpolate */ 31029566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 31033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31049318fe57SMatthew G. Knepley } 31059318fe57SMatthew G. Knepley 31069318fe57SMatthew G. Knepley /*@ 31079318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 31089318fe57SMatthew G. Knepley 31099318fe57SMatthew G. Knepley Collective 31109318fe57SMatthew G. Knepley 31119318fe57SMatthew G. Knepley Input Parameters: 3112a1cb98faSBarry Smith + comm - The communicator for the `DM` object 31139318fe57SMatthew G. Knepley . n - The number of wedges around the origin 31149318fe57SMatthew G. Knepley - interpolate - Create edges and faces 31159318fe57SMatthew G. Knepley 31169318fe57SMatthew G. Knepley Output Parameter: 3117a1cb98faSBarry Smith . dm - The `DM` object 31189318fe57SMatthew G. Knepley 31199318fe57SMatthew G. Knepley Level: beginner 31209318fe57SMatthew G. Knepley 31211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 31229318fe57SMatthew G. Knepley @*/ 3123d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 3124d71ae5a4SJacob Faibussowitsch { 31259318fe57SMatthew G. Knepley PetscFunctionBegin; 31264f572ea9SToby Isaac PetscAssertPointer(dm, 4); 31279566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 31289566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 31299566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 31303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 313124119c2aSMatthew G. Knepley } 313224119c2aSMatthew G. Knepley 3133d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 3134d71ae5a4SJacob Faibussowitsch { 313565a81367SMatthew G. Knepley PetscReal prod = 0.0; 313665a81367SMatthew G. Knepley PetscInt i; 313765a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 313865a81367SMatthew G. Knepley return PetscSqrtReal(prod); 313965a81367SMatthew G. Knepley } 3140dd2b43ebSStefano Zampini 3141d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 3142d71ae5a4SJacob Faibussowitsch { 314365a81367SMatthew G. Knepley PetscReal prod = 0.0; 314465a81367SMatthew G. Knepley PetscInt i; 314565a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += x[i] * y[i]; 314665a81367SMatthew G. Knepley return prod; 314765a81367SMatthew G. Knepley } 314865a81367SMatthew G. Knepley 314951a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 3150d71ae5a4SJacob 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[]) 3151d71ae5a4SJacob Faibussowitsch { 315251a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 315351a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 315451a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 315551a74b61SMatthew G. Knepley 315651a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 315751a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 315851a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 315951a74b61SMatthew G. Knepley } 316051a74b61SMatthew G. Knepley 3161d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 3162d71ae5a4SJacob Faibussowitsch { 316365a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 316465a81367SMatthew G. Knepley PetscSection coordSection; 316565a81367SMatthew G. Knepley Vec coordinates; 316665a81367SMatthew G. Knepley PetscScalar *coords; 316765a81367SMatthew G. Knepley PetscReal *coordsIn; 316807c565c5SJose E. Roman PetscInt numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, e; 316965a81367SMatthew G. Knepley PetscMPIInt rank; 317065a81367SMatthew G. Knepley 317165a81367SMatthew G. Knepley PetscFunctionBegin; 31729318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 317346139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 31749566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 31759566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 31769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 317765a81367SMatthew G. Knepley switch (dim) { 31785c344501SMatthew G. Knepley case 1: 31795c344501SMatthew G. Knepley numCells = 16; 31805c344501SMatthew G. Knepley numVerts = numCells; 31815c344501SMatthew G. Knepley 31825c344501SMatthew G. Knepley // Build Topology 31835c344501SMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 31845c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 31855c344501SMatthew G. Knepley PetscCall(DMSetUp(dm)); 31865c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 31875c344501SMatthew G. Knepley PetscInt cone[2]; 31885c344501SMatthew G. Knepley 31895c344501SMatthew G. Knepley cone[0] = c + numCells; 31905c344501SMatthew G. Knepley cone[1] = (c + 1) % numVerts + numCells; 31915c344501SMatthew G. Knepley PetscCall(DMPlexSetCone(dm, c, cone)); 31925c344501SMatthew G. Knepley } 31935c344501SMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 31945c344501SMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 31955c344501SMatthew G. Knepley PetscCall(PetscMalloc1(numVerts * embedDim, &coordsIn)); 31965c344501SMatthew G. Knepley for (PetscInt v = 0; v < numVerts; ++v) { 31975c344501SMatthew G. Knepley const PetscReal rad = 2. * PETSC_PI * v / numVerts; 31985c344501SMatthew G. Knepley 31995c344501SMatthew G. Knepley coordsIn[v * embedDim + 0] = PetscCosReal(rad); 32005c344501SMatthew G. Knepley coordsIn[v * embedDim + 1] = PetscSinReal(rad); 32015c344501SMatthew G. Knepley } 32025c344501SMatthew G. Knepley break; 320365a81367SMatthew G. Knepley case 2: 320465a81367SMatthew G. Knepley if (simplex) { 320551a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 320651a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 320765a81367SMatthew G. Knepley const PetscInt degree = 5; 320851a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 320965a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 321065a81367SMatthew G. Knepley PetscInt cone[3]; 321107c565c5SJose E. Roman PetscInt *graph; 321265a81367SMatthew G. Knepley 32139371c9d4SSatish Balay vertex[0] *= R / radius; 32149371c9d4SSatish Balay vertex[1] *= R / radius; 32159371c9d4SSatish Balay vertex[2] *= R / radius; 3216dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 3217dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 321865a81367SMatthew G. Knepley firstVertex = numCells; 321951a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 322065a81367SMatthew G. Knepley 322165a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 322265a81367SMatthew G. Knepley 322365a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 322451a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 322565a81367SMatthew G. Knepley */ 322665a81367SMatthew G. Knepley /* Construct vertices */ 32279566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3228dd400576SPatrick Sanan if (rank == 0) { 322907c565c5SJose E. Roman for (PetscInt p = 0, i = 0; p < embedDim; ++p) { 323065a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 323165a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 323265a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 323365a81367SMatthew G. Knepley ++i; 323465a81367SMatthew G. Knepley } 323565a81367SMatthew G. Knepley } 323665a81367SMatthew G. Knepley } 323745da822fSValeria Barra } 323865a81367SMatthew G. Knepley /* Construct graph */ 32399566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 324007c565c5SJose E. Roman for (PetscInt i = 0; i < numVerts; ++i) { 324107c565c5SJose E. Roman PetscInt k = 0; 324207c565c5SJose E. Roman for (PetscInt j = 0; j < numVerts; ++j) { 32439371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 32449371c9d4SSatish Balay graph[i * numVerts + j] = 1; 32459371c9d4SSatish Balay ++k; 32469371c9d4SSatish Balay } 324765a81367SMatthew G. Knepley } 324863a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 324965a81367SMatthew G. Knepley } 325065a81367SMatthew G. Knepley /* Build Topology */ 32519566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 325207c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 32539566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 325465a81367SMatthew G. Knepley /* Cells */ 325507c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 325607c565c5SJose E. Roman for (PetscInt j = 0; j < i; ++j) { 325707c565c5SJose E. Roman for (PetscInt k = 0; k < j; ++k) { 325865a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 32599371c9d4SSatish Balay cone[0] = firstVertex + i; 32609371c9d4SSatish Balay cone[1] = firstVertex + j; 32619371c9d4SSatish Balay cone[2] = firstVertex + k; 326265a81367SMatthew G. Knepley /* Check orientation */ 326365a81367SMatthew G. Knepley { 32649371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 32659371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 32669371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 32679371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 32689371c9d4SSatish Balay }; 326965a81367SMatthew G. Knepley PetscReal normal[3]; 327065a81367SMatthew G. Knepley PetscInt e, f; 327165a81367SMatthew G. Knepley 327265a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 327365a81367SMatthew G. Knepley normal[d] = 0.0; 327465a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3275ad540459SPierre 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]); 327665a81367SMatthew G. Knepley } 327765a81367SMatthew G. Knepley } 32789371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 32799371c9d4SSatish Balay PetscInt tmp = cone[1]; 32809371c9d4SSatish Balay cone[1] = cone[2]; 32819371c9d4SSatish Balay cone[2] = tmp; 328265a81367SMatthew G. Knepley } 328365a81367SMatthew G. Knepley } 32849566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 328565a81367SMatthew G. Knepley } 328665a81367SMatthew G. Knepley } 328765a81367SMatthew G. Knepley } 328865a81367SMatthew G. Knepley } 32899566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 32909566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 32919566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 329265a81367SMatthew G. Knepley } else { 32932829fed8SMatthew G. Knepley /* 32942829fed8SMatthew G. Knepley 12-21--13 32952829fed8SMatthew G. Knepley | | 32962829fed8SMatthew G. Knepley 25 4 24 32972829fed8SMatthew G. Knepley | | 32982829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 32992829fed8SMatthew G. Knepley | | | | 33002829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 33012829fed8SMatthew G. Knepley | | | | 33022829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 33032829fed8SMatthew G. Knepley | | 33042829fed8SMatthew G. Knepley 20 1 19 33052829fed8SMatthew G. Knepley | | 33062829fed8SMatthew G. Knepley 10-18--11 33072829fed8SMatthew G. Knepley | | 33082829fed8SMatthew G. Knepley 23 2 22 33092829fed8SMatthew G. Knepley | | 33102829fed8SMatthew G. Knepley 12-21--13 33112829fed8SMatthew G. Knepley */ 33122829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 33132829fed8SMatthew G. Knepley 3314dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 3315dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 3316dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 331765a81367SMatthew G. Knepley firstVertex = numCells; 331865a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 33192829fed8SMatthew G. Knepley /* Build Topology */ 33209566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 332107c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 332248a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 33239566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3324dd400576SPatrick Sanan if (rank == 0) { 33252829fed8SMatthew G. Knepley /* Cell 0 */ 33269371c9d4SSatish Balay cone[0] = 14; 33279371c9d4SSatish Balay cone[1] = 15; 33289371c9d4SSatish Balay cone[2] = 16; 33299371c9d4SSatish Balay cone[3] = 17; 33309566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 33319371c9d4SSatish Balay ornt[0] = 0; 33329371c9d4SSatish Balay ornt[1] = 0; 33339371c9d4SSatish Balay ornt[2] = 0; 33349371c9d4SSatish Balay ornt[3] = 0; 33359566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 33362829fed8SMatthew G. Knepley /* Cell 1 */ 33379371c9d4SSatish Balay cone[0] = 18; 33389371c9d4SSatish Balay cone[1] = 19; 33399371c9d4SSatish Balay cone[2] = 14; 33409371c9d4SSatish Balay cone[3] = 20; 33419566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 33429371c9d4SSatish Balay ornt[0] = 0; 33439371c9d4SSatish Balay ornt[1] = 0; 33449371c9d4SSatish Balay ornt[2] = -1; 33459371c9d4SSatish Balay ornt[3] = 0; 33469566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 33472829fed8SMatthew G. Knepley /* Cell 2 */ 33489371c9d4SSatish Balay cone[0] = 21; 33499371c9d4SSatish Balay cone[1] = 22; 33509371c9d4SSatish Balay cone[2] = 18; 33519371c9d4SSatish Balay cone[3] = 23; 33529566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 33539371c9d4SSatish Balay ornt[0] = 0; 33549371c9d4SSatish Balay ornt[1] = 0; 33559371c9d4SSatish Balay ornt[2] = -1; 33569371c9d4SSatish Balay ornt[3] = 0; 33579566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 33582829fed8SMatthew G. Knepley /* Cell 3 */ 33599371c9d4SSatish Balay cone[0] = 19; 33609371c9d4SSatish Balay cone[1] = 22; 33619371c9d4SSatish Balay cone[2] = 24; 33629371c9d4SSatish Balay cone[3] = 15; 33639566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 33649371c9d4SSatish Balay ornt[0] = -1; 33659371c9d4SSatish Balay ornt[1] = -1; 33669371c9d4SSatish Balay ornt[2] = 0; 33679371c9d4SSatish Balay ornt[3] = -1; 33689566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 33692829fed8SMatthew G. Knepley /* Cell 4 */ 33709371c9d4SSatish Balay cone[0] = 16; 33719371c9d4SSatish Balay cone[1] = 24; 33729371c9d4SSatish Balay cone[2] = 21; 33739371c9d4SSatish Balay cone[3] = 25; 33749566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 33759371c9d4SSatish Balay ornt[0] = -1; 33769371c9d4SSatish Balay ornt[1] = -1; 33779371c9d4SSatish Balay ornt[2] = -1; 33789371c9d4SSatish Balay ornt[3] = 0; 33799566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 33802829fed8SMatthew G. Knepley /* Cell 5 */ 33819371c9d4SSatish Balay cone[0] = 20; 33829371c9d4SSatish Balay cone[1] = 17; 33839371c9d4SSatish Balay cone[2] = 25; 33849371c9d4SSatish Balay cone[3] = 23; 33859566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 33869371c9d4SSatish Balay ornt[0] = -1; 33879371c9d4SSatish Balay ornt[1] = -1; 33889371c9d4SSatish Balay ornt[2] = -1; 33899371c9d4SSatish Balay ornt[3] = -1; 33909566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 33912829fed8SMatthew G. Knepley /* Edges */ 33929371c9d4SSatish Balay cone[0] = 6; 33939371c9d4SSatish Balay cone[1] = 7; 33949566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 33959371c9d4SSatish Balay cone[0] = 7; 33969371c9d4SSatish Balay cone[1] = 8; 33979566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 33989371c9d4SSatish Balay cone[0] = 8; 33999371c9d4SSatish Balay cone[1] = 9; 34009566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 34019371c9d4SSatish Balay cone[0] = 9; 34029371c9d4SSatish Balay cone[1] = 6; 34039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 34049371c9d4SSatish Balay cone[0] = 10; 34059371c9d4SSatish Balay cone[1] = 11; 34069566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 34079371c9d4SSatish Balay cone[0] = 11; 34089371c9d4SSatish Balay cone[1] = 7; 34099566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 34109371c9d4SSatish Balay cone[0] = 6; 34119371c9d4SSatish Balay cone[1] = 10; 34129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 34139371c9d4SSatish Balay cone[0] = 12; 34149371c9d4SSatish Balay cone[1] = 13; 34159566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 34169371c9d4SSatish Balay cone[0] = 13; 34179371c9d4SSatish Balay cone[1] = 11; 34189566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 34199371c9d4SSatish Balay cone[0] = 10; 34209371c9d4SSatish Balay cone[1] = 12; 34219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 34229371c9d4SSatish Balay cone[0] = 13; 34239371c9d4SSatish Balay cone[1] = 8; 34249566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 34259371c9d4SSatish Balay cone[0] = 12; 34269371c9d4SSatish Balay cone[1] = 9; 34279566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 342845da822fSValeria Barra } 34299566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 34309566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 34312829fed8SMatthew G. Knepley /* Build coordinates */ 34329566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3433dd400576SPatrick Sanan if (rank == 0) { 34349371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 34359371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 34369371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 34379371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 34389371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 34399371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 34409371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 34419371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 34429371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 34439371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 34449371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 34459371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 34469371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 34479371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 34489371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 34499371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 34509371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 34519371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 34529371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 34539371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 34549371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 34559371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 34569371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 34579371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 345865a81367SMatthew G. Knepley } 345945da822fSValeria Barra } 346065a81367SMatthew G. Knepley break; 346165a81367SMatthew G. Knepley case 3: 3462116ded15SMatthew G. Knepley if (simplex) { 3463116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 346451a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 346551a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 346651a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 3467116ded15SMatthew G. Knepley const PetscInt degree = 12; 3468116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 34699371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 34709371c9d4SSatish Balay {0, 1, 2, 3}, 34719371c9d4SSatish Balay {0, 2, 3, 1}, 34729371c9d4SSatish Balay {0, 3, 1, 2}, 34739371c9d4SSatish Balay {1, 0, 3, 2}, 34749371c9d4SSatish Balay {1, 2, 0, 3}, 34759371c9d4SSatish Balay {1, 3, 2, 0}, 34769371c9d4SSatish Balay {2, 0, 1, 3}, 34779371c9d4SSatish Balay {2, 1, 3, 0}, 34789371c9d4SSatish Balay {2, 3, 0, 1}, 34799371c9d4SSatish Balay {3, 0, 2, 1}, 34809371c9d4SSatish Balay {3, 1, 0, 2}, 34819371c9d4SSatish Balay {3, 2, 1, 0} 34829371c9d4SSatish Balay }; 3483116ded15SMatthew G. Knepley PetscInt cone[4]; 3484116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 3485116ded15SMatthew G. Knepley 34869371c9d4SSatish Balay vertexA[0] *= R; 34879371c9d4SSatish Balay vertexA[1] *= R; 34889371c9d4SSatish Balay vertexA[2] *= R; 34899371c9d4SSatish Balay vertexA[3] *= R; 34909371c9d4SSatish Balay vertexB[0] *= R; 34919371c9d4SSatish Balay vertexB[1] *= R; 34929371c9d4SSatish Balay vertexB[2] *= R; 34939371c9d4SSatish Balay vertexB[3] *= R; 34949371c9d4SSatish Balay vertexC[0] *= R; 34959371c9d4SSatish Balay vertexC[1] *= R; 34969371c9d4SSatish Balay vertexC[2] *= R; 34979371c9d4SSatish Balay vertexC[3] *= R; 3498dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 3499dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 3500116ded15SMatthew G. Knepley firstVertex = numCells; 3501116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 3502116ded15SMatthew G. Knepley 3503116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 3504116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 3505116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 3506116ded15SMatthew G. Knepley 3507116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 35086333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 3509116ded15SMatthew G. Knepley 3510116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 3511116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 3512116ded15SMatthew G. Knepley */ 3513116ded15SMatthew G. Knepley /* Construct vertices */ 35149566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3515116ded15SMatthew G. Knepley i = 0; 3516dd400576SPatrick Sanan if (rank == 0) { 3517116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3518116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3519116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3520116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 3521116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 3522116ded15SMatthew G. Knepley ++i; 3523116ded15SMatthew G. Knepley } 3524116ded15SMatthew G. Knepley } 3525116ded15SMatthew G. Knepley } 3526116ded15SMatthew G. Knepley } 3527116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 3528116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 3529116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3530116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 3531116ded15SMatthew G. Knepley ++i; 3532116ded15SMatthew G. Knepley } 3533116ded15SMatthew G. Knepley } 3534116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 3535116ded15SMatthew G. Knepley s[3] = 1; 3536116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3537116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3538116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3539116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 3540116ded15SMatthew G. Knepley ++i; 3541116ded15SMatthew G. Knepley } 3542116ded15SMatthew G. Knepley } 3543116ded15SMatthew G. Knepley } 3544116ded15SMatthew G. Knepley } 354545da822fSValeria Barra } 354663a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 3547116ded15SMatthew G. Knepley /* Construct graph */ 35489566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 3549116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 3550116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 35519371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 35529371c9d4SSatish Balay graph[i * numVerts + j] = 1; 35539371c9d4SSatish Balay ++k; 35549371c9d4SSatish Balay } 3555116ded15SMatthew G. Knepley } 355663a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 3557116ded15SMatthew G. Knepley } 3558116ded15SMatthew G. Knepley /* Build Topology */ 35599566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 356007c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 35619566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3562116ded15SMatthew G. Knepley /* Cells */ 3563dd400576SPatrick Sanan if (rank == 0) { 356407c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 3565116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 3566116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 3567116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 35689371c9d4SSatish 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]) { 35699371c9d4SSatish Balay cone[0] = firstVertex + i; 35709371c9d4SSatish Balay cone[1] = firstVertex + j; 35719371c9d4SSatish Balay cone[2] = firstVertex + k; 35729371c9d4SSatish Balay cone[3] = firstVertex + l; 3573116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 3574116ded15SMatthew G. Knepley { 35759371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 35769371c9d4SSatish 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}}}, 3577116ded15SMatthew G. Knepley 35789371c9d4SSatish 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}}}, 3579116ded15SMatthew G. Knepley 35809371c9d4SSatish 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}}}, 3581116ded15SMatthew G. Knepley 35829371c9d4SSatish 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}} } 35839371c9d4SSatish Balay }; 3584116ded15SMatthew G. Knepley PetscReal normal[4]; 3585116ded15SMatthew G. Knepley PetscInt e, f, g; 3586116ded15SMatthew G. Knepley 3587116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 3588116ded15SMatthew G. Knepley normal[d] = 0.0; 3589116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3590116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 3591116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 3592116ded15SMatthew 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]); 3593116ded15SMatthew G. Knepley } 3594116ded15SMatthew G. Knepley } 3595116ded15SMatthew G. Knepley } 3596116ded15SMatthew G. Knepley } 35979371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 35989371c9d4SSatish Balay PetscInt tmp = cone[1]; 35999371c9d4SSatish Balay cone[1] = cone[2]; 36009371c9d4SSatish Balay cone[2] = tmp; 36019371c9d4SSatish Balay } 3602116ded15SMatthew G. Knepley } 36039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 3604116ded15SMatthew G. Knepley } 3605116ded15SMatthew G. Knepley } 3606116ded15SMatthew G. Knepley } 3607116ded15SMatthew G. Knepley } 3608116ded15SMatthew G. Knepley } 360945da822fSValeria Barra } 36109566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 36119566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 36129566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 3613116ded15SMatthew G. Knepley } 3614f4d061e9SPierre Jolivet break; 3615d71ae5a4SJacob Faibussowitsch default: 3616d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 361765a81367SMatthew G. Knepley } 361865a81367SMatthew G. Knepley /* Create coordinates */ 36199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 36209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 36219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 36229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 36232829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 36249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 36259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 36262829fed8SMatthew G. Knepley } 36279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 36289566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 36299566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 36309566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 36319566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 36329566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 36339566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 36349566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 36359371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 3636ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 36379566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 36389566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 36399566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 36409566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 364151a74b61SMatthew G. Knepley { 364251a74b61SMatthew G. Knepley DM cdm; 364351a74b61SMatthew G. Knepley PetscDS cds; 36449318fe57SMatthew G. Knepley PetscScalar c = R; 364551a74b61SMatthew G. Knepley 3646e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, snapToSphere)); 36479566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 36489566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 36499566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 365051a74b61SMatthew G. Knepley } 365146139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 36529318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 36539566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 36543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36559318fe57SMatthew G. Knepley } 36569318fe57SMatthew G. Knepley 3657b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 3658b7f5c055SJed Brown 3659b7f5c055SJed Brown /* 3660b7f5c055SJed Brown The Schwarz P implicit surface is 3661b7f5c055SJed Brown 3662b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 3663b7f5c055SJed Brown */ 3664d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3665d71ae5a4SJacob Faibussowitsch { 3666b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 3667b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 3668b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 3669b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3670b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 3671ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 3672b7f5c055SJed Brown } 3673b7f5c055SJed Brown } 3674b7f5c055SJed Brown 36754663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3676d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3677d71ae5a4SJacob Faibussowitsch { 3678ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 36793ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 36804663dae6SJed Brown } 36814663dae6SJed Brown 3682b7f5c055SJed Brown /* 3683b7f5c055SJed Brown The Gyroid implicit surface is 3684b7f5c055SJed Brown 3685b7f5c055SJed 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) 3686b7f5c055SJed Brown 3687b7f5c055SJed Brown */ 3688d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3689d71ae5a4SJacob Faibussowitsch { 3690b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 3691b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 3692b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 3693b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 3694b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 3695b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 3696b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 3697b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3698b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3699b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 3700b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3701b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3702b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 3703b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3704b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3705b7f5c055SJed Brown } 3706b7f5c055SJed Brown 37074663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3708d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3709d71ae5a4SJacob Faibussowitsch { 37104663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 37114663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 37124663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 37134663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 37144663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 37153ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 37164663dae6SJed Brown } 37174663dae6SJed Brown 3718b7f5c055SJed Brown /* 3719b7f5c055SJed Brown We wish to solve 3720b7f5c055SJed Brown 3721b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 3722b7f5c055SJed Brown 3723b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 3724b7f5c055SJed 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 3725b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 3726b7f5c055SJed Brown 3727b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 3728b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 3729b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 3730b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 3731da81f932SPierre Jolivet Since Q is symmetric, this is equivalent to multiplying by Q and taking the last two entries. 3732b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 3733b7f5c055SJed Brown 3734b7f5c055SJed Brown f(y) = 0 1 equation 3735b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 3736b7f5c055SJed Brown 3737b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 3738b7f5c055SJed Brown */ 3739d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 3740d71ae5a4SJacob Faibussowitsch { 3741b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 3742b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 37432f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 37449371c9d4SSatish Balay PetscReal n_y[3][3] = { 37459371c9d4SSatish Balay {0, 0, 0}, 37469371c9d4SSatish Balay {0, 0, 0}, 37479371c9d4SSatish Balay {0, 0, 0} 37489371c9d4SSatish Balay }; 3749b7f5c055SJed Brown 3750b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 3751b7f5c055SJed Brown 3752b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 3753b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3754ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 3755b7f5c055SJed Brown 3756b7f5c055SJed Brown // Define the Householder reflector 3757b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 3758b7f5c055SJed Brown n[0] += norm * sign; 3759b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 3760b7f5c055SJed Brown 3761b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3762b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 3763b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 3764b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 3765b7f5c055SJed Brown 3766b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3767b7f5c055SJed Brown n[i] /= norm; 3768b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3769b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 3770b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 3771b7f5c055SJed Brown } 3772b7f5c055SJed Brown } 3773b7f5c055SJed Brown 3774b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 3775b7f5c055SJed 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]; 3776b7f5c055SJed Brown 3777b7f5c055SJed Brown res[0] = f; 3778b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 3779b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 3780b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 3781b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3782b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 3783b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 3784b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 3785b7f5c055SJed Brown } 3786b7f5c055SJed Brown } 3787b7f5c055SJed Brown 3788b7f5c055SJed Brown /* 3789b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 3790b7f5c055SJed Brown */ 3791d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 3792d71ae5a4SJacob Faibussowitsch { 3793b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 3794b7f5c055SJed Brown 3795b7f5c055SJed Brown PetscFunctionBegin; 3796b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 3797b7f5c055SJed Brown PetscScalar res[3], J[9]; 3798b7f5c055SJed Brown PetscReal resnorm; 3799b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 3800b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 3801b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 380263a3b9bcSJacob 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]))); 3803b7f5c055SJed Brown } 3804b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 3805b7f5c055SJed Brown 3806b7f5c055SJed Brown // Take the Newton step 38079566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 3808b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 3809b7f5c055SJed Brown } 3810b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 38113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3812b7f5c055SJed Brown } 3813b7f5c055SJed Brown 3814b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 3815b7f5c055SJed Brown 3816d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 3817d71ae5a4SJacob Faibussowitsch { 3818b7f5c055SJed Brown PetscMPIInt rank; 3819b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 3820b7f5c055SJed Brown PetscInt (*edges)[2] = NULL, *edgeSets = NULL; 3821b7f5c055SJed Brown PetscInt *cells_flat = NULL; 3822b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 3823b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 38248434afd1SBarry Smith PetscSimplePointFn *normalFunc = NULL; 3825b7f5c055SJed Brown DMLabel label; 3826b7f5c055SJed Brown 3827b7f5c055SJed Brown PetscFunctionBegin; 382846139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 38299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 383063a3b9bcSJacob 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); 3831b7f5c055SJed Brown switch (tpstype) { 3832b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 3833b7f5c055SJed 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"); 3834c5853193SPierre Jolivet if (rank == 0) { 3835b7f5c055SJed Brown PetscInt (*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 3836b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 3837b7f5c055SJed Brown PetscReal L = 1; 3838b7f5c055SJed Brown 3839b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 3840b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 3841b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 3842b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 3843b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 3844b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 38459566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 38469566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 38479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 38489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 3849b7f5c055SJed Brown // x-normal pipes 3850b7f5c055SJed Brown vcount = 0; 3851b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 3852b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3853b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3854b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3855b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 3856b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3857b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3858b7f5c055SJed Brown } 3859b7f5c055SJed Brown } 3860b7f5c055SJed Brown } 3861b7f5c055SJed Brown } 3862b7f5c055SJed Brown // y-normal pipes 3863b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3864b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 3865b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3866b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3867b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3868b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 3869b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3870b7f5c055SJed Brown } 3871b7f5c055SJed Brown } 3872b7f5c055SJed Brown } 3873b7f5c055SJed Brown } 3874b7f5c055SJed Brown // z-normal pipes 3875b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3876b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3877b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 3878b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3879b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3880b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3881b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 3882b7f5c055SJed Brown } 3883b7f5c055SJed Brown } 3884b7f5c055SJed Brown } 3885b7f5c055SJed Brown } 3886b7f5c055SJed Brown // junctions 3887b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3888b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3889b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3890b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 3891b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 3892b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 3893b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 3894b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 3895b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 3896b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 3897b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 3898b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 3899b7f5c055SJed Brown } 3900b7f5c055SJed Brown } 3901b7f5c055SJed Brown } 3902b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 3903b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 3904b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 3905b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 3906b7f5c055SJed Brown }; 3907b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 39089371c9d4SSatish 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}; 3909b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 39109371c9d4SSatish 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}; 3911b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 3912b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 3913b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 3914b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 3915b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 3916b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 3917b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 3918b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 3919b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 3920b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 3921b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 3922b7f5c055SJed Brown if (ijk[dir] == 0) { 3923b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 3924b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 3925b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 3926b7f5c055SJed Brown numEdges++; 3927b7f5c055SJed Brown } 3928b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 3929b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 3930b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 3931b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 3932b7f5c055SJed Brown numEdges++; 3933b7f5c055SJed Brown } 3934b7f5c055SJed Brown } 3935b7f5c055SJed Brown } 3936b7f5c055SJed Brown } 3937b7f5c055SJed Brown } 3938b7f5c055SJed Brown } 393963a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 3940b7f5c055SJed Brown numFaces = 24 * Njunctions; 3941b7f5c055SJed Brown cells_flat = cells[0][0][0]; 3942b7f5c055SJed Brown } 3943b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 39444663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 3945b7f5c055SJed Brown break; 3946b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 3947c5853193SPierre Jolivet if (rank == 0) { 3948b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 3949b7f5c055SJed Brown // 3950b7f5c055SJed 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) 3951b7f5c055SJed Brown // 3952b7f5c055SJed Brown // on the cell [0,2]^3. 3953b7f5c055SJed Brown // 3954b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 3955b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 3956b7f5c055SJed Brown // like a boomerang: 3957b7f5c055SJed Brown // 3958b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 3959b7f5c055SJed Brown // ----- ------- ------- ------- // 3960b7f5c055SJed Brown // // 3961b7f5c055SJed Brown // + + + + + + + \ + // 3962b7f5c055SJed Brown // \ / \ // 3963b7f5c055SJed Brown // \ `-_ _-' / } // 3964b7f5c055SJed Brown // *-_ `-' _-' / // 3965b7f5c055SJed Brown // + `-+ + + +-' + + / + // 3966b7f5c055SJed Brown // // 3967b7f5c055SJed Brown // // 3968b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 3969b7f5c055SJed Brown // ----- ------- ------- ------- // 3970b7f5c055SJed Brown // // 3971b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 3972b7f5c055SJed Brown // `-_ _-_ _-` / // 3973b7f5c055SJed Brown // \ _-' `-_ / { // 3974b7f5c055SJed Brown // \ / \ // 3975b7f5c055SJed Brown // + + + + + + + \ + // 3976b7f5c055SJed Brown // 3977b7f5c055SJed Brown // 3978b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 3979b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 3980b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 3981b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 3982b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 3983b7f5c055SJed Brown // 3984b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 3985b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 3986b7f5c055SJed Brown // 3987b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 3988b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 3989b7f5c055SJed Brown 3990b7f5c055SJed Brown PetscInt facesPerBlock = 64; 3991b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 3992b7f5c055SJed Brown PetscInt extentPlus[3]; 3993b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 39949371c9d4SSatish 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; 39959371c9d4SSatish Balay const PetscInt pattern[64][4] = { 39969371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 3997b7f5c055SJed Brown /* layer 0 */ 39989371c9d4SSatish Balay {A, C, K, G }, 39999371c9d4SSatish Balay {C, B, II, K }, 40009371c9d4SSatish Balay {D, A, H, L }, 40019371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 40029371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 40039371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 40049371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 40059371c9d4SSatish Balay {B, F, M, II }, 4006b7f5c055SJed Brown /* layer 1 */ 40079371c9d4SSatish Balay {G, K, Q, O }, 40089371c9d4SSatish Balay {K, II, P, Q }, 40099371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 40109371c9d4SSatish Balay {J, L, R, P }, 40119371c9d4SSatish Balay {N, J, P, S }, 40129371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 40139371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 40149371c9d4SSatish Balay {II, M, T, P }, 4015b7f5c055SJed Brown /* layer 2 */ 40169371c9d4SSatish Balay {O, Q, Y, U }, 40179371c9d4SSatish Balay {Q, P, W, Y }, 40189371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 40199371c9d4SSatish Balay {P, R, Ap, W }, 40209371c9d4SSatish Balay {S, P, X, Bp }, 40219371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 40229371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 40239371c9d4SSatish Balay {P, T, Z, X }, 4024b7f5c055SJed Brown /* layer 3 */ 40259371c9d4SSatish Balay {U, Y, Ep, Dp }, 40269371c9d4SSatish Balay {Y, W, Cp, Ep }, 40279371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 40289371c9d4SSatish Balay {W, Ap, Gp, Cp }, 40299371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 40309371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 40319371c9d4SSatish Balay {Z, V, Dp, Hp }, 40329371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 4033b7f5c055SJed Brown /* layer 4 */ 40349371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 40359371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 40369371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 40379371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 40389371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 40399371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 40409371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 40419371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 4042b7f5c055SJed Brown /* layer 5 */ 40439371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 40449371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 40459371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 40469371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 40479371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 40489371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 40499371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 40509371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 4051b7f5c055SJed Brown /* layer 6 */ 40529371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 40539371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 40549371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 40559371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 40569371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 40579371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 40589371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 40599371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 4060b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 40619371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 40629371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 40639371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 40649371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 40659371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 40669371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 40679371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 40689371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 4069b7f5c055SJed Brown }; 4070b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 40719371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 4072bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 4073bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 4074bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 4075bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 4076bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 4077bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 4078b7f5c055SJed Brown 4079bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 4080bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 4081bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 4082bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 4083bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 4084bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 4085bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 4086bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 4087b7f5c055SJed Brown 4088bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 4089bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 4090bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 4091bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 4092bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 4093bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 4094b7f5c055SJed Brown 4095bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 4096bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 4097bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 4098bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 4099bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 4100bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 4101bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 4102bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 4103b7f5c055SJed Brown 4104bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 4105bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 4106bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 4107bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 4108bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 4109bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 4110b7f5c055SJed Brown 4111bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 4112bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 4113bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 4114bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 4115bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 4116bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 4117bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 4118bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 4119b7f5c055SJed Brown 4120bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 4121bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 4122bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 4123bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 4124bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 4125bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 4126b7f5c055SJed Brown 4127bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 4128bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 4129bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 4130bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 4131bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 4132bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 4133bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 4134bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 4135b7f5c055SJed Brown }; 4136b7f5c055SJed Brown PetscInt (*cells)[64][4] = NULL; 4137b7f5c055SJed Brown PetscBool *seen; 4138b7f5c055SJed Brown PetscInt *vertToTrueVert; 4139b7f5c055SJed Brown PetscInt count; 4140b7f5c055SJed Brown 4141b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 4142b7f5c055SJed Brown numBlocks = 1; 4143b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 4144b7f5c055SJed Brown numBlocksPlus = 1; 4145b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 4146b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 41479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 41489566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 4149b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 4150b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 4151b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 4152b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 4153b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 4154b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 4155b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 4156b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 4157b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 4158b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 4159b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 4160b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 4161b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 4162b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 4163b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 4164b7f5c055SJed Brown 4165b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 4166b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 4167b7f5c055SJed Brown } 4168b7f5c055SJed Brown } 4169b7f5c055SJed Brown } 4170b7f5c055SJed Brown } 4171b7f5c055SJed Brown } 41729371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 41739371c9d4SSatish Balay if (seen[i]) numVertices++; 4174b7f5c055SJed Brown count = 0; 41759566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 41769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 4177b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 4178b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 4179b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 4180b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 4181b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 4182b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 4183b7f5c055SJed Brown 4184b7f5c055SJed Brown if (seen[vIdx]) { 4185b7f5c055SJed Brown PetscInt thisVert; 4186b7f5c055SJed Brown 4187b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 4188b7f5c055SJed Brown 4189b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 4190b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 4191b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 4192b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 4193b7f5c055SJed Brown } 4194b7f5c055SJed Brown } 4195b7f5c055SJed Brown } 4196b7f5c055SJed Brown } 4197b7f5c055SJed Brown } 4198b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 4199b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 4200ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 4201b7f5c055SJed Brown } 4202b7f5c055SJed Brown } 42039566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 42049566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 4205b7f5c055SJed Brown cells_flat = cells[0][0]; 4206b7f5c055SJed Brown numEdges = 0; 4207b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 4208b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 4209b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 4210b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 4211b7f5c055SJed Brown 4212b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 4213b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 4214b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 4215b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 4216b7f5c055SJed Brown } 4217b7f5c055SJed Brown } 4218b7f5c055SJed Brown } 4219b7f5c055SJed Brown } 42209566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 42219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 4222b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 4223b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 4224b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 4225b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 4226b7f5c055SJed Brown 4227b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 4228b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 4229b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 4230b7f5c055SJed Brown edges[edge][0] = ev[0]; 4231b7f5c055SJed Brown edges[edge][1] = ev[1]; 4232b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 4233b7f5c055SJed Brown } 4234b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 4235b7f5c055SJed Brown edges[edge][0] = ev[0]; 4236b7f5c055SJed Brown edges[edge][1] = ev[1]; 4237b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 4238b7f5c055SJed Brown } 4239b7f5c055SJed Brown } 4240b7f5c055SJed Brown } 4241b7f5c055SJed Brown } 4242b7f5c055SJed Brown } 4243b7f5c055SJed Brown } 4244b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 42454663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 4246b7f5c055SJed Brown break; 4247b7f5c055SJed Brown } 4248b7f5c055SJed Brown 42499566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 4250c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 42519566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 42529566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 4253b7f5c055SJed Brown { 4254b7f5c055SJed Brown DM idm; 42559566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 425669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 4257b7f5c055SJed Brown } 4258c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 42599566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 42609566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 4261b7f5c055SJed Brown 42629566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 42639566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 4264b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 4265b7f5c055SJed Brown PetscInt njoin; 4266b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 42679566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 426863a3b9bcSJacob 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]); 42699566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 42709566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 4271b7f5c055SJed Brown } 42729566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 42739566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 42741436d7faSJed Brown if (tps_distribute) { 42751436d7faSJed Brown DM pdm = NULL; 42761436d7faSJed Brown PetscPartitioner part; 42771436d7faSJed Brown 42789566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 42799566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 42809566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 428148a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 42821436d7faSJed Brown // Do not auto-distribute again 42839566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 42841436d7faSJed Brown } 4285b7f5c055SJed Brown 42869566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 4287b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 4288b7f5c055SJed Brown PetscInt m; 4289b7f5c055SJed Brown DM dmf; 4290b7f5c055SJed Brown Vec X; 4291b7f5c055SJed Brown PetscScalar *x; 42929566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 429369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 4294b7f5c055SJed Brown 42959566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 42969566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 42979566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 429848a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 42999566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 4300b7f5c055SJed Brown } 4301b7f5c055SJed Brown 4302b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 43039566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 43049566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 4305b7f5c055SJed Brown 430646139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 430746139095SJed Brown 4308b7f5c055SJed Brown if (thickness > 0) { 43094663dae6SJed Brown DM edm, cdm, ecdm; 43104663dae6SJed Brown DMPlexTransform tr; 43114663dae6SJed Brown const char *prefix; 43124663dae6SJed Brown PetscOptions options; 43134663dae6SJed Brown // Code from DMPlexExtrude 43144663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 43154663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 4316ce78bad3SBarry Smith PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDETYPE)); 43174663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 43184663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 43194663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 43204663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 43214663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 43224663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 43234663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 43244663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 43254663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 43264663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 43274663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 43284663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 43294663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 43304663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 43314663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 43324663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 43334663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 43344663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 43354663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 43364663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 4337a77a5016SMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, edm)); 433869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 4339b7f5c055SJed Brown } 43403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4341b7f5c055SJed Brown } 4342b7f5c055SJed Brown 4343b7f5c055SJed Brown /*@ 4344b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 4345b7f5c055SJed Brown 4346b7f5c055SJed Brown Collective 4347b7f5c055SJed Brown 4348b7f5c055SJed Brown Input Parameters: 4349a1cb98faSBarry Smith + comm - The communicator for the `DM` object 4350b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 4351b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 435220f4b53cSBarry Smith . periodic - array of length 3 with periodicity, or `NULL` for non-periodic 43531436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 4354817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 43551436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 4356817da375SSatish Balay - thickness - Thickness in normal direction 4357b7f5c055SJed Brown 4358b7f5c055SJed Brown Output Parameter: 4359a1cb98faSBarry Smith . dm - The `DM` object 4360a1cb98faSBarry Smith 4361a1cb98faSBarry Smith Level: beginner 4362b7f5c055SJed Brown 4363b7f5c055SJed Brown Notes: 436415229ffcSPierre Jolivet This meshes the surface of the Schwarz P or Gyroid surfaces. Schwarz P is the simplest member of the triply-periodic minimal surfaces. 43651d27aa22SBarry Smith <https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22)> and can be cut with "clean" boundaries. 43661d27aa22SBarry 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. 4367b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 4368b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 4369b7f5c055SJed Brown This projection could readily be extended to related surfaces. 4370b7f5c055SJed Brown 43711d27aa22SBarry Smith See {cite}`maskery2018insights` 43721d27aa22SBarry Smith 43731d27aa22SBarry Smith The face (edge) sets for the Schwarz P surface are numbered $1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z)$. 43741d27aa22SBarry Smith When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). 43751d27aa22SBarry Smith Use `DMPlexLabelComplete()` to propagate to coarse-level vertices. 4376b7f5c055SJed Brown 437760225df5SJacob Faibussowitsch Developer Notes: 4378b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 4379b7f5c055SJed Brown 43801cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 4381b7f5c055SJed Brown @*/ 4382d71ae5a4SJacob 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) 4383d71ae5a4SJacob Faibussowitsch { 4384b7f5c055SJed Brown PetscFunctionBegin; 43859566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 43869566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 43879566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 43883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4389b7f5c055SJed Brown } 4390b7f5c055SJed Brown 43919318fe57SMatthew G. Knepley /*@ 43929318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 43939318fe57SMatthew G. Knepley 43949318fe57SMatthew G. Knepley Collective 43959318fe57SMatthew G. Knepley 43969318fe57SMatthew G. Knepley Input Parameters: 4397a1cb98faSBarry Smith + comm - The communicator for the `DM` object 43989318fe57SMatthew G. Knepley . dim - The dimension 43999318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 44009318fe57SMatthew G. Knepley - R - The radius 44019318fe57SMatthew G. Knepley 44029318fe57SMatthew G. Knepley Output Parameter: 4403a1cb98faSBarry Smith . dm - The `DM` object 44049318fe57SMatthew G. Knepley 44059318fe57SMatthew G. Knepley Level: beginner 44069318fe57SMatthew G. Knepley 44071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 44089318fe57SMatthew G. Knepley @*/ 4409d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 4410d71ae5a4SJacob Faibussowitsch { 44119318fe57SMatthew G. Knepley PetscFunctionBegin; 44124f572ea9SToby Isaac PetscAssertPointer(dm, 5); 44139566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44149566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 44159566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 44163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44179318fe57SMatthew G. Knepley } 44189318fe57SMatthew G. Knepley 4419d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 4420d71ae5a4SJacob Faibussowitsch { 44219318fe57SMatthew G. Knepley DM sdm, vol; 44229318fe57SMatthew G. Knepley DMLabel bdlabel; 4423dd2b43ebSStefano Zampini const char *prefix; 44249318fe57SMatthew G. Knepley 44259318fe57SMatthew G. Knepley PetscFunctionBegin; 44269566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 44279566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 4428dd2b43ebSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 4429dd2b43ebSStefano Zampini PetscCall(DMSetOptionsPrefix(sdm, prefix)); 4430dd2b43ebSStefano Zampini PetscCall(DMAppendOptionsPrefix(sdm, "bd_")); 4431dd2b43ebSStefano Zampini PetscCall(DMPlexDistributeSetDefault(sdm, PETSC_FALSE)); 44329566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 44339566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 44349566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 44359566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 44369566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 443769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 44389566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 44399566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 44409566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 44419566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 44423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 444351a74b61SMatthew G. Knepley } 444451a74b61SMatthew G. Knepley 444551a74b61SMatthew G. Knepley /*@ 444651a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 444751a74b61SMatthew G. Knepley 444851a74b61SMatthew G. Knepley Collective 444951a74b61SMatthew G. Knepley 445051a74b61SMatthew G. Knepley Input Parameters: 4451a1cb98faSBarry Smith + comm - The communicator for the `DM` object 445251a74b61SMatthew G. Knepley . dim - The dimension 445351a74b61SMatthew G. Knepley - R - The radius 445451a74b61SMatthew G. Knepley 445551a74b61SMatthew G. Knepley Output Parameter: 4456a1cb98faSBarry Smith . dm - The `DM` object 445751a74b61SMatthew G. Knepley 4458a1cb98faSBarry Smith Options Database Key: 445960225df5SJacob Faibussowitsch . bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 446051a74b61SMatthew G. Knepley 446151a74b61SMatthew G. Knepley Level: beginner 446251a74b61SMatthew G. Knepley 44631cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 446451a74b61SMatthew G. Knepley @*/ 4465d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 4466d71ae5a4SJacob Faibussowitsch { 446751a74b61SMatthew G. Knepley PetscFunctionBegin; 44689566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44699566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 44709566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 44713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44722829fed8SMatthew G. Knepley } 44732829fed8SMatthew G. Knepley 4474d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 4475d71ae5a4SJacob Faibussowitsch { 44760a6ba040SMatthew G. Knepley PetscFunctionBegin; 44779318fe57SMatthew G. Knepley switch (ct) { 44789371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 44799318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 44809318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 44819318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 44829318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 44839318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 44849318fe57SMatthew G. Knepley 44859566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 44869566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 44879371c9d4SSatish Balay } break; 44889371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 44899318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 44909318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 44919318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 44929318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 44939318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 44949318fe57SMatthew G. Knepley 44959566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 44969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 44979371c9d4SSatish Balay } break; 44989371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 4499b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 4500b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 4501b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 4502b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 4503b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 4504b5a892a1SMatthew G. Knepley 45059566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 45069566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45079371c9d4SSatish Balay } break; 45089371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 45099318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 45109318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 45119318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 45129318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 45139318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 45149318fe57SMatthew G. Knepley 45159566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45169566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45179371c9d4SSatish Balay } break; 45189371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 45199318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45209318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 45219318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45229318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 45239318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 45249318fe57SMatthew G. Knepley 45259566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45269566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45279371c9d4SSatish Balay } break; 45289371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 45299318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45309318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 45319318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45329318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 45339318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 45349318fe57SMatthew G. Knepley 45359566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45379371c9d4SSatish Balay } break; 45389371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 45399318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45409318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 4541f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45429318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 4543f0edb160SMatthew 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}; 45449318fe57SMatthew G. Knepley 45459566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45469566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45479371c9d4SSatish Balay } break; 45489371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 45499318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 45509318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 4551f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 45529318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 45539371c9d4SSatish 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}; 45549318fe57SMatthew G. Knepley 45559566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45569566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45579371c9d4SSatish Balay } break; 45589371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 45599318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 45609318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 4561f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 45629318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 45639371c9d4SSatish 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}; 45649318fe57SMatthew G. Knepley 45659566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45679371c9d4SSatish Balay } break; 45689371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 45699318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 45709318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 45719318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 45729318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 45739371c9d4SSatish 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}; 45749318fe57SMatthew G. Knepley 45759566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45769566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45779371c9d4SSatish Balay } break; 45789371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 45799318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 45809318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 45819318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 45829318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 45839371c9d4SSatish 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}; 45849318fe57SMatthew G. Knepley 45859566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45869566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45879371c9d4SSatish Balay } break; 45889371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 45899318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 45909318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 4591f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 45929318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 45939371c9d4SSatish 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}; 45949318fe57SMatthew G. Knepley 45959566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45979371c9d4SSatish Balay } break; 4598d71ae5a4SJacob Faibussowitsch default: 4599d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 46009318fe57SMatthew G. Knepley } 46019318fe57SMatthew G. Knepley { 46029318fe57SMatthew G. Knepley PetscInt Nv, v; 46039318fe57SMatthew G. Knepley 46049318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 46059566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 46069566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 46079566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 46089566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 46099318fe57SMatthew G. Knepley } 46109566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 46119566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 46123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46130a6ba040SMatthew G. Knepley } 46140a6ba040SMatthew G. Knepley 46159318fe57SMatthew G. Knepley /*@ 4616a1cb98faSBarry Smith DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell 46179318fe57SMatthew G. Knepley 46189318fe57SMatthew G. Knepley Collective 46199318fe57SMatthew G. Knepley 46209318fe57SMatthew G. Knepley Input Parameters: 46219318fe57SMatthew G. Knepley + comm - The communicator 46229318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 46239318fe57SMatthew G. Knepley 46249318fe57SMatthew G. Knepley Output Parameter: 46259318fe57SMatthew G. Knepley . refdm - The reference cell 46269318fe57SMatthew G. Knepley 46279318fe57SMatthew G. Knepley Level: intermediate 46289318fe57SMatthew G. Knepley 462942747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()` 46309318fe57SMatthew G. Knepley @*/ 4631d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 4632d71ae5a4SJacob Faibussowitsch { 46330a6ba040SMatthew G. Knepley PetscFunctionBegin; 46349566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 46359566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 46369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 46373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46389318fe57SMatthew G. Knepley } 463979a015ccSMatthew G. Knepley 4640d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 4641d71ae5a4SJacob Faibussowitsch { 46429318fe57SMatthew G. Knepley DM plex; 46439318fe57SMatthew G. Knepley DMLabel label; 46449318fe57SMatthew G. Knepley PetscBool hasLabel; 46450a6ba040SMatthew G. Knepley 4646c22d3578SMatthew G. Knepley PetscFunctionBegin; 46479566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 46483ba16761SJacob Faibussowitsch if (hasLabel) PetscFunctionReturn(PETSC_SUCCESS); 46499566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 46509566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 46519566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 46529566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 46531c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 46549566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 46553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46569318fe57SMatthew G. Knepley } 4657acdc6f61SToby Isaac 4658669647acSMatthew G. Knepley /* 4659669647acSMatthew 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. 4660669647acSMatthew G. Knepley 4661669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 4662669647acSMatthew G. Knepley */ 4663d71ae5a4SJacob 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[]) 4664d71ae5a4SJacob Faibussowitsch { 4665669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 4666669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 4667669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 4668669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 4669669647acSMatthew G. Knepley 4670669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 4671669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 4672669647acSMatthew G. Knepley } 4673669647acSMatthew G. Knepley 46745390be7dSMatthew G. Knepley // Insert vertices and their joins, marked by depth 46755390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Vertices(DM dm, DMLabel label, DMLabel vlabel, PetscInt val, PetscInt n, const PetscInt vertices[]) 46765390be7dSMatthew G. Knepley { 46775390be7dSMatthew G. Knepley PetscFunctionBegin; 46785390be7dSMatthew G. Knepley PetscCall(DMPlexMarkSubmesh_Interpolated(dm, vlabel, val, PETSC_FALSE, PETSC_FALSE, label, NULL)); 46795390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 46805390be7dSMatthew G. Knepley } 46815390be7dSMatthew G. Knepley 46825390be7dSMatthew G. Knepley // Insert faces and their closures, marked by depth 46835390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Faces(DM dm, DMLabel label, PetscInt n, const PetscInt faces[]) 46845390be7dSMatthew G. Knepley { 46855390be7dSMatthew G. Knepley PetscFunctionBegin; 46865390be7dSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) { 46875390be7dSMatthew G. Knepley const PetscInt point = faces[p]; 46885390be7dSMatthew G. Knepley PetscInt *closure = NULL; 46895390be7dSMatthew G. Knepley PetscInt clSize, pdepth; 46905390be7dSMatthew G. Knepley 46915390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, point, &pdepth)); 46925390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, point, pdepth)); 46935390be7dSMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 46945390be7dSMatthew G. Knepley for (PetscInt cl = 0; cl < clSize * 2; cl += 2) { 46955390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, closure[cl], &pdepth)); 46965390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, closure[cl], pdepth)); 46975390be7dSMatthew G. Knepley } 46985390be7dSMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 46995390be7dSMatthew G. Knepley } 47005390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 47015390be7dSMatthew G. Knepley } 47025390be7dSMatthew G. Knepley 47034e22dd4cSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *flg); 47044e22dd4cSMatthew G. Knepley 47055dca41c3SJed Brown const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "zbox", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 47069318fe57SMatthew G. Knepley 4707ce78bad3SBarry Smith static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 4708d71ae5a4SJacob Faibussowitsch { 47099318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 47109318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 47119318fe57SMatthew G. Knepley PetscInt dim = 2; 4712b9da1bb3SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, orient = PETSC_FALSE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 4713d0812dedSMatthew G. Knepley PetscBool flg, flg2, fflg, strflg, bdfflg, nameflg; 47149318fe57SMatthew G. Knepley MPI_Comm comm; 4715ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4716ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4717ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 47184e22dd4cSMatthew G. Knepley const char *option; 47199318fe57SMatthew G. Knepley 47209318fe57SMatthew G. Knepley PetscFunctionBegin; 4721708be2fdSJed Brown PetscCall(PetscLogEventBegin(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 47229566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 47239318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 47249566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 4725d0812dedSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_file_contents", "Contents of a file format in a string", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &strflg)); 47269566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 47279566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 47289566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 47299566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 47309566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 47319566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 47329566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 47339566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 4734b9da1bb3SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_orient", "Orient the constructed mesh", "DMPlexOrient", orient, &orient, &flg)); 47359566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 47369566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 47379566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 47383f3e541fSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_adj", "Debug output level all adjacency computations", "", 0, &((DM_Plex *)dm->data)->printAdj, NULL, 0)); 47399318fe57SMatthew G. Knepley 474061a622f3SMatthew G. Knepley switch (cell) { 474161a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 474261a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 474361a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 474461a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 474561a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 474661a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 4747d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 4748d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_TRUE; 4749d71ae5a4SJacob Faibussowitsch break; 4750d71ae5a4SJacob Faibussowitsch default: 4751d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_FALSE; 4752d71ae5a4SJacob Faibussowitsch break; 475361a622f3SMatthew G. Knepley } 475461a622f3SMatthew G. Knepley 47559318fe57SMatthew G. Knepley if (fflg) { 47569318fe57SMatthew G. Knepley DM dmnew; 47571e4a82c4SMatthew G. Knepley const char *name; 47589318fe57SMatthew G. Knepley 47591e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 47601e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, nameflg ? plexname : name, interpolate, &dmnew)); 47615de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 476269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 47639318fe57SMatthew G. Knepley } else if (refDomain) { 47649566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 47659318fe57SMatthew G. Knepley } else if (bdfflg) { 47669318fe57SMatthew G. Knepley DM bdm, dmnew; 47671e4a82c4SMatthew G. Knepley const char *name; 47689318fe57SMatthew G. Knepley 47691e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 47701e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, nameflg ? plexname : name, interpolate, &bdm)); 47719566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 47729566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 47739566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 47749566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 47755de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 477669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 4777d0812dedSMatthew G. Knepley } else if (strflg) { 4778d0812dedSMatthew G. Knepley DM dmnew; 4779d0812dedSMatthew G. Knepley PetscViewer viewer; 4780d0812dedSMatthew G. Knepley const char *contents; 4781d0812dedSMatthew G. Knepley char *strname; 4782d0812dedSMatthew G. Knepley char tmpdir[PETSC_MAX_PATH_LEN]; 4783d0812dedSMatthew G. Knepley char tmpfilename[PETSC_MAX_PATH_LEN]; 4784d0812dedSMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 4785d0812dedSMatthew G. Knepley MPI_Comm comm; 4786d0812dedSMatthew G. Knepley PetscMPIInt rank; 4787d0812dedSMatthew G. Knepley 4788d0812dedSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4789d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 4790d0812dedSMatthew G. Knepley PetscCall(PetscStrchr(filename, ':', &strname)); 4791d0812dedSMatthew G. Knepley PetscCheck(strname, comm, PETSC_ERR_ARG_WRONG, "File contents must have the form \"ext:string_name\", not %s", filename); 4792d0812dedSMatthew G. Knepley strname[0] = '\0'; 4793d0812dedSMatthew G. Knepley ++strname; 4794d0812dedSMatthew G. Knepley PetscCall(PetscDLSym(NULL, strname, (void **)&contents)); 4795d0812dedSMatthew G. Knepley PetscCheck(contents, comm, PETSC_ERR_ARG_WRONG, "Could not locate mesh string %s", strname); 4796d0812dedSMatthew G. Knepley PetscCall(PetscGetTmp(comm, tmpdir, PETSC_MAX_PATH_LEN)); 4797ed32af8cSMatthew G. Knepley PetscCall(PetscStrlcat(tmpdir, "/meshXXXXXX", PETSC_MAX_PATH_LEN)); 4798ed32af8cSMatthew G. Knepley PetscCall(PetscMkdtemp(tmpdir)); 4799ed32af8cSMatthew G. Knepley PetscCall(PetscSNPrintf(tmpfilename, PETSC_MAX_PATH_LEN, "%s/mesh.%s", tmpdir, filename)); 4800d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIOpen(comm, tmpfilename, &viewer)); 4801d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", contents)); 4802d0812dedSMatthew G. Knepley PetscCall(PetscViewerDestroy(&viewer)); 4803d0812dedSMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), tmpfilename, plexname, interpolate, &dmnew)); 4804ed32af8cSMatthew G. Knepley PetscCall(PetscRMTree(tmpdir)); 4805d0812dedSMatthew G. Knepley PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%s Mesh", strname)); 4806d0812dedSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, name)); 4807d0812dedSMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 4808d0812dedSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 48099318fe57SMatthew G. Knepley } else { 48109566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 48119318fe57SMatthew G. Knepley switch (shape) { 4812669647acSMatthew G. Knepley case DM_SHAPE_BOX: 48135dca41c3SJed Brown case DM_SHAPE_ZBOX: 4814669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 48159318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 48169318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 48179318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 48189318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4819669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 48209318fe57SMatthew G. Knepley PetscInt i, n; 48219318fe57SMatthew G. Knepley 48229318fe57SMatthew G. Knepley n = dim; 48239318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 48249566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 48259318fe57SMatthew G. Knepley n = 3; 48269566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 482763a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 48289318fe57SMatthew G. Knepley n = 3; 48299566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 483063a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 48319318fe57SMatthew G. Knepley n = 3; 48329566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 483363a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 4834669647acSMatthew G. Knepley 4835669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 4836669647acSMatthew G. Knepley if (isAnnular) 4837669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 4838669647acSMatthew G. Knepley 48399318fe57SMatthew G. Knepley switch (cell) { 484061a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 48419566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 4842d410b0cfSMatthew G. Knepley if (!interpolate) { 4843d410b0cfSMatthew G. Knepley DM udm; 4844d410b0cfSMatthew G. Knepley 48459566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 484669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 4847d410b0cfSMatthew G. Knepley } 48489318fe57SMatthew G. Knepley break; 4849d71ae5a4SJacob Faibussowitsch default: 48505dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(dm, shape, dim, simplex, faces, lower, upper, bdt, interpolate)); 4851d71ae5a4SJacob Faibussowitsch break; 48529318fe57SMatthew G. Knepley } 4853669647acSMatthew G. Knepley if (isAnnular) { 4854669647acSMatthew G. Knepley DM cdm; 4855669647acSMatthew G. Knepley PetscDS cds; 4856669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 4857669647acSMatthew G. Knepley 4858669647acSMatthew G. Knepley // Fix coordinates for annular region 4859669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 4860669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 4861669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 4862e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL)); 4863669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 4864669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 4865669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 4866669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 4867669647acSMatthew G. Knepley } 48689371c9d4SSatish Balay } break; 48699371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 48709318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 48719318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 48729318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 48739318fe57SMatthew G. Knepley PetscInt i, n; 48749318fe57SMatthew G. Knepley 48759318fe57SMatthew G. Knepley n = dim + 1; 48769318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 48779566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 48789318fe57SMatthew G. Knepley n = 3; 48799566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 488063a3b9bcSJacob 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); 48819318fe57SMatthew G. Knepley n = 3; 48829566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 488363a3b9bcSJacob 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); 48849566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 48859371c9d4SSatish Balay } break; 48869371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 48879318fe57SMatthew G. Knepley PetscReal R = 1.0; 48889318fe57SMatthew G. Knepley 48899566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 48909566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 48919371c9d4SSatish Balay } break; 48929371c9d4SSatish Balay case DM_SHAPE_BALL: { 48939318fe57SMatthew G. Knepley PetscReal R = 1.0; 48949318fe57SMatthew G. Knepley 48959566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 48969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 48979371c9d4SSatish Balay } break; 48989371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 48999318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 49009318fe57SMatthew G. Knepley PetscInt Nw = 6; 490149704ca5SMatthew G. Knepley PetscInt Nr = 0; 49029318fe57SMatthew G. Knepley 49039566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 49049566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 490549704ca5SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_refine", "Number of refinements before projection", "", Nr, &Nr, NULL)); 49069318fe57SMatthew G. Knepley switch (cell) { 4907d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_TRI_PRISM_TENSOR: 4908d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 4909d71ae5a4SJacob Faibussowitsch break; 4910d71ae5a4SJacob Faibussowitsch default: 491149704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt, Nr)); 4912d71ae5a4SJacob Faibussowitsch break; 49139318fe57SMatthew G. Knepley } 49149371c9d4SSatish Balay } break; 4915b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 49169371c9d4SSatish Balay case DM_SHAPE_GYROID: { 4917b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 4918b7f5c055SJed Brown PetscReal thickness = 0.; 4919b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4920b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 49211436d7faSJed Brown PetscBool tps_distribute; 49229566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 49239566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 49249566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 49259566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 49269566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 49279566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 49289566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 49299566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 49309371c9d4SSatish Balay } break; 49319371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 493205bd46c0SStefano Zampini DM dmnew; 493305bd46c0SStefano Zampini PetscReal rl = 0.0; 493405bd46c0SStefano Zampini 493505bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 493605bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 49375de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 493869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 49399371c9d4SSatish Balay } break; 4940cfb853baSMatthew G. Knepley case DM_SHAPE_HYPERCUBIC: { 49418d2ec52aSSatish Balay PetscInt *edges, overlap = 1; 4942cfb853baSMatthew G. Knepley PetscReal *lower, *upper; 4943cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 4944cfb853baSMatthew G. Knepley PetscInt n, d; 4945cfb853baSMatthew G. Knepley 4946cfb853baSMatthew G. Knepley *useCoordSpace = PETSC_FALSE; 4947cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt)); 4948cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 4949cfb853baSMatthew G. Knepley edges[d] = 1; 4950cfb853baSMatthew G. Knepley lower[d] = 0.; 4951cfb853baSMatthew G. Knepley upper[d] = 1.; 4952cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 4953cfb853baSMatthew G. Knepley } 4954cfb853baSMatthew G. Knepley n = dim; 4955cfb853baSMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg)); 4956cfb853baSMatthew G. Knepley n = dim; 4957cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 4958cfb853baSMatthew 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); 4959cfb853baSMatthew G. Knepley n = dim; 4960cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 4961cfb853baSMatthew 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); 4962cfb853baSMatthew G. Knepley n = dim; 4963cfb853baSMatthew G. Knepley PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 4964cfb853baSMatthew 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); 49658d2ec52aSSatish Balay PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", overlap, &overlap, NULL, 0)); 49668d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, overlap, bdt)); 4967cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edges, lower, upper, bdt)); 4968cfb853baSMatthew G. Knepley } break; 4969d71ae5a4SJacob Faibussowitsch default: 4970d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 49719318fe57SMatthew G. Knepley } 49729318fe57SMatthew G. Knepley } 49739566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 497448a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 4975b9da1bb3SMatthew G. Knepley if (orient) PetscCall(DMPlexOrient(dm)); 49764e22dd4cSMatthew G. Knepley // Allow label creation 49774e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_label_", &option, NULL, &flg)); 49784e22dd4cSMatthew G. Knepley if (flg) { 49794e22dd4cSMatthew G. Knepley DMLabel label; 49804e22dd4cSMatthew G. Knepley PetscInt points[1024], n = 1024; 49814e22dd4cSMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 49824e22dd4cSMatthew G. Knepley const char *name = &option[14]; 49834e22dd4cSMatthew G. Knepley 49844e22dd4cSMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 49854e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 49864e22dd4cSMatthew G. Knepley fulloption[0] = '-'; 49874e22dd4cSMatthew G. Knepley fulloption[1] = 0; 49884e22dd4cSMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, option, PETSC_MAX_PATH_LEN)); 49894e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, NULL)); 49904e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) PetscCall(DMLabelSetValue(label, points[p], 1)); 49914e22dd4cSMatthew G. Knepley } 4992dd0eeac9SMatthew G. Knepley // Allow cohesive label creation 4993dd0eeac9SMatthew G. Knepley // Faces are input, completed, and all points are marked with their depth 4994dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_cohesive_label_", &option, NULL, &flg)); 4995dd0eeac9SMatthew G. Knepley if (flg) { 4996dd0eeac9SMatthew G. Knepley DMLabel label; 4997dd0eeac9SMatthew G. Knepley PetscInt points[1024], n, pStart, pEnd, Nl = 1; 49985390be7dSMatthew G. Knepley PetscBool noCreate = PETSC_FALSE; 4999dd0eeac9SMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 5000dd0eeac9SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 5001dd0eeac9SMatthew G. Knepley size_t len; 5002dd0eeac9SMatthew G. Knepley 5003dd0eeac9SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 5004dd0eeac9SMatthew G. Knepley PetscCall(PetscStrncpy(name, &option[23], PETSC_MAX_PATH_LEN)); 5005dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlen(name, &len)); 5006dd0eeac9SMatthew G. Knepley if (name[len - 1] == '0') Nl = 10; 5007dd0eeac9SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 50086497c311SBarry Smith if (l > 0) name[len - 1] = (char)('0' + l); 5009dd0eeac9SMatthew G. Knepley fulloption[0] = 0; 5010dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, "-dm_plex_cohesive_label_", 32)); 5011dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, name, PETSC_MAX_PATH_LEN - 32)); 5012dd0eeac9SMatthew G. Knepley n = 1024; 5013dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, &flg)); 5014dd0eeac9SMatthew G. Knepley if (!flg) break; 50155390be7dSMatthew G. Knepley PetscCall(DMHasLabel(dm, name, &noCreate)); 50165390be7dSMatthew G. Knepley if (noCreate) { 50175390be7dSMatthew G. Knepley DMLabel inlabel; 50185390be7dSMatthew G. Knepley IS pointIS; 50195390be7dSMatthew G. Knepley const PetscInt *lpoints; 50205390be7dSMatthew G. Knepley PetscInt pdep, ln, inval = points[0]; 50215390be7dSMatthew G. Knepley char newname[PETSC_MAX_PATH_LEN]; 50225390be7dSMatthew G. Knepley 50235390be7dSMatthew G. Knepley PetscCheck(n == 1, comm, PETSC_ERR_ARG_WRONG, "Must specify a label value with this option"); 50245390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &inlabel)); 50255390be7dSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(inlabel, inval, &pointIS)); 50265390be7dSMatthew G. Knepley PetscCall(ISGetLocalSize(pointIS, &ln)); 50275390be7dSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &lpoints)); 50285390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, lpoints[0], &pdep)); 50295390be7dSMatthew G. Knepley PetscCall(PetscSNPrintf(newname, PETSC_MAX_PATH_LEN, "%s%" PetscInt_FMT, name, points[0])); 50305390be7dSMatthew G. Knepley PetscCall(DMCreateLabel(dm, newname)); 50315390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, newname, &label)); 50325390be7dSMatthew G. Knepley if (!pdep) PetscCall(ProcessCohesiveLabel_Vertices(dm, label, inlabel, inval, ln, lpoints)); 50335390be7dSMatthew G. Knepley else PetscCall(ProcessCohesiveLabel_Faces(dm, label, ln, lpoints)); 50345390be7dSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &lpoints)); 50355390be7dSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 50365390be7dSMatthew G. Knepley } else { 5037dd0eeac9SMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 5038dd0eeac9SMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 5039dd0eeac9SMatthew G. Knepley if (pStart >= pEnd) n = 0; 50405390be7dSMatthew G. Knepley PetscCall(ProcessCohesiveLabel_Faces(dm, label, n, points)); 5041dd0eeac9SMatthew G. Knepley } 5042dd0eeac9SMatthew G. Knepley PetscCall(DMPlexOrientLabel(dm, label)); 50430542aa8cSMatthew G. Knepley PetscCall(DMPlexLabelCohesiveComplete(dm, label, NULL, 1, PETSC_FALSE, PETSC_FALSE, NULL)); 5044dd0eeac9SMatthew G. Knepley } 5045dd0eeac9SMatthew G. Knepley } 50465390be7dSMatthew G. Knepley PetscCall(DMViewFromOptions(dm, NULL, "-created_dm_view")); 5047708be2fdSJed Brown PetscCall(PetscLogEventEnd(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 50483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50490a6ba040SMatthew G. Knepley } 50500a6ba040SMatthew G. Knepley 5051ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems PetscOptionsObject) 5052d71ae5a4SJacob Faibussowitsch { 50530a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 50547f9d8d6cSVaclav Hapla PetscBool flg, flg2; 50559318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 5056adc21957SMatthew G. Knepley char method[PETSC_MAX_PATH_LEN]; 50570a6ba040SMatthew G. Knepley 50580a6ba040SMatthew G. Knepley PetscFunctionBegin; 50590a6ba040SMatthew G. Knepley /* Handle viewing */ 50609566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 50615962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level for all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 50625962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fvm", "Debug output level for all fvm computations", "DMPlexSNESComputeResidualFVM", 0, &mesh->printFVM, NULL, 0)); 50639566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 50649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 5065f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 5066a77a5016SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_project", "Debug output level all projection computations", "DMPlexProject", 0, &mesh->printProject, NULL, 0)); 50679566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 50689566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 50695e2c5519SMatthew G. Knepley // Interpolation 50705e2c5519SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_interpolate_prefer_tensor", "When different orderings exist, prefer the tensor order", "DMPlexSetInterpolationPreferTensor", mesh->interpolatePreferTensor, &mesh->interpolatePreferTensor, NULL)); 50719318fe57SMatthew G. Knepley /* Labeling */ 50729566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 50739566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 5074953fc75cSMatthew G. Knepley /* Point Location */ 50759566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 50760848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 50779566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 5078d02c7345SMatthew G. Knepley /* Reordering */ 5079adc21957SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_reorder_section", "Compute point permutation for local section", "DMReorderSectionSetDefault", PETSC_FALSE, &flg2, &flg)); 5080adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetDefault(dm, flg2 ? DM_REORDER_DEFAULT_TRUE : DM_REORDER_DEFAULT_FALSE)); 5081adc21957SMatthew G. Knepley PetscCall(PetscOptionsString("-dm_reorder_section_type", "Reordering method for local section", "DMReorderSectionSetType", method, method, PETSC_MAX_PATH_LEN, &flg)); 5082adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetType(dm, method)); 50832e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 50849566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 5085*61f058f9SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_save_transform", "Save the transform producing this mesh", "DMAdapt", PETSC_FALSE, &mesh->saveTransform, NULL)); 5086b29cfa1cSToby Isaac /* Projection behavior */ 5087d5b43468SJose E. Roman PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 50889566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 5089f12cf164SMatthew G. Knepley /* Checking structure */ 5090f12cf164SMatthew G. Knepley { 50917f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 5092f12cf164SMatthew G. Knepley 50937f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 50947f9d8d6cSVaclav Hapla if (all) { 50957f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 50967f9d8d6cSVaclav Hapla } else { 50979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 50987f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 50999566063dSJacob 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)); 51007f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 51019566063dSJacob 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)); 51027f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 51039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 51047f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 51059566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 5106d7d32a9aSMatthew G. Knepley if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 51079566063dSJacob 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)); 51087f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 51097f9d8d6cSVaclav Hapla } 51109566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 51119566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 5112f12cf164SMatthew G. Knepley } 51139318fe57SMatthew G. Knepley { 51149318fe57SMatthew G. Knepley PetscReal scale = 1.0; 51154f3833eaSMatthew G. Knepley 51169566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 51179318fe57SMatthew G. Knepley if (flg) { 51189318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 51199318fe57SMatthew G. Knepley 51209566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 51219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 51229566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 51239566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 51249318fe57SMatthew G. Knepley } 51259318fe57SMatthew G. Knepley } 51269566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 51273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 512868d4fef7SMatthew G. Knepley } 512968d4fef7SMatthew G. Knepley 5130ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems PetscOptionsObject, PetscInt *overlap) 5131d71ae5a4SJacob Faibussowitsch { 5132c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 5133c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 5134c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 5135c506a872SMatthew G. Knepley PetscBool flg; 5136c506a872SMatthew G. Knepley 5137c506a872SMatthew G. Knepley PetscFunctionBegin; 5138c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 5139c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 5140c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 5141c506a872SMatthew G. Knepley if (numOvLabels) { 5142c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 5143c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 5144c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 5145c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 5146c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 5147c506a872SMatthew G. Knepley } 5148c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 5149c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 5150c506a872SMatthew 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); 5151c506a872SMatthew G. Knepley 5152c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 5153c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 5154c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 5155c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 5156c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 5157c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 5158c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 5159c506a872SMatthew G. Knepley } 5160c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 5161c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 5162c506a872SMatthew 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); 5163c506a872SMatthew G. Knepley } 51643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5165c506a872SMatthew G. Knepley } 5166c506a872SMatthew G. Knepley 5167ce78bad3SBarry Smith static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems PetscOptionsObject) 5168d71ae5a4SJacob Faibussowitsch { 5169bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 5170bdf63967SMatthew G. Knepley char oname[256]; 51714e22dd4cSMatthew G. Knepley char sublabelname[PETSC_MAX_PATH_LEN] = ""; 5172adc21957SMatthew G. Knepley DMReorderDefaultFlag reorder; 5173d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 51749318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 5175530e699aSMatthew G. Knepley PetscBool uniformOrig = PETSC_FALSE, uniform = PETSC_TRUE, distribute, saveSF = PETSC_FALSE, interpolate = PETSC_TRUE, coordSpace = PETSC_FALSE, remap = PETSC_TRUE, ghostCells = PETSC_FALSE, isHierarchy, flg; 517668d4fef7SMatthew G. Knepley 517768d4fef7SMatthew G. Knepley PetscFunctionBegin; 5178d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 5179dd4c3f67SMatthew G. Knepley if (dm->cloneOpts) goto non_refine; 51809318fe57SMatthew G. Knepley /* Handle automatic creation */ 51819566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 5182530e699aSMatthew G. Knepley if (dim < 0) PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 51836bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 5184d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 51859566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 5186d89e6e46SMatthew G. Knepley if (flg) { 5187d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 5188d89e6e46SMatthew G. Knepley 51899566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 5190d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 5191d89e6e46SMatthew G. Knepley DM udm; 5192d89e6e46SMatthew G. Knepley 51939566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 519469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 5195d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 5196d89e6e46SMatthew G. Knepley DM idm; 5197d89e6e46SMatthew G. Knepley 51989566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 519969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 5200d89e6e46SMatthew G. Knepley } 5201d89e6e46SMatthew G. Knepley } 52024e22dd4cSMatthew G. Knepley // Handle submesh selection before distribution 52034e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_submesh", "Label to use for submesh selection", "", sublabelname, sublabelname, PETSC_MAX_PATH_LEN, &flg)); 52044e22dd4cSMatthew G. Knepley if (flg) { 52054e22dd4cSMatthew G. Knepley DM subdm; 52064e22dd4cSMatthew G. Knepley DMLabel label; 52074e22dd4cSMatthew G. Knepley IS valueIS, pointIS; 52084e22dd4cSMatthew G. Knepley const PetscInt *values, *points; 52094e22dd4cSMatthew G. Knepley PetscBool markedFaces = PETSC_FALSE; 52104e22dd4cSMatthew G. Knepley PetscInt Nv, value, Np; 52114e22dd4cSMatthew G. Knepley 52124e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, sublabelname, &label)); 52134e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &Nv)); 52144e22dd4cSMatthew 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); 52154e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetValueIS(label, &valueIS)); 52164e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &values)); 52174e22dd4cSMatthew G. Knepley value = values[0]; 52184e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(valueIS, &values)); 52194e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 52204e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumSize(label, value, &Np)); 52214e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, value, &pointIS)); 52224e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &points)); 52234e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 52244e22dd4cSMatthew G. Knepley PetscInt pdepth; 52254e22dd4cSMatthew G. Knepley 52264e22dd4cSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, points[p], &pdepth)); 52274e22dd4cSMatthew G. Knepley if (pdepth) { 52284e22dd4cSMatthew G. Knepley markedFaces = PETSC_TRUE; 52294e22dd4cSMatthew G. Knepley break; 52304e22dd4cSMatthew G. Knepley } 52314e22dd4cSMatthew G. Knepley } 52324e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &points)); 52334e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 52344e22dd4cSMatthew G. Knepley PetscCall(DMPlexCreateSubmesh(dm, label, value, markedFaces, &subdm)); 52354e22dd4cSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &subdm)); 52364e22dd4cSMatthew G. Knepley PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 52374e22dd4cSMatthew G. Knepley } 52389b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 52399566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 52409566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 52419566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 52429566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 52439566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 52449566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 52459318fe57SMatthew G. Knepley if (flg) { 52469566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 52479566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 52489318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 52499318fe57SMatthew G. Knepley } 5250b23db253SStefano Zampini if (prerefine) PetscCall(DMLocalizeCoordinates(dm)); 52519b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 52529b44eab4SMatthew G. Knepley DM rdm; 52539b44eab4SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 52549b44eab4SMatthew G. Knepley 5255dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 52569566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 525769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 5258dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 525961a622f3SMatthew G. Knepley if (coordFunc && remap) { 52609566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 52619b44eab4SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 52629b44eab4SMatthew G. Knepley } 52639b44eab4SMatthew G. Knepley } 52649566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 52659318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 52669566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 52679318fe57SMatthew G. Knepley if (extLayers) { 52689318fe57SMatthew G. Knepley DM edm; 52699318fe57SMatthew G. Knepley 52709566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 527169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 527248d16a33SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = NULL; 5273dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5274d410b0cfSMatthew G. Knepley extLayers = 0; 52755e17fc22SAidan Hamilton PetscCall(DMGetDimension(dm, &dim)); 52769318fe57SMatthew G. Knepley } 5277bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 52786bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 52799566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 52806bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 52819566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 5282adc21957SMatthew G. Knepley if (reorder == DM_REORDER_DEFAULT_TRUE || flg) { 5283bdf63967SMatthew G. Knepley DM pdm; 5284bdf63967SMatthew G. Knepley IS perm; 5285bdf63967SMatthew G. Knepley 52869566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 52879566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 52889566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 528969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 5290dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5291bdf63967SMatthew G. Knepley } 52929b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 52939566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 5294c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 5295a286e215SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute_save_sf", "Flag to save the migration SF", "DMPlexSetMigrationSF", saveSF, &saveSF, NULL)); 5296dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 52979b44eab4SMatthew G. Knepley if (distribute) { 52989b44eab4SMatthew G. Knepley DM pdm = NULL; 52999b44eab4SMatthew G. Knepley PetscPartitioner part; 5300a286e215SMatthew G. Knepley PetscSF sfMigration; 53019b44eab4SMatthew G. Knepley 53029566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 53039566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 5304a286e215SMatthew G. Knepley PetscCall(DMPlexDistribute(dm, overlap, &sfMigration, &pdm)); 53055d2873a6SJames Wright if (pdm) { 53065d2873a6SJames Wright // Delete the local section to force the existing one to be rebuilt with the distributed DM 53075d2873a6SJames Wright PetscCall(DMSetLocalSection(dm, pdm->localSection)); 53085d2873a6SJames Wright PetscCall(DMPlexReplace_Internal(dm, &pdm)); 53095d2873a6SJames Wright } 5310a286e215SMatthew G. Knepley if (saveSF) PetscCall(DMPlexSetMigrationSF(dm, sfMigration)); 5311a286e215SMatthew G. Knepley PetscCall(PetscSFDestroy(&sfMigration)); 53129b44eab4SMatthew G. Knepley } 53134054ae39SJames Wright 53144054ae39SJames Wright { 53154054ae39SJames Wright PetscBool useBoxLabel = PETSC_FALSE; 53164054ae39SJames Wright PetscCall(PetscOptionsBool("-dm_plex_box_label", "Create 'Face Sets' assuming boundary faces align with cartesian directions", "DMCreate", useBoxLabel, &useBoxLabel, NULL)); 5317d7d2d1d2SJames Wright if (useBoxLabel) { 5318d7d2d1d2SJames Wright PetscInt n = 3; 5319d7d2d1d2SJames Wright DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 5320d7d2d1d2SJames Wright 5321d7d2d1d2SJames Wright PetscCall(PetscOptionsEnumArray("-dm_plex_box_label_bd", "Boundary type for each dimension when using -dm_plex_box_label", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 5322d7d2d1d2SJames 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); 5323d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, bdt)); 5324d7d2d1d2SJames Wright } 53254054ae39SJames Wright } 5326d2b2dc1eSMatthew G. Knepley /* Must check CEED options before creating function space for coordinates */ 5327d2b2dc1eSMatthew G. Knepley { 5328d2b2dc1eSMatthew G. Knepley PetscBool useCeed = PETSC_FALSE, flg; 5329d2b2dc1eSMatthew G. Knepley 5330d2b2dc1eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_use_ceed", "Use LibCEED as the FEM backend", "DMPlexSetUseCeed", useCeed, &useCeed, &flg)); 5331d2b2dc1eSMatthew G. Knepley if (flg) PetscCall(DMPlexSetUseCeed(dm, useCeed)); 5332d2b2dc1eSMatthew G. Knepley } 53339318fe57SMatthew G. Knepley /* Create coordinate space */ 5334530e699aSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, NULL)); 5335530e699aSMatthew G. Knepley if (coordSpace) { 533661a622f3SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5337e44f6aebSMatthew G. Knepley PetscInt degree = 1, deg; 53385515ebd3SMatthew G. Knepley PetscInt height = 0; 53395515ebd3SMatthew G. Knepley DM cdm; 5340530e699aSMatthew G. Knepley PetscBool localize = PETSC_TRUE, sparseLocalize = PETSC_TRUE; 53419318fe57SMatthew G. Knepley 53429566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 5343e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDegree_Internal(dm, °)); 5344e44f6aebSMatthew G. Knepley if (coordSpace && deg <= 1) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_TRUE, mesh->coordFunc)); 53455515ebd3SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5346530e699aSMatthew G. Knepley if (!coordSpace) { 534761a622f3SMatthew G. Knepley PetscDS cds; 534861a622f3SMatthew G. Knepley PetscObject obj; 534961a622f3SMatthew G. Knepley PetscClassId id; 535061a622f3SMatthew G. Knepley 53519566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 53529566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 53539566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 535461a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 535561a622f3SMatthew G. Knepley PetscContainer dummy; 535661a622f3SMatthew G. Knepley 53579566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 53589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 53599566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 53609566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 53619566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 536261a622f3SMatthew G. Knepley } 536361a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 536461a622f3SMatthew G. Knepley } 5365c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_localize", "Localize mesh coordinates", "", localize, &localize, NULL)); 5366c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "DMSetSparseLocalize", sparseLocalize, &sparseLocalize, &flg)); 5367c3db174cSMatthew G. Knepley if (flg) PetscCall(DMSetSparseLocalize(dm, sparseLocalize)); 53685515ebd3SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg)); 53695515ebd3SMatthew G. Knepley if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height)); 5370c3db174cSMatthew G. Knepley if (localize) PetscCall(DMLocalizeCoordinates(dm)); 53719318fe57SMatthew G. Knepley } 537268d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 537361a622f3SMatthew G. Knepley remap = PETSC_TRUE; 53749566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 53759566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 53769566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 53779566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 537868d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 5379acdc6f61SToby Isaac DM *dms, coarseDM; 538068d4fef7SMatthew G. Knepley 53819566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 53829566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 53839566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 53849566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 538568d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 53869566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 538768d4fef7SMatthew G. Knepley if (refine == 1) { 53889566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 53899566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 539068d4fef7SMatthew G. Knepley } else { 53919566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 53929566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 53939566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 53949566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 539568d4fef7SMatthew G. Knepley } 53969566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 53979566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 539868d4fef7SMatthew G. Knepley /* Free DMs */ 539968d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 5400dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 54019566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 540268d4fef7SMatthew G. Knepley } 54039566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 540468d4fef7SMatthew G. Knepley } else { 540568d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 54069318fe57SMatthew G. Knepley DM rdm; 540751a74b61SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 540868d4fef7SMatthew G. Knepley 5409dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54109566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 541168d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 541269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 5413dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 541461a622f3SMatthew G. Knepley if (coordFunc && remap) { 54159566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 541651a74b61SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 541751a74b61SMatthew G. Knepley } 541868d4fef7SMatthew G. Knepley } 541968d4fef7SMatthew G. Knepley } 54203cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 54219566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 54229566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 5423b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 5424b653a561SMatthew G. Knepley DM *dms; 5425b653a561SMatthew G. Knepley 54269566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 54279566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 5428b653a561SMatthew G. Knepley /* Free DMs */ 5429b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 5430dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 54319566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 5432b653a561SMatthew G. Knepley } 54339566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 5434b653a561SMatthew G. Knepley } else { 5435b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 54369318fe57SMatthew G. Knepley DM cdm; 54379318fe57SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 54383cf6fe12SMatthew G. Knepley 5439dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54409566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 54413cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 544269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 5443dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54449318fe57SMatthew G. Knepley if (coordFunc) { 54459566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 54469318fe57SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 54479318fe57SMatthew G. Knepley } 54483cf6fe12SMatthew G. Knepley } 5449b653a561SMatthew G. Knepley } 5450be664eb1SMatthew G. Knepley // Handle coordinate remapping 5451be664eb1SMatthew G. Knepley remap = PETSC_FALSE; 5452be664eb1SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_coord_remap", "Flag to control coordinate remapping", "", remap, &remap, NULL)); 5453be664eb1SMatthew G. Knepley if (remap) { 5454be664eb1SMatthew G. Knepley DMPlexCoordMap map = DM_COORD_MAP_NONE; 5455be664eb1SMatthew G. Knepley PetscPointFunc mapFunc = NULL; 5456be664eb1SMatthew G. Knepley PetscScalar params[16]; 5457f45b553cSPierre Jolivet PetscInt Np = PETSC_STATIC_ARRAY_LENGTH(params), cdim; 5458be664eb1SMatthew G. Knepley MPI_Comm comm; 5459be664eb1SMatthew G. Knepley 5460be664eb1SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 5461be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 5462be664eb1SMatthew G. Knepley PetscCall(PetscOptionsScalarArray("-dm_coord_map_params", "Parameters for the coordinate remapping", "", params, &Np, &flg)); 5463be664eb1SMatthew G. Knepley if (!flg) Np = 0; 5464be664eb1SMatthew G. Knepley // TODO Allow user to pass a map function by name 5465be664eb1SMatthew G. Knepley PetscCall(PetscOptionsEnum("-dm_coord_map", "Coordinate mapping for built-in mesh", "", DMPlexCoordMaps, (PetscEnum)map, (PetscEnum *)&map, &flg)); 5466be664eb1SMatthew G. Knepley if (flg) { 5467be664eb1SMatthew G. Knepley switch (map) { 5468be664eb1SMatthew G. Knepley case DM_COORD_MAP_NONE: 5469be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5470be664eb1SMatthew G. Knepley break; 5471be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHEAR: 5472be664eb1SMatthew G. Knepley mapFunc = coordMap_shear; 5473be664eb1SMatthew G. Knepley if (!Np) { 5474be664eb1SMatthew G. Knepley Np = cdim + 1; 5475be664eb1SMatthew G. Knepley params[0] = 0; 5476be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5477be664eb1SMatthew G. Knepley } 5478be664eb1SMatthew 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); 5479be664eb1SMatthew G. Knepley break; 5480be664eb1SMatthew G. Knepley case DM_COORD_MAP_FLARE: 5481be664eb1SMatthew G. Knepley mapFunc = coordMap_flare; 5482be664eb1SMatthew G. Knepley if (!Np) { 5483be664eb1SMatthew G. Knepley Np = cdim + 1; 5484be664eb1SMatthew G. Knepley params[0] = 0; 5485be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5486be664eb1SMatthew G. Knepley } 5487be664eb1SMatthew 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); 5488be664eb1SMatthew G. Knepley break; 5489be664eb1SMatthew G. Knepley case DM_COORD_MAP_ANNULUS: 5490be664eb1SMatthew G. Knepley mapFunc = coordMap_annulus; 5491be664eb1SMatthew G. Knepley if (!Np) { 5492be664eb1SMatthew G. Knepley Np = 2; 5493be664eb1SMatthew G. Knepley params[0] = 1.; 5494be664eb1SMatthew G. Knepley params[1] = 2.; 5495be664eb1SMatthew G. Knepley } 5496be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The annulus coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5497be664eb1SMatthew G. Knepley break; 5498be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHELL: 5499be664eb1SMatthew G. Knepley mapFunc = coordMap_shell; 5500be664eb1SMatthew G. Knepley if (!Np) { 5501be664eb1SMatthew G. Knepley Np = 2; 5502be664eb1SMatthew G. Knepley params[0] = 1.; 5503be664eb1SMatthew G. Knepley params[1] = 2.; 5504be664eb1SMatthew G. Knepley } 5505be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The spherical shell coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5506be664eb1SMatthew G. Knepley break; 5507530e699aSMatthew G. Knepley case DM_COORD_MAP_SINUSOID: 5508530e699aSMatthew G. Knepley mapFunc = coordMap_sinusoid; 5509530e699aSMatthew G. Knepley if (!Np) { 5510530e699aSMatthew G. Knepley Np = 3; 5511530e699aSMatthew G. Knepley params[0] = 1.; 5512530e699aSMatthew G. Knepley params[1] = 1.; 5513530e699aSMatthew G. Knepley params[2] = 1.; 5514530e699aSMatthew G. Knepley } 5515530e699aSMatthew G. Knepley PetscCheck(Np == 3, comm, PETSC_ERR_ARG_WRONG, "The sinusoidal coordinate map must have 3 parameters, not %" PetscInt_FMT, Np); 5516530e699aSMatthew G. Knepley break; 5517be664eb1SMatthew G. Knepley default: 5518be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5519be664eb1SMatthew G. Knepley } 5520be664eb1SMatthew G. Knepley } 5521be664eb1SMatthew G. Knepley if (Np) { 5522be664eb1SMatthew G. Knepley DM cdm; 5523be664eb1SMatthew G. Knepley PetscDS cds; 5524be664eb1SMatthew G. Knepley 5525be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5526be664eb1SMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 5527be664eb1SMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, Np, params)); 5528be664eb1SMatthew G. Knepley } 5529be664eb1SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, mapFunc)); 5530be664eb1SMatthew G. Knepley } 5531909dfd52SMatthew G. Knepley /* Handle ghost cells */ 55329566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 5533909dfd52SMatthew G. Knepley if (ghostCells) { 5534909dfd52SMatthew G. Knepley DM gdm; 5535909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 5536909dfd52SMatthew G. Knepley 5537909dfd52SMatthew G. Knepley lname[0] = '\0'; 55389566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 55399566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 554069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 5541909dfd52SMatthew G. Knepley } 55426913077dSMatthew G. Knepley /* Handle 1D order */ 5543adc21957SMatthew G. Knepley if (reorder != DM_REORDER_DEFAULT_FALSE && dim == 1) { 55446913077dSMatthew G. Knepley DM cdm, rdm; 55456913077dSMatthew G. Knepley PetscDS cds; 55466913077dSMatthew G. Knepley PetscObject obj; 55476913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 55486913077dSMatthew G. Knepley IS perm; 55496bc1bd01Sksagiyam PetscInt Nf; 55506913077dSMatthew G. Knepley PetscBool distributed; 55516913077dSMatthew G. Knepley 55529566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 55539566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 55549566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 55559566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 55566913077dSMatthew G. Knepley if (Nf) { 55579566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 55589566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 55596913077dSMatthew G. Knepley } 55606bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 55619566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 55629566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 556369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 55649566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 55656913077dSMatthew G. Knepley } 55666913077dSMatthew G. Knepley } 55673cf6fe12SMatthew G. Knepley /* Handle */ 5568dd4c3f67SMatthew G. Knepley non_refine: 5569dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 557022d6dc08SStefano Zampini char *phases[16]; 557122d6dc08SStefano Zampini PetscInt Nphases = 16; 557222d6dc08SStefano Zampini PetscCall(PetscOptionsStringArray("-dm_plex_option_phases", "Option phase prefixes", "DMSetFromOptions", phases, &Nphases, &flg)); 5573d0609cedSBarry Smith PetscOptionsHeadEnd(); 557422d6dc08SStefano Zampini 557522d6dc08SStefano Zampini // Phases 557622d6dc08SStefano Zampini if (flg) { 5577530e699aSMatthew G. Knepley DM cdm; 5578530e699aSMatthew G. Knepley char *oldPrefix, *oldCoordPrefix; 5579530e699aSMatthew G. Knepley const char *tmp; 558022d6dc08SStefano Zampini 5581530e699aSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5582530e699aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &tmp)); 5583530e699aSMatthew G. Knepley PetscCall(PetscStrallocpy(tmp, &oldPrefix)); 5584530e699aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)cdm, &tmp)); 5585530e699aSMatthew G. Knepley PetscCall(PetscStrallocpy(tmp, &oldCoordPrefix)); 558622d6dc08SStefano Zampini for (PetscInt ph = 0; ph < Nphases; ++ph) { 558722d6dc08SStefano Zampini PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, phases[ph])); 5588530e699aSMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)cdm, phases[ph])); 558922d6dc08SStefano Zampini PetscCall(PetscInfo(dm, "Options phase %s for DM %s\n", phases[ph], dm->hdr.name)); 559022d6dc08SStefano Zampini PetscCall(DMSetFromOptions(dm)); 559122d6dc08SStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix)); 5592530e699aSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5593530e699aSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)cdm, oldCoordPrefix)); 559422d6dc08SStefano Zampini PetscCall(PetscFree(phases[ph])); 559522d6dc08SStefano Zampini } 5596530e699aSMatthew G. Knepley PetscCall(PetscFree(oldPrefix)); 5597530e699aSMatthew G. Knepley PetscCall(PetscFree(oldCoordPrefix)); 559822d6dc08SStefano Zampini } 55993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56000a6ba040SMatthew G. Knepley } 56010a6ba040SMatthew G. Knepley 5602d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) 5603d71ae5a4SJacob Faibussowitsch { 5604552f7358SJed Brown PetscFunctionBegin; 56059566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 56069566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 56079566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 56089566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 56099566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 56109566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 56113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5612552f7358SJed Brown } 5613552f7358SJed Brown 5614d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) 5615d71ae5a4SJacob Faibussowitsch { 5616552f7358SJed Brown PetscFunctionBegin; 56179566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 56189566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 56199566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 56203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5621552f7358SJed Brown } 5622552f7358SJed Brown 5623d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 5624d71ae5a4SJacob Faibussowitsch { 5625793f3fe5SMatthew G. Knepley PetscInt depth, d; 5626793f3fe5SMatthew G. Knepley 5627793f3fe5SMatthew G. Knepley PetscFunctionBegin; 56289566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 5629793f3fe5SMatthew G. Knepley if (depth == 1) { 56309566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 56319566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 56329566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 56339371c9d4SSatish Balay else { 56349371c9d4SSatish Balay *pStart = 0; 56359371c9d4SSatish Balay *pEnd = 0; 56369371c9d4SSatish Balay } 5637793f3fe5SMatthew G. Knepley } else { 56389566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 5639793f3fe5SMatthew G. Knepley } 56403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5641793f3fe5SMatthew G. Knepley } 5642793f3fe5SMatthew G. Knepley 5643d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 5644d71ae5a4SJacob Faibussowitsch { 5645502a2867SDave May PetscSF sf; 56466497c311SBarry Smith PetscMPIInt niranks, njranks; 56476497c311SBarry Smith PetscInt n; 56480a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 56490a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 5650502a2867SDave May 56512f356facSMatthew G. Knepley PetscFunctionBegin; 56529566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 56530a19bb7dSprj- if (!data->neighbors) { 56549566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 56559566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 56569566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 56579566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 56589566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 56599566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 56600a19bb7dSprj- n = njranks + niranks; 56619566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 56620a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 56639566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 56640a19bb7dSprj- } 56650a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 56660a19bb7dSprj- if (ranks) { 56670a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 56680a19bb7dSprj- else *ranks = NULL; 56690a19bb7dSprj- } 56703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5671502a2867SDave May } 5672502a2867SDave May 56731eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 56741eb70e55SToby Isaac 5675d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm) 5676d71ae5a4SJacob Faibussowitsch { 5677552f7358SJed Brown PetscFunctionBegin; 5678552f7358SJed Brown dm->ops->view = DMView_Plex; 56792c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 5680552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 568138221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 5682552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 56831bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 5684adc21957SMatthew G. Knepley dm->ops->createsectionpermutation = DMCreateSectionPermutation_Plex; 568566ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 5686552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 5687552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 5688184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 56890298fd71SBarry Smith dm->ops->createfieldis = NULL; 5690552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 5691f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 56920a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 5693552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 5694bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 5695bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 5696b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 56975a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 5698552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 56990a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 57000a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 5701b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 5702d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 57030298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 57040298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 57050298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 57060298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 5707552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 5708552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 57092adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 5710793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 5711552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 57120709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 57130709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 5714bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 57158c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 5716ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 57170709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 5718b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 57192a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 572028d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 57216c6a6b79SMatthew G. Knepley dm->ops->getlocalboundingbox = DMGetLocalBoundingBox_Coordinates; 5722907a3e9cSStefano Zampini dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_Plex; 5723907a3e9cSStefano Zampini dm->ops->createddscatters = DMCreateDomainDecompositionScatters_Plex; 57249566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 57256c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 57269566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 57279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 57289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 57299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 57306bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 57316bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 5732adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", DMReorderSectionGetDefault_Plex)); 5733adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", DMReorderSectionSetDefault_Plex)); 5734adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", DMReorderSectionGetType_Plex)); 5735adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", DMReorderSectionSetType_Plex)); 57369566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 5737c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 5738c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 5739d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", DMPlexGetUseCeed_Plex)); 5740d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", DMPlexSetUseCeed_Plex)); 57413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5742552f7358SJed Brown } 5743552f7358SJed Brown 5744d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 5745d71ae5a4SJacob Faibussowitsch { 574663a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 57471fca310dSJames Wright const PetscSF *face_sfs; 57481fca310dSJames Wright PetscInt num_face_sfs; 574963a16f15SMatthew G. Knepley 575063a16f15SMatthew G. Knepley PetscFunctionBegin; 575163a16f15SMatthew G. Knepley mesh->refct++; 575263a16f15SMatthew G. Knepley (*newdm)->data = mesh; 57531fca310dSJames Wright PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &face_sfs)); 57541fca310dSJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, num_face_sfs, (PetscSF *)face_sfs)); 57559566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 57569566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 57573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 575863a16f15SMatthew G. Knepley } 575963a16f15SMatthew G. Knepley 57608818961aSMatthew G Knepley /*MC 57610b4b7b1cSBarry Smith DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh (or grid), or CW Complex {cite}`cwcomplex`, 57620b4b7b1cSBarry Smith which can be expressed using a Hasse Diagram {cite}`hassediagram`. 576320f4b53cSBarry Smith In the local representation, `Vec`s contain all unknowns in the interior and shared boundary. This is 57640b4b7b1cSBarry Smith specified by a `PetscSection` object. Ownership in the global representation is determined by 5765a1cb98faSBarry Smith ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object. 57668818961aSMatthew G Knepley 5767e5893cccSMatthew G. Knepley Options Database Keys: 5768250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 5769250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 5770250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 5771250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 5772250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 5773250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 5774c3db174cSMatthew G. Knepley . -dm_localize <bool> - Whether to localize coordinates for periodic meshes 5775c3db174cSMatthew G. Knepley . -dm_sparse_localize <bool> - Whether to only localize cells on the periodic boundary 5776250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 5777ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 5778f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 5779f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 5780d5b43468SJose E. Roman . -dm_plex_max_projection_height - Maximum mesh point height used to project locally 5781f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 5782d02c7345SMatthew G. Knepley . -dm_plex_reorder_section - Use specialized blocking if available 5783aaa8cc7dSPierre Jolivet . -dm_plex_check_all - Perform all checks below 5784f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 5785f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 5786f12cf164SMatthew 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 5787f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 5788f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 5789e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 57905962854dSMatthew G. Knepley . -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 57915962854dSMatthew G. Knepley - -dm_plex_print_fvm <num> - View FVM assembly information, such as flux updates 5792e5893cccSMatthew G. Knepley 57938818961aSMatthew G Knepley Level: intermediate 57948818961aSMatthew G Knepley 57951cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection` 57968818961aSMatthew G Knepley M*/ 57978818961aSMatthew G Knepley 5798d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 5799d71ae5a4SJacob Faibussowitsch { 5800552f7358SJed Brown DM_Plex *mesh; 5801412e9a14SMatthew G. Knepley PetscInt unit; 5802552f7358SJed Brown 5803552f7358SJed Brown PetscFunctionBegin; 5804f39ec787SMatthew G. Knepley PetscCall(PetscCitationsRegister(PlexCitation, &Plexcite)); 5805552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58064dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mesh)); 5807adc21957SMatthew G. Knepley dm->reorderSection = DM_REORDER_DEFAULT_NOTSET; 5808552f7358SJed Brown dm->data = mesh; 5809552f7358SJed Brown 5810552f7358SJed Brown mesh->refct = 1; 58119566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 58129566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 5813552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 5814552f7358SJed Brown mesh->refinementLimit = -1.0; 5815e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 5816adc21957SMatthew G. Knepley mesh->reorderDefault = DM_REORDER_DEFAULT_NOTSET; 58171d1f2f2aSksagiyam mesh->distributionName = NULL; 58187d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 58197d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 58205e2c5519SMatthew G. Knepley mesh->interpolatePreferTensor = PETSC_TRUE; 5821552f7358SJed Brown 58229566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 58232e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 5824d9deefdfSMatthew G. Knepley 58258865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 5826552f7358SJed Brown 5827df0420ecSMatthew G. Knepley mesh->depthState = -1; 5828ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 58296113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 5830c29ce622SStefano Zampini mesh->nonempty_comm = MPI_COMM_SELF; 5831552f7358SJed Brown 58329566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 58333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5834552f7358SJed Brown } 5835552f7358SJed Brown 5836552f7358SJed Brown /*@ 5837a1cb98faSBarry Smith DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 5838552f7358SJed Brown 5839d083f849SBarry Smith Collective 5840552f7358SJed Brown 5841552f7358SJed Brown Input Parameter: 5842a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object 5843552f7358SJed Brown 5844552f7358SJed Brown Output Parameter: 5845a1cb98faSBarry Smith . mesh - The `DMPLEX` object 5846552f7358SJed Brown 5847552f7358SJed Brown Level: beginner 5848552f7358SJed Brown 584942747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMCreate()`, `DMSetType()` 5850552f7358SJed Brown @*/ 5851d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 5852d71ae5a4SJacob Faibussowitsch { 5853552f7358SJed Brown PetscFunctionBegin; 58544f572ea9SToby Isaac PetscAssertPointer(mesh, 2); 58559566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 58569566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 58573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5858552f7358SJed Brown } 5859552f7358SJed Brown 5860b09969d6SVaclav Hapla /*@C 5861b0fe842aSMatthew 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 5862a1cb98faSBarry Smith 586320f4b53cSBarry Smith Collective; No Fortran Support 5864b09969d6SVaclav Hapla 5865b09969d6SVaclav Hapla Input Parameters: 5866a1cb98faSBarry Smith + dm - The `DM` 5867b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 5868a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 5869a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DETERMINE` 5870b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 58715e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 5872b09969d6SVaclav Hapla 5873be8c289dSNicolas Barral Output Parameters: 5874a1cb98faSBarry Smith + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 5875be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 5876b09969d6SVaclav Hapla 5877b09969d6SVaclav Hapla Level: advanced 5878b09969d6SVaclav Hapla 5879a1cb98faSBarry Smith Notes: 5880a1cb98faSBarry Smith Two triangles sharing a face 5881a1cb98faSBarry Smith .vb 5882a1cb98faSBarry Smith 5883a1cb98faSBarry Smith 2 5884a1cb98faSBarry Smith / | \ 5885a1cb98faSBarry Smith / | \ 5886a1cb98faSBarry Smith / | \ 5887a1cb98faSBarry Smith 0 0 | 1 3 5888a1cb98faSBarry Smith \ | / 5889a1cb98faSBarry Smith \ | / 5890a1cb98faSBarry Smith \ | / 5891a1cb98faSBarry Smith 1 5892a1cb98faSBarry Smith .ve 5893a1cb98faSBarry Smith would have input 5894a1cb98faSBarry Smith .vb 5895a1cb98faSBarry Smith numCells = 2, numVertices = 4 5896a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 5897a1cb98faSBarry Smith .ve 5898a1cb98faSBarry Smith which would result in the `DMPLEX` 5899a1cb98faSBarry Smith .vb 5900a1cb98faSBarry Smith 5901a1cb98faSBarry Smith 4 5902a1cb98faSBarry Smith / | \ 5903a1cb98faSBarry Smith / | \ 5904a1cb98faSBarry Smith / | \ 5905a1cb98faSBarry Smith 2 0 | 1 5 5906a1cb98faSBarry Smith \ | / 5907a1cb98faSBarry Smith \ | / 5908a1cb98faSBarry Smith \ | / 5909a1cb98faSBarry Smith 3 5910a1cb98faSBarry Smith .ve 5911a1cb98faSBarry Smith 5912a1cb98faSBarry Smith Vertices are implicitly numbered consecutively 0,...,NVertices. 5913a1cb98faSBarry Smith Each rank owns a chunk of numVertices consecutive vertices. 5914a1cb98faSBarry Smith If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 5915a1cb98faSBarry Smith If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 5916a1cb98faSBarry Smith If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 5917a1cb98faSBarry Smith 5918a1cb98faSBarry Smith The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 5919a1cb98faSBarry Smith 59201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 5921a1cb98faSBarry Smith `PetscSF` 5922b09969d6SVaclav Hapla @*/ 5923ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[]) 5924d71ae5a4SJacob Faibussowitsch { 59252464107aSksagiyam PetscSF sfPoint; 59262464107aSksagiyam PetscLayout layout; 592782fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 5928a47d0d45SMatthew G. Knepley 5929a47d0d45SMatthew G. Knepley PetscFunctionBegin; 593025b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 59319566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 593225b6865aSVaclav Hapla /* Get/check global number of vertices */ 593325b6865aSVaclav Hapla { 593425b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 593525b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 593625b6865aSVaclav Hapla 593725b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 59381690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 59399371c9d4SSatish Balay for (i = 0; i < len; i++) 59409371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 594125b6865aSVaclav Hapla ++NVerticesInCells; 5942462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 594325b6865aSVaclav Hapla 594425b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 59459371c9d4SSatish Balay else 59469371c9d4SSatish 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); 594725b6865aSVaclav Hapla } 59489079aca8SVaclav Hapla /* Count locally unique vertices */ 59499079aca8SVaclav Hapla { 59509079aca8SVaclav Hapla PetscHSetI vhash; 59519079aca8SVaclav Hapla PetscInt off = 0; 59529079aca8SVaclav Hapla 59539566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 5954a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 595548a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 5956a47d0d45SMatthew G. Knepley } 59579566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 59589566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 5959ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 59609566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 59619566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 596263a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 5963a47d0d45SMatthew G. Knepley } 59649566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 5965a47d0d45SMatthew G. Knepley /* Create cones */ 59669566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 59679566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 59689566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 59699566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 5970a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 5971a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 5972a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 5973a47d0d45SMatthew G. Knepley PetscInt lv; 5974a47d0d45SMatthew G. Knepley 59759079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 59769079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 59779566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 597863a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 5979961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 5980a47d0d45SMatthew G. Knepley } 5981a47d0d45SMatthew G. Knepley } 59822464107aSksagiyam /* Build point sf */ 59839566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 59849566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 59859566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 59869566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 59879566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 59889566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 59899566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 59909566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 59912464107aSksagiyam if (dm->sf) { 59922464107aSksagiyam const char *prefix; 59932464107aSksagiyam 59949566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 59959566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 59962464107aSksagiyam } 59979566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 59989566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 5999f4f49eeaSPierre Jolivet if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 6000a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 60019566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 60029566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 60039566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 60043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6005a47d0d45SMatthew G. Knepley } 6006a47d0d45SMatthew G. Knepley 6007b0fe842aSMatthew G. Knepley /*@C 6008b0fe842aSMatthew G. Knepley DMPlexBuildFromCellSectionParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) allowing multiple celltypes 6009b0fe842aSMatthew G. Knepley 6010b0fe842aSMatthew G. Knepley Collective; No Fortran Support 6011b0fe842aSMatthew G. Knepley 6012b0fe842aSMatthew G. Knepley Input Parameters: 6013b0fe842aSMatthew G. Knepley + dm - The `DM` 6014b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 6015b0fe842aSMatthew G. Knepley . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 6016b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DETERMINE` 6017b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 6018b0fe842aSMatthew G. Knepley - cells - An array of the global vertex numbers for each cell 6019b0fe842aSMatthew G. Knepley 6020b0fe842aSMatthew G. Knepley Output Parameters: 6021b0fe842aSMatthew G. Knepley + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 6022b0fe842aSMatthew G. Knepley - verticesAdjSaved - (Optional) vertex adjacency array 6023b0fe842aSMatthew G. Knepley 6024b0fe842aSMatthew G. Knepley Level: advanced 6025b0fe842aSMatthew G. Knepley 6026b0fe842aSMatthew G. Knepley Notes: 6027b0fe842aSMatthew G. Knepley A triangle and quadrilateral sharing a face 6028b0fe842aSMatthew G. Knepley .vb 6029b0fe842aSMatthew G. Knepley 2----------3 6030b0fe842aSMatthew G. Knepley / | | 6031b0fe842aSMatthew G. Knepley / | | 6032b0fe842aSMatthew G. Knepley / | | 6033b0fe842aSMatthew G. Knepley 0 0 | 1 | 6034b0fe842aSMatthew G. Knepley \ | | 6035b0fe842aSMatthew G. Knepley \ | | 6036b0fe842aSMatthew G. Knepley \ | | 6037b0fe842aSMatthew G. Knepley 1----------4 6038b0fe842aSMatthew G. Knepley .ve 6039b0fe842aSMatthew G. Knepley would have input 6040b0fe842aSMatthew G. Knepley .vb 6041b0fe842aSMatthew G. Knepley numCells = 2, numVertices = 5 6042b0fe842aSMatthew G. Knepley cells = [0 1 2 1 4 3 2] 6043b0fe842aSMatthew G. Knepley .ve 6044b0fe842aSMatthew G. Knepley which would result in the `DMPLEX` 6045b0fe842aSMatthew G. Knepley .vb 6046b0fe842aSMatthew G. Knepley 4----------5 6047b0fe842aSMatthew G. Knepley / | | 6048b0fe842aSMatthew G. Knepley / | | 6049b0fe842aSMatthew G. Knepley / | | 6050b0fe842aSMatthew G. Knepley 2 0 | 1 | 6051b0fe842aSMatthew G. Knepley \ | | 6052b0fe842aSMatthew G. Knepley \ | | 6053b0fe842aSMatthew G. Knepley \ | | 6054b0fe842aSMatthew G. Knepley 3----------6 6055b0fe842aSMatthew G. Knepley .ve 6056b0fe842aSMatthew G. Knepley 6057b0fe842aSMatthew G. Knepley Vertices are implicitly numbered consecutively 0,...,NVertices. 6058b0fe842aSMatthew G. Knepley Each rank owns a chunk of numVertices consecutive vertices. 6059b0fe842aSMatthew G. Knepley If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 6060b0fe842aSMatthew 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. 6061b0fe842aSMatthew G. Knepley If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 6062b0fe842aSMatthew G. Knepley 6063b0fe842aSMatthew G. Knepley The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 6064b0fe842aSMatthew G. Knepley 6065b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexCreateFromCellSectionParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 6066b0fe842aSMatthew G. Knepley `PetscSF` 6067b0fe842aSMatthew G. Knepley @*/ 6068ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellSectionParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[]) 6069b0fe842aSMatthew G. Knepley { 6070b0fe842aSMatthew G. Knepley PetscSF sfPoint; 6071b0fe842aSMatthew G. Knepley PetscLayout layout; 6072b0fe842aSMatthew G. Knepley PetscInt numVerticesAdj, *verticesAdj, *cones, cStart, cEnd, len; 6073b0fe842aSMatthew G. Knepley 6074b0fe842aSMatthew G. Knepley PetscFunctionBegin; 6075b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, NVertices, 4); 6076b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 6077b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetChart(cellSection, &cStart, &cEnd)); 6078b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(cellSection, &len)); 6079b0fe842aSMatthew 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); 6080b0fe842aSMatthew G. Knepley /* Get/check global number of vertices */ 6081b0fe842aSMatthew G. Knepley { 6082b0fe842aSMatthew G. Knepley PetscInt NVerticesInCells; 6083b0fe842aSMatthew G. Knepley 6084b0fe842aSMatthew G. Knepley /* NVerticesInCells = max(cells) + 1 */ 6085b0fe842aSMatthew G. Knepley NVerticesInCells = PETSC_MIN_INT; 6086b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) 6087b0fe842aSMatthew G. Knepley if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 6088b0fe842aSMatthew G. Knepley ++NVerticesInCells; 6089b0fe842aSMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 6090b0fe842aSMatthew G. Knepley 6091b0fe842aSMatthew G. Knepley if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 6092b0fe842aSMatthew G. Knepley else 6093b0fe842aSMatthew 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); 6094b0fe842aSMatthew G. Knepley } 6095b0fe842aSMatthew G. Knepley /* Count locally unique vertices */ 6096b0fe842aSMatthew G. Knepley { 6097b0fe842aSMatthew G. Knepley PetscHSetI vhash; 6098b0fe842aSMatthew G. Knepley PetscInt off = 0; 6099b0fe842aSMatthew G. Knepley 6100b0fe842aSMatthew G. Knepley PetscCall(PetscHSetICreate(&vhash)); 6101b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) PetscCall(PetscHSetIAdd(vhash, cells[i])); 6102b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 6103b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 6104b0fe842aSMatthew G. Knepley else verticesAdj = *verticesAdjSaved; 6105b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 6106b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIDestroy(&vhash)); 6107b0fe842aSMatthew 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); 6108b0fe842aSMatthew G. Knepley } 6109b0fe842aSMatthew G. Knepley PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 6110b0fe842aSMatthew G. Knepley /* Create cones */ 6111b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 6112b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 6113b0fe842aSMatthew G. Knepley PetscInt dof; 6114b0fe842aSMatthew G. Knepley 6115b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 6116b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetConeSize(dm, c, dof)); 6117b0fe842aSMatthew G. Knepley } 6118b0fe842aSMatthew G. Knepley PetscCall(DMSetUp(dm)); 6119b0fe842aSMatthew G. Knepley PetscCall(DMPlexGetCones(dm, &cones)); 6120b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 6121b0fe842aSMatthew G. Knepley PetscInt dof, off; 6122b0fe842aSMatthew G. Knepley 6123b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 6124b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cellSection, c, &off)); 6125b0fe842aSMatthew G. Knepley for (PetscInt p = off; p < off + dof; ++p) { 6126b0fe842aSMatthew G. Knepley const PetscInt gv = cells[p]; 6127b0fe842aSMatthew G. Knepley PetscInt lv; 6128b0fe842aSMatthew G. Knepley 6129b0fe842aSMatthew G. Knepley /* Positions within verticesAdj form 0-based local vertex numbering; 6130b0fe842aSMatthew G. Knepley we need to shift it by numCells to get correct DAG points (cells go first) */ 6131b0fe842aSMatthew G. Knepley PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 6132b0fe842aSMatthew G. Knepley PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 6133b0fe842aSMatthew G. Knepley cones[p] = lv + numCells; 6134b0fe842aSMatthew G. Knepley } 6135b0fe842aSMatthew G. Knepley } 6136b0fe842aSMatthew G. Knepley /* Build point sf */ 6137b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 6138b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetSize(layout, NVertices)); 6139b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 6140b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetBlockSize(layout, 1)); 6141b0fe842aSMatthew G. Knepley PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 6142b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutDestroy(&layout)); 6143b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 6144b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 6145b0fe842aSMatthew G. Knepley if (dm->sf) { 6146b0fe842aSMatthew G. Knepley const char *prefix; 6147b0fe842aSMatthew G. Knepley 6148b0fe842aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 6149b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 6150b0fe842aSMatthew G. Knepley } 6151b0fe842aSMatthew G. Knepley PetscCall(DMSetPointSF(dm, sfPoint)); 6152b0fe842aSMatthew G. Knepley PetscCall(PetscSFDestroy(&sfPoint)); 6153b0fe842aSMatthew G. Knepley if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 6154b0fe842aSMatthew G. Knepley /* Fill in the rest of the topology structure */ 6155b0fe842aSMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 6156b0fe842aSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 6157b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 6158b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 6159b0fe842aSMatthew G. Knepley } 6160b0fe842aSMatthew G. Knepley 6161cc4c1da9SBarry Smith /*@ 6162a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 6163a1cb98faSBarry Smith 616420f4b53cSBarry Smith Collective; No Fortran Support 6165b09969d6SVaclav Hapla 6166b09969d6SVaclav Hapla Input Parameters: 6167a1cb98faSBarry Smith + dm - The `DM` 6168b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6169a1cb98faSBarry Smith . sfVert - `PetscSF` describing complete vertex ownership 6170b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6171b09969d6SVaclav Hapla 6172b09969d6SVaclav Hapla Level: advanced 6173b09969d6SVaclav Hapla 61741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 6175b09969d6SVaclav Hapla @*/ 6176d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 6177d71ae5a4SJacob Faibussowitsch { 6178a47d0d45SMatthew G. Knepley PetscSection coordSection; 6179a47d0d45SMatthew G. Knepley Vec coordinates; 6180a47d0d45SMatthew G. Knepley PetscScalar *coords; 61811edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 6182835f2295SStefano Zampini PetscMPIInt spaceDimi; 6183a47d0d45SMatthew G. Knepley 6184a47d0d45SMatthew G. Knepley PetscFunctionBegin; 61859566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 61869566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 61871dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 61889566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 61899566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 61901dca8a05SBarry 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); 61919566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 61929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 61939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 61949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 61951edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 61969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 61979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 6198a47d0d45SMatthew G. Knepley } 61999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 62009566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 62019566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 62029566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 62039566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 62049566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 62059566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 62069566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6207a47d0d45SMatthew G. Knepley { 6208a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 6209a47d0d45SMatthew G. Knepley 6210a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 6211835f2295SStefano Zampini PetscCall(PetscMPIIntCast(spaceDim, &spaceDimi)); 6212835f2295SStefano Zampini PetscCallMPI(MPI_Type_contiguous(spaceDimi, MPIU_SCALAR, &coordtype)); 62139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 621421016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 621521016a8bSBarry Smith { 621621016a8bSBarry Smith PetscScalar *svertexCoords; 621721016a8bSBarry Smith PetscInt i; 62189566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 62193612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 62209566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 62219566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 62229566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 622321016a8bSBarry Smith } 622421016a8bSBarry Smith #else 62259566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 62269566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 622721016a8bSBarry Smith #endif 62289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 6229a47d0d45SMatthew G. Knepley } 62309566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 62319566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 62329566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 62339566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 62343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6235a47d0d45SMatthew G. Knepley } 6236a47d0d45SMatthew G. Knepley 6237c3edce3dSSatish Balay /*@ 6238b0fe842aSMatthew 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 6239a1cb98faSBarry Smith 6240a1cb98faSBarry Smith Collective 6241a47d0d45SMatthew G. Knepley 6242a47d0d45SMatthew G. Knepley Input Parameters: 6243a47d0d45SMatthew G. Knepley + comm - The communicator 6244a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 6245a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 6246a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 6247a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DECIDE` 6248a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 6249a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6250a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 6251a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 6252a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6253a47d0d45SMatthew G. Knepley 6254d8d19677SJose E. Roman Output Parameters: 6255a1cb98faSBarry Smith + dm - The `DM` 6256a1cb98faSBarry Smith . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 625760225df5SJacob Faibussowitsch - verticesAdj - (Optional) vertex adjacency array 6258a47d0d45SMatthew G. Knepley 6259b09969d6SVaclav Hapla Level: intermediate 6260a47d0d45SMatthew G. Knepley 6261a1cb98faSBarry Smith Notes: 6262a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 6263a1cb98faSBarry Smith `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 6264a1cb98faSBarry Smith 6265a1cb98faSBarry Smith See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters. 6266a1cb98faSBarry Smith 6267a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 6268a1cb98faSBarry Smith 62691cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 6270a47d0d45SMatthew G. Knepley @*/ 6271ce78bad3SBarry Smith PetscErrorCode DMPlexCreateFromCellListParallelPetsc(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdj[], DM *dm) 6272d71ae5a4SJacob Faibussowitsch { 6273a47d0d45SMatthew G. Knepley PetscSF sfVert; 6274a47d0d45SMatthew G. Knepley 6275a47d0d45SMatthew G. Knepley PetscFunctionBegin; 62769566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 62779566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 6278a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 6279064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 62809566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 62819566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 6282a47d0d45SMatthew G. Knepley if (interpolate) { 62835fd9971aSMatthew G. Knepley DM idm; 6284a47d0d45SMatthew G. Knepley 62859566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 62869566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 6287a47d0d45SMatthew G. Knepley *dm = idm; 6288a47d0d45SMatthew G. Knepley } 62899566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 629018d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 62919566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 62923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6293a47d0d45SMatthew G. Knepley } 6294a47d0d45SMatthew G. Knepley 6295cc4c1da9SBarry Smith /*@ 6296b0fe842aSMatthew G. Knepley DMPlexCreateFromCellSectionParallel - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) and supports multiple celltypes 6297b0fe842aSMatthew G. Knepley 6298b0fe842aSMatthew G. Knepley Collective 6299b0fe842aSMatthew G. Knepley 6300b0fe842aSMatthew G. Knepley Input Parameters: 6301b0fe842aSMatthew G. Knepley + comm - The communicator 6302b0fe842aSMatthew G. Knepley . dim - The topological dimension of the mesh 6303b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 6304b0fe842aSMatthew G. Knepley . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 6305b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DECIDE` 6306b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 6307b0fe842aSMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6308b0fe842aSMatthew G. Knepley . cells - An array of the global vertex numbers for each cell 6309b0fe842aSMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 6310b0fe842aSMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6311b0fe842aSMatthew G. Knepley 6312b0fe842aSMatthew G. Knepley Output Parameters: 6313b0fe842aSMatthew G. Knepley + dm - The `DM` 6314b0fe842aSMatthew G. Knepley . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 6315b0fe842aSMatthew G. Knepley - verticesAdj - (Optional) vertex adjacency array 6316b0fe842aSMatthew G. Knepley 6317b0fe842aSMatthew G. Knepley Level: intermediate 6318b0fe842aSMatthew G. Knepley 6319b0fe842aSMatthew G. Knepley Notes: 6320b0fe842aSMatthew G. Knepley This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 6321b0fe842aSMatthew G. Knepley `DMPlexBuildFromCellSectionParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 6322b0fe842aSMatthew G. Knepley 6323b0fe842aSMatthew G. Knepley See `DMPlexBuildFromCellSectionParallel()` for an example and details about the topology-related parameters. 6324b0fe842aSMatthew G. Knepley 6325b0fe842aSMatthew G. Knepley See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 6326b0fe842aSMatthew G. Knepley 6327b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 6328b0fe842aSMatthew G. Knepley @*/ 6329ce78bad3SBarry Smith PetscErrorCode DMPlexCreateFromCellSectionParallel(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdj[], DM *dm) 6330b0fe842aSMatthew G. Knepley { 6331b0fe842aSMatthew G. Knepley PetscSF sfVert; 6332b0fe842aSMatthew G. Knepley 6333b0fe842aSMatthew G. Knepley PetscFunctionBegin; 6334b0fe842aSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 6335b0fe842aSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 6336b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 6337b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 6338b0fe842aSMatthew G. Knepley PetscCall(DMSetDimension(*dm, dim)); 6339b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildFromCellSectionParallel(*dm, numCells, numVertices, NVertices, cellSection, cells, &sfVert, verticesAdj)); 6340b0fe842aSMatthew G. Knepley if (interpolate) { 6341b0fe842aSMatthew G. Knepley DM idm; 6342b0fe842aSMatthew G. Knepley 6343b0fe842aSMatthew G. Knepley PetscCall(DMPlexInterpolate(*dm, &idm)); 6344b0fe842aSMatthew G. Knepley PetscCall(DMDestroy(dm)); 6345b0fe842aSMatthew G. Knepley *dm = idm; 6346b0fe842aSMatthew G. Knepley } 6347b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 6348b0fe842aSMatthew G. Knepley if (vertexSF) *vertexSF = sfVert; 6349b0fe842aSMatthew G. Knepley else PetscCall(PetscSFDestroy(&sfVert)); 6350b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 6351b0fe842aSMatthew G. Knepley } 6352b0fe842aSMatthew G. Knepley 6353b0fe842aSMatthew G. Knepley /*@ 6354a1cb98faSBarry Smith DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) 6355a1cb98faSBarry Smith 635620f4b53cSBarry Smith Collective; No Fortran Support 63579298eaa6SMatthew G Knepley 63589298eaa6SMatthew G Knepley Input Parameters: 6359a1cb98faSBarry Smith + dm - The `DM` 6360b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 6361a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE` 63629298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 6363a3b724e8SBarry Smith - cells - An array of `numCells` x `numCorners` numbers, the global vertex numbers for each cell 63649298eaa6SMatthew G Knepley 6365b09969d6SVaclav Hapla Level: advanced 63669298eaa6SMatthew G Knepley 6367b09969d6SVaclav Hapla Notes: 6368b09969d6SVaclav Hapla Two triangles sharing a face 6369a1cb98faSBarry Smith .vb 63709298eaa6SMatthew G Knepley 6371a1cb98faSBarry Smith 2 6372a1cb98faSBarry Smith / | \ 6373a1cb98faSBarry Smith / | \ 6374a1cb98faSBarry Smith / | \ 6375a1cb98faSBarry Smith 0 0 | 1 3 6376a1cb98faSBarry Smith \ | / 6377a1cb98faSBarry Smith \ | / 6378a1cb98faSBarry Smith \ | / 6379a1cb98faSBarry Smith 1 6380a1cb98faSBarry Smith .ve 6381a1cb98faSBarry Smith would have input 6382a1cb98faSBarry Smith .vb 6383a1cb98faSBarry Smith numCells = 2, numVertices = 4 6384a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 6385a1cb98faSBarry Smith .ve 6386a1cb98faSBarry Smith which would result in the `DMPLEX` 6387a1cb98faSBarry Smith .vb 6388a1cb98faSBarry Smith 6389a1cb98faSBarry Smith 4 6390a1cb98faSBarry Smith / | \ 6391a1cb98faSBarry Smith / | \ 6392a1cb98faSBarry Smith / | \ 6393a1cb98faSBarry Smith 2 0 | 1 5 6394a1cb98faSBarry Smith \ | / 6395a1cb98faSBarry Smith \ | / 6396a1cb98faSBarry Smith \ | / 6397a1cb98faSBarry Smith 3 6398a1cb98faSBarry Smith .ve 6399a1cb98faSBarry Smith 6400a1cb98faSBarry Smith If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1. 640125b6865aSVaclav Hapla 64021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 6403b09969d6SVaclav Hapla @*/ 6404d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 6405d71ae5a4SJacob Faibussowitsch { 6406961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 6407b09969d6SVaclav Hapla 6408b09969d6SVaclav Hapla PetscFunctionBegin; 64099566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 64109566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 641125b6865aSVaclav Hapla /* Get/check global number of vertices */ 641225b6865aSVaclav Hapla { 641325b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 641425b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 641525b6865aSVaclav Hapla 641625b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 64171690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 64189371c9d4SSatish Balay for (i = 0; i < len; i++) 64199371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 642025b6865aSVaclav Hapla ++NVerticesInCells; 642125b6865aSVaclav Hapla 642225b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 64239371c9d4SSatish Balay else 64249371c9d4SSatish 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); 642525b6865aSVaclav Hapla } 64269566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 642748a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 64289566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 64299566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 6430b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 6431ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 6432b09969d6SVaclav Hapla } 64339566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 64349566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 64359566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 64363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6437b09969d6SVaclav Hapla } 6438b09969d6SVaclav Hapla 6439cc4c1da9SBarry Smith /*@ 6440a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 6441a1cb98faSBarry Smith 6442cc4c1da9SBarry Smith Collective 6443b09969d6SVaclav Hapla 6444b09969d6SVaclav Hapla Input Parameters: 6445a1cb98faSBarry Smith + dm - The `DM` 6446b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6447b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6448b09969d6SVaclav Hapla 6449b09969d6SVaclav Hapla Level: advanced 6450b09969d6SVaclav Hapla 64511cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 6452b09969d6SVaclav Hapla @*/ 6453d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 6454d71ae5a4SJacob Faibussowitsch { 6455b09969d6SVaclav Hapla PetscSection coordSection; 6456b09969d6SVaclav Hapla Vec coordinates; 6457b09969d6SVaclav Hapla DM cdm; 6458b09969d6SVaclav Hapla PetscScalar *coords; 64591edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 6460b09969d6SVaclav Hapla 6461b09969d6SVaclav Hapla PetscFunctionBegin; 64629566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 64639566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 64641dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 64659566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 64669566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 64679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 64689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 64699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 64701edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 64719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 64729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 6473b09969d6SVaclav Hapla } 64749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6475b09969d6SVaclav Hapla 64769566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 64779566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 64789566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 64799566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 64809566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 64811edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 6482ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 6483b09969d6SVaclav Hapla } 64849566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 64859566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 64869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 64879566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 64883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6489b09969d6SVaclav Hapla } 6490b09969d6SVaclav Hapla 6491b09969d6SVaclav Hapla /*@ 6492a1cb98faSBarry Smith DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 64933df08285SMatthew G. Knepley 6494a1cb98faSBarry Smith Collective 6495b09969d6SVaclav Hapla 6496b09969d6SVaclav Hapla Input Parameters: 6497b09969d6SVaclav Hapla + comm - The communicator 6498b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 64993df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 6500a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0 65013df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 6502b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6503ce78bad3SBarry Smith . cells - An array of $ numCells \times numCorners$ numbers, the vertices for each cell, only on process 0 6504b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6505ce78bad3SBarry Smith - vertexCoords - An array of $ numVertices \times spaceDim$ numbers, the coordinates of each vertex, only on process 0 6506b09969d6SVaclav Hapla 6507b09969d6SVaclav Hapla Output Parameter: 6508a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0 650925b6865aSVaclav Hapla 6510b09969d6SVaclav Hapla Level: intermediate 6511b09969d6SVaclav Hapla 6512a1cb98faSBarry Smith Notes: 6513a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`, 6514a1cb98faSBarry Smith `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()` 6515a1cb98faSBarry Smith 6516a1cb98faSBarry Smith See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters. 6517a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters. 6518a1cb98faSBarry Smith See `DMPlexCreateFromCellListParallelPetsc()` for parallel input 6519a1cb98faSBarry Smith 65201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 65219298eaa6SMatthew G Knepley @*/ 6522d71ae5a4SJacob 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) 6523d71ae5a4SJacob Faibussowitsch { 65243df08285SMatthew G. Knepley PetscMPIInt rank; 65259298eaa6SMatthew G Knepley 65269298eaa6SMatthew G Knepley PetscFunctionBegin; 652728b400f6SJacob 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."); 65289566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 65299566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 65309566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 65319566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 6532c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 65339566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 65349298eaa6SMatthew G Knepley if (interpolate) { 65355fd9971aSMatthew G. Knepley DM idm; 65369298eaa6SMatthew G Knepley 65379566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 65389566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 65399298eaa6SMatthew G Knepley *dm = idm; 65409298eaa6SMatthew G Knepley } 6541c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 65429566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 65433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 65449298eaa6SMatthew G Knepley } 65459298eaa6SMatthew G Knepley 6546939f6067SMatthew G. Knepley /*@ 654720f4b53cSBarry Smith DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a `DM` 6548939f6067SMatthew G. Knepley 6549939f6067SMatthew G. Knepley Input Parameters: 655020f4b53cSBarry Smith + dm - The empty `DM` object, usually from `DMCreate()` and `DMSetDimension()` 6551939f6067SMatthew G. Knepley . depth - The depth of the DAG 6552ce78bad3SBarry Smith . numPoints - Array of size $ depth + 1 $ containing the number of points at each `depth` 6553939f6067SMatthew G. Knepley . coneSize - The cone size of each point 6554939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 6555939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 6556ce78bad3SBarry Smith - vertexCoords - An array of $ numPoints[0] \times spacedim $ numbers representing the coordinates of each vertex, with `spacedim` the value set via `DMSetCoordinateDim()` 6557939f6067SMatthew G. Knepley 6558939f6067SMatthew G. Knepley Output Parameter: 655920f4b53cSBarry Smith . dm - The `DM` 656020f4b53cSBarry Smith 656120f4b53cSBarry Smith Level: advanced 6562939f6067SMatthew G. Knepley 6563a1cb98faSBarry Smith Note: 6564a1cb98faSBarry Smith Two triangles sharing a face would have input 6565a1cb98faSBarry Smith .vb 6566a1cb98faSBarry Smith depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 6567a1cb98faSBarry Smith cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 6568a1cb98faSBarry Smith vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 6569a1cb98faSBarry Smith .ve 6570939f6067SMatthew G. Knepley which would result in the DMPlex 6571a1cb98faSBarry Smith .vb 6572a1cb98faSBarry Smith 4 6573a1cb98faSBarry Smith / | \ 6574a1cb98faSBarry Smith / | \ 6575a1cb98faSBarry Smith / | \ 6576a1cb98faSBarry Smith 2 0 | 1 5 6577a1cb98faSBarry Smith \ | / 6578a1cb98faSBarry Smith \ | / 6579a1cb98faSBarry Smith \ | / 6580a1cb98faSBarry Smith 3 6581a1cb98faSBarry Smith .ve 6582a1cb98faSBarry Smith Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()` 6583939f6067SMatthew G. Knepley 6584ce78bad3SBarry Smith Developer Note: 6585ce78bad3SBarry Smith This does not create anything so should not have create in the name. 6586ce78bad3SBarry Smith 65871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 6588939f6067SMatthew G. Knepley @*/ 6589d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 6590d71ae5a4SJacob Faibussowitsch { 65919298eaa6SMatthew G Knepley Vec coordinates; 65929298eaa6SMatthew G Knepley PetscSection coordSection; 65939298eaa6SMatthew G Knepley PetscScalar *coords; 6594811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 65959298eaa6SMatthew G Knepley 65969298eaa6SMatthew G Knepley PetscFunctionBegin; 65979566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 65989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 659963a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 66009298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 66019566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 66029298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 66039566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 6604ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 660597e052ccSToby Isaac } 66061dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 66079566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 66089298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 66099566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 66109566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 66119298eaa6SMatthew G Knepley } 66129566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 66139566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 66149298eaa6SMatthew G Knepley /* Build coordinates */ 66159566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 66169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 66179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 66189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 66199298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 66209566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 66219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 66229298eaa6SMatthew G Knepley } 66239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 66249566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 66259566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 66269566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 66279566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 662858b7e2c1SStefano Zampini PetscCall(VecSetBlockSize(coordinates, PetscMax(dimEmbed, 1))); 66299566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 66309318fe57SMatthew G. Knepley if (vertexCoords) { 66319566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 66329298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 66339298eaa6SMatthew G Knepley PetscInt off; 66349298eaa6SMatthew G Knepley 66359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 6636ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 66379298eaa6SMatthew G Knepley } 66389318fe57SMatthew G. Knepley } 66399566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 66409566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 66419566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 66423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 66439298eaa6SMatthew G Knepley } 66448415267dSToby Isaac 6645a4e35b19SJacob Faibussowitsch /* 6646a1cb98faSBarry Smith DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file. 6647a1cb98faSBarry Smith 6648a1cb98faSBarry Smith Collective 66498ca92349SMatthew G. Knepley 66508ca92349SMatthew G. Knepley + comm - The MPI communicator 66518ca92349SMatthew G. Knepley . filename - Name of the .dat file 66528ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 66538ca92349SMatthew G. Knepley 66548ca92349SMatthew G. Knepley Output Parameter: 6655a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 66568ca92349SMatthew G. Knepley 66578ca92349SMatthew G. Knepley Level: beginner 66588ca92349SMatthew G. Knepley 6659a1cb98faSBarry Smith Note: 6660a1cb98faSBarry Smith The format is the simplest possible: 6661a1cb98faSBarry Smith .vb 6662d0812dedSMatthew G. Knepley dim Ne Nv Nc Nl 6663d0812dedSMatthew G. Knepley v_1 v_2 ... v_Nc 6664d0812dedSMatthew G. Knepley ... 6665d0812dedSMatthew G. Knepley x y z marker_1 ... marker_Nl 6666a1cb98faSBarry Smith .ve 6667a1cb98faSBarry Smith 6668a1cb98faSBarry Smith Developer Note: 6669a1cb98faSBarry Smith Should use a `PetscViewer` not a filename 6670a1cb98faSBarry Smith 66716afe31f6SMartin Diehl .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 6672a4e35b19SJacob Faibussowitsch */ 6673ff6a9541SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 6674d71ae5a4SJacob Faibussowitsch { 66758ca92349SMatthew G. Knepley DMLabel marker; 66768ca92349SMatthew G. Knepley PetscViewer viewer; 66778ca92349SMatthew G. Knepley Vec coordinates; 66788ca92349SMatthew G. Knepley PetscSection coordSection; 66798ca92349SMatthew G. Knepley PetscScalar *coords; 66808ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 6681d0812dedSMatthew G. Knepley PetscInt cdim, coordSize, v, c, d; 66828ca92349SMatthew G. Knepley PetscMPIInt rank; 6683d0812dedSMatthew G. Knepley int snum, dim, Nv, Nc, Ncn, Nl; 66848ca92349SMatthew G. Knepley 66858ca92349SMatthew G. Knepley PetscFunctionBegin; 66869566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 66879566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 66889566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 66899566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 66909566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 6691dd400576SPatrick Sanan if (rank == 0) { 6692d0812dedSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING)); 6693d0812dedSMatthew G. Knepley snum = sscanf(line, "%d %d %d %d %d", &dim, &Nc, &Nv, &Ncn, &Nl); 6694d0812dedSMatthew G. Knepley PetscCheck(snum == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 669525ce1634SJed Brown } else { 6696f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 66978ca92349SMatthew G. Knepley } 6698d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm)); 6699835f2295SStefano Zampini cdim = dim; 67009566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 67019566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 67029566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 6703835f2295SStefano Zampini PetscCall(DMSetDimension(*dm, dim)); 67049566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 67058ca92349SMatthew G. Knepley /* Read topology */ 6706dd400576SPatrick Sanan if (rank == 0) { 6707f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 6708f8d5e320SMatthew G. Knepley PetscInt cone[8]; 67098ca92349SMatthew G. Knepley int vbuf[8], v; 67108ca92349SMatthew G. Knepley 67119371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 67129371c9d4SSatish Balay format[c * 3 + 0] = '%'; 67139371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 67149371c9d4SSatish Balay format[c * 3 + 2] = ' '; 67159371c9d4SSatish Balay } 6716f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 67179566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 67189566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 67198ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 67209566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 6721f8d5e320SMatthew G. Knepley switch (Ncn) { 6722d71ae5a4SJacob Faibussowitsch case 2: 6723d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1]); 6724d71ae5a4SJacob Faibussowitsch break; 6725d71ae5a4SJacob Faibussowitsch case 3: 6726d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); 6727d71ae5a4SJacob Faibussowitsch break; 6728d71ae5a4SJacob Faibussowitsch case 4: 6729d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); 6730d71ae5a4SJacob Faibussowitsch break; 6731d71ae5a4SJacob Faibussowitsch case 6: 6732d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); 6733d71ae5a4SJacob Faibussowitsch break; 6734d71ae5a4SJacob Faibussowitsch case 8: 6735d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 6736d71ae5a4SJacob Faibussowitsch break; 6737d71ae5a4SJacob Faibussowitsch default: 6738d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 6739f8d5e320SMatthew G. Knepley } 674008401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6741f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 67428ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 6743f8d5e320SMatthew G. Knepley if (Ncn == 8) { 67448ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 67458ca92349SMatthew G. Knepley cone[1] = cone[3]; 67468ca92349SMatthew G. Knepley cone[3] = tmp; 67478ca92349SMatthew G. Knepley } 67489566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 67498ca92349SMatthew G. Knepley } 67508ca92349SMatthew G. Knepley } 67519566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 67529566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 67538ca92349SMatthew G. Knepley /* Read coordinates */ 67549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 67559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 67569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 67579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 67588ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 67599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 67609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 67618ca92349SMatthew G. Knepley } 67629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 67639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 67649566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 67659566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 67669566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 67679566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 67689566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 67699566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6770dd400576SPatrick Sanan if (rank == 0) { 6771f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 67728ca92349SMatthew G. Knepley double x[3]; 6773f8d5e320SMatthew G. Knepley int l, val[3]; 67748ca92349SMatthew G. Knepley 6775f8d5e320SMatthew G. Knepley if (Nl) { 67769371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 67779371c9d4SSatish Balay format[l * 3 + 0] = '%'; 67789371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 67799371c9d4SSatish Balay format[l * 3 + 2] = ' '; 67809371c9d4SSatish Balay } 6781f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 67829566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 67839566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 6784f8d5e320SMatthew G. Knepley } 67858ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 67869566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 6787f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 678808401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6789f8d5e320SMatthew G. Knepley switch (Nl) { 6790d71ae5a4SJacob Faibussowitsch case 0: 6791d71ae5a4SJacob Faibussowitsch snum = 0; 6792d71ae5a4SJacob Faibussowitsch break; 6793d71ae5a4SJacob Faibussowitsch case 1: 6794d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0]); 6795d71ae5a4SJacob Faibussowitsch break; 6796d71ae5a4SJacob Faibussowitsch case 2: 6797d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1]); 6798d71ae5a4SJacob Faibussowitsch break; 6799d71ae5a4SJacob Faibussowitsch case 3: 6800d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1], &val[2]); 6801d71ae5a4SJacob Faibussowitsch break; 6802d71ae5a4SJacob Faibussowitsch default: 6803d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 6804f8d5e320SMatthew G. Knepley } 680508401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 68068ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 68079566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 68088ca92349SMatthew G. Knepley } 68098ca92349SMatthew G. Knepley } 68109566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 68119566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 68129566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 68139566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 68148ca92349SMatthew G. Knepley if (interpolate) { 68158ca92349SMatthew G. Knepley DM idm; 68168ca92349SMatthew G. Knepley DMLabel bdlabel; 68178ca92349SMatthew G. Knepley 68189566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 68199566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 68208ca92349SMatthew G. Knepley *dm = idm; 68218ca92349SMatthew G. Knepley 6822f8d5e320SMatthew G. Knepley if (!Nl) { 68239566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 68249566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 68259566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 68269566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 68278ca92349SMatthew G. Knepley } 6828f8d5e320SMatthew G. Knepley } 68293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68308ca92349SMatthew G. Knepley } 68318ca92349SMatthew G. Knepley 6832cc4c1da9SBarry Smith /*@ 6833a1cb98faSBarry Smith DMPlexCreateFromFile - This takes a filename and produces a `DM` 6834a1cb98faSBarry Smith 6835a1cb98faSBarry Smith Collective 6836ca522641SMatthew G. Knepley 6837ca522641SMatthew G. Knepley Input Parameters: 6838ca522641SMatthew G. Knepley + comm - The communicator 6839ca522641SMatthew G. Knepley . filename - A file name 6840a1cb98faSBarry Smith . plexname - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats 6841ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 6842ca522641SMatthew G. Knepley 6843ca522641SMatthew G. Knepley Output Parameter: 6844a1cb98faSBarry Smith . dm - The `DM` 6845ca522641SMatthew G. Knepley 6846a1cb98faSBarry Smith Options Database Key: 6847a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5 684802ef0d99SVaclav Hapla 684937fdd005SBarry Smith Use `-dm_plex_create_ prefix` to pass options to the internal `PetscViewer`, e.g. 6850bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective 6851bca97951SVaclav Hapla 6852ca522641SMatthew G. Knepley Level: beginner 6853ca522641SMatthew G. Knepley 6854a1cb98faSBarry Smith Notes: 6855a1cb98faSBarry Smith Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX` 6856a1cb98faSBarry Smith meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()` 6857a1cb98faSBarry Smith before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object. 6858a1cb98faSBarry Smith The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally 6859a1cb98faSBarry Smith calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats. 6860a1cb98faSBarry Smith 68611cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 6862ca522641SMatthew G. Knepley @*/ 6863d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 6864d71ae5a4SJacob Faibussowitsch { 6865ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 6866ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 6867ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 6868ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 6869ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 6870ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 6871ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 6872ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 6873ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 68746f2c871aSStefano Zampini const char extXDMFHDF5[] = ".xdmf.h5"; 6875ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 68765552b385SBrandon const char extEGADSlite[] = ".egadslite"; 6877ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 6878ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 68795552b385SBrandon const char extIGES2[] = ".iges"; 6880ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 68815552b385SBrandon const char extSTEP2[] = ".step"; 68825552b385SBrandon const char extBREP[] = ".brep"; 6883ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 6884ca522641SMatthew G. Knepley size_t len; 68855552b385SBrandon PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isPLY, isEGADSlite, isEGADS, isIGES, isIGES2, isSTEP, isSTEP2, isBREP, isCV, isXDMFHDF5; 6886ca522641SMatthew G. Knepley PetscMPIInt rank; 6887ca522641SMatthew G. Knepley 6888ca522641SMatthew G. Knepley PetscFunctionBegin; 68894f572ea9SToby Isaac PetscAssertPointer(filename, 2); 68904f572ea9SToby Isaac if (plexname) PetscAssertPointer(plexname, 3); 68914f572ea9SToby Isaac PetscAssertPointer(dm, 5); 68929566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 68939566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 68949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 68959566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 689628b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 6897ef3a5affSJacob Faibussowitsch 68989371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 68999371c9d4SSatish Balay do { \ 6900274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 6901274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 6902274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 6903274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 6904ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 6905ef3a5affSJacob Faibussowitsch } else { \ 6906274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 6907ef3a5affSJacob Faibussowitsch } \ 6908ef3a5affSJacob Faibussowitsch } while (0) 6909ef3a5affSJacob Faibussowitsch 6910ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 6911ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 6912ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 6913ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 6914ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 6915ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 6916ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 6917ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 6918ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 6919ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 69205552b385SBrandon CheckExtension(extEGADSlite, isEGADSlite); 6921ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 6922ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 69235552b385SBrandon CheckExtension(extIGES2, isIGES2); 6924ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 69255552b385SBrandon CheckExtension(extSTEP2, isSTEP2); 69265552b385SBrandon CheckExtension(extBREP, isBREP); 6927ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 69286f2c871aSStefano Zampini CheckExtension(extXDMFHDF5, isXDMFHDF5); 6929ef3a5affSJacob Faibussowitsch 6930ef3a5affSJacob Faibussowitsch #undef CheckExtension 6931ef3a5affSJacob Faibussowitsch 6932de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 69339566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 6934ca522641SMatthew G. Knepley } else if (isCGNS) { 69359566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 693690c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 69379566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 69382f0bd6dcSMichael Lange } else if (isFluent) { 69399566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 6940cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 6941cc2f8f65SMatthew G. Knepley PetscViewer viewer; 6942cc2f8f65SMatthew G. Knepley 694343b242b4SVaclav 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 */ 69446f2c871aSStefano Zampini PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &isXDMFHDF5, NULL)); 69459566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 69469566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 69479566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 69489566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 69499566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 69509566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 6951cd7e8a5eSksagiyam 69529566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 6953f4f49eeaSPierre Jolivet PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 69549566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 69556f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 69569566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 69576f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPopFormat(viewer)); 69589566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 69595fd9971aSMatthew G. Knepley 69605fd9971aSMatthew G. Knepley if (interpolate) { 69615fd9971aSMatthew G. Knepley DM idm; 69625fd9971aSMatthew G. Knepley 69639566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 69649566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 69655fd9971aSMatthew G. Knepley *dm = idm; 69665fd9971aSMatthew G. Knepley } 6967f2801cd6SMatthew G. Knepley } else if (isPLY) { 69689566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 69695552b385SBrandon } else if (isEGADSlite || isEGADS || isIGES || isIGES2 || isSTEP || isSTEP2 || isBREP) { 69705552b385SBrandon PetscCall(DMPlexCreateGeomFromFile(comm, filename, dm, isEGADSlite)); 69715552b385SBrandon 69727bee2925SMatthew Knepley if (!interpolate) { 69737bee2925SMatthew Knepley DM udm; 69747bee2925SMatthew Knepley 69759566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 69769566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 69777bee2925SMatthew Knepley *dm = udm; 69787bee2925SMatthew Knepley } 69798ca92349SMatthew G. Knepley } else if (isCV) { 69809566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 698198921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 69829566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 6983f4f49eeaSPierre Jolivet if (len) PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 69849566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 69853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6986ca522641SMatthew G. Knepley } 698712b8a6daSStefano Zampini 6988cc4c1da9SBarry Smith /*@ 69899f6c5813SMatthew 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. 69909f6c5813SMatthew G. Knepley 69910528010dSStefano Zampini Input Parameters: 69920528010dSStefano Zampini + tr - The `DMPlexTransform` 69930528010dSStefano Zampini - prefix - An options prefix, or NULL 69949f6c5813SMatthew G. Knepley 69959f6c5813SMatthew G. Knepley Output Parameter: 69969f6c5813SMatthew G. Knepley . dm - The `DM` 69979f6c5813SMatthew G. Knepley 69989f6c5813SMatthew G. Knepley Level: beginner 69999f6c5813SMatthew G. Knepley 700020f4b53cSBarry Smith Notes: 700120f4b53cSBarry 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. 700220f4b53cSBarry Smith 70039f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 70049f6c5813SMatthew G. Knepley @*/ 70050528010dSStefano Zampini PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, const char prefix[], DM *dm) 70069f6c5813SMatthew G. Knepley { 70070528010dSStefano Zampini DM bdm, bcdm, cdm; 70080528010dSStefano Zampini Vec coordinates, coordinatesNew; 70090528010dSStefano Zampini PetscSection cs; 7010817b2c36SMatthew G. Knepley PetscInt cdim, Nl; 70119f6c5813SMatthew G. Knepley 70129f6c5813SMatthew G. Knepley PetscFunctionBegin; 70139f6c5813SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm)); 70149f6c5813SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 70150528010dSStefano Zampini ((DM_Plex *)(*dm)->data)->interpolated = DMPLEX_INTERPOLATED_FULL; 70160528010dSStefano Zampini // Handle coordinates 70170528010dSStefano Zampini PetscCall(DMPlexTransformGetDM(tr, &bdm)); 7018817b2c36SMatthew G. Knepley PetscCall(DMPlexTransformSetDimensions(tr, bdm, *dm)); 7019817b2c36SMatthew G. Knepley PetscCall(DMGetCoordinateDim(*dm, &cdim)); 70200528010dSStefano Zampini PetscCall(DMGetCoordinateDM(bdm, &bcdm)); 70210528010dSStefano Zampini PetscCall(DMGetCoordinateDM(*dm, &cdm)); 70220528010dSStefano Zampini PetscCall(DMCopyDisc(bcdm, cdm)); 70230528010dSStefano Zampini PetscCall(DMGetLocalSection(cdm, &cs)); 70240528010dSStefano Zampini PetscCall(PetscSectionSetNumFields(cs, 1)); 70250528010dSStefano Zampini PetscCall(PetscSectionSetFieldComponents(cs, 0, cdim)); 70260528010dSStefano Zampini PetscCall(DMGetCoordinatesLocal(bdm, &coordinates)); 70270528010dSStefano Zampini PetscCall(VecDuplicate(coordinates, &coordinatesNew)); 70280528010dSStefano Zampini PetscCall(VecCopy(coordinates, coordinatesNew)); 70290528010dSStefano Zampini PetscCall(DMSetCoordinatesLocal(*dm, coordinatesNew)); 70300528010dSStefano Zampini PetscCall(VecDestroy(&coordinatesNew)); 70319f6c5813SMatthew G. Knepley 70329f6c5813SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)tr)); 70339f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr)); 70349f6c5813SMatthew G. Knepley ((DM_Plex *)(*dm)->data)->tr = tr; 70350528010dSStefano Zampini PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE)); 70360528010dSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix)); 70370528010dSStefano Zampini PetscCall(DMSetFromOptions(*dm)); 70389f6c5813SMatthew G. Knepley 70399f6c5813SMatthew G. Knepley PetscCall(DMGetNumLabels(bdm, &Nl)); 70409f6c5813SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 70419f6c5813SMatthew G. Knepley DMLabel label, labelNew; 70429f6c5813SMatthew G. Knepley const char *lname; 70439f6c5813SMatthew G. Knepley PetscBool isDepth, isCellType; 70449f6c5813SMatthew G. Knepley 70459f6c5813SMatthew G. Knepley PetscCall(DMGetLabelName(bdm, l, &lname)); 70469f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 70479f6c5813SMatthew G. Knepley if (isDepth) continue; 70489f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "celltype", &isCellType)); 70499f6c5813SMatthew G. Knepley if (isCellType) continue; 70509f6c5813SMatthew G. Knepley PetscCall(DMCreateLabel(*dm, lname)); 70519f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(bdm, lname, &label)); 70529f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(*dm, lname, &labelNew)); 70539f6c5813SMatthew G. Knepley PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL)); 70549f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetLabel(labelNew, label)); 70559f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetTransform(labelNew, tr)); 70569f6c5813SMatthew G. Knepley PetscCall(DMLabelSetUp(labelNew)); 70579f6c5813SMatthew G. Knepley } 70583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70599f6c5813SMatthew G. Knepley } 7060