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