1552f7358SJed Brown #define PETSCDM_DLL 2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3cc4c1da9SBarry Smith #include <petsc/private/hashseti.h> 40c312b8eSJed Brown #include <petscsf.h> 5cc4c1da9SBarry Smith #include <petscdmplextransform.h> /*I "petscdmplextransform.h" I*/ 69f6c5813SMatthew G. Knepley #include <petscdmlabelephemeral.h> 7b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h> 8b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h> 9552f7358SJed Brown 10d0812dedSMatthew G. Knepley #ifdef PETSC_HAVE_UNISTD_H 11d0812dedSMatthew G. Knepley #include <unistd.h> 12d0812dedSMatthew G. Knepley #endif 13d0812dedSMatthew G. Knepley #include <errno.h> 14d0812dedSMatthew G. Knepley 15708be2fdSJed Brown PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_CreateFromOptions, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList; 1658cd63d5SVaclav Hapla 179318fe57SMatthew G. Knepley /* External function declarations here */ 189318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm); 199318fe57SMatthew G. Knepley 205552b385SBrandon PETSC_EXTERN PetscErrorCode DMPlexCheckEGADS_Private(DM dm) 215552b385SBrandon { 225552b385SBrandon PetscObject modelObj; 235552b385SBrandon 245552b385SBrandon PetscFunctionBegin; 255552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", &modelObj)); 265552b385SBrandon PetscCheck(modelObj, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Input DM must have attached EGADS Geometry Model"); 275552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 285552b385SBrandon } 295552b385SBrandon 305552b385SBrandon static PetscErrorCode DMPlexCopyContext_Private(DM dmin, const char name[], DM dmout) 315552b385SBrandon { 325552b385SBrandon PetscObject obj; 335552b385SBrandon 345552b385SBrandon PetscFunctionBegin; 355552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmin, name, &obj)); 365552b385SBrandon if (obj) PetscCall(PetscObjectCompose((PetscObject)dmout, name, obj)); 375552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 385552b385SBrandon } 395552b385SBrandon 405552b385SBrandon static PetscErrorCode DMPlexSwapContext_Private(DM dmA, const char name[], DM dmB) 415552b385SBrandon { 425552b385SBrandon PetscObject objA, objB; 435552b385SBrandon 445552b385SBrandon PetscFunctionBegin; 455552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmA, name, &objA)); 465552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmB, name, &objB)); 475552b385SBrandon PetscCall(PetscObjectReference(objA)); 485552b385SBrandon PetscCall(PetscObjectReference(objB)); 495552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dmA, name, objB)); 505552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dmB, name, objA)); 515552b385SBrandon PetscCall(PetscObjectDereference(objA)); 525552b385SBrandon PetscCall(PetscObjectDereference(objB)); 535552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 545552b385SBrandon } 555552b385SBrandon 565552b385SBrandon PetscErrorCode DMPlexCopyEGADSInfo_Internal(DM dmin, DM dmout) 575552b385SBrandon { 585552b385SBrandon PetscFunctionBegin; 595552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Model", dmout)); 605552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Context", dmout)); 615552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Model", dmout)); 625552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Context", dmout)); 635552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 645552b385SBrandon } 655552b385SBrandon 665552b385SBrandon static PetscErrorCode DMPlexSwapEGADSInfo_Private(DM dmA, DM dmB) 675552b385SBrandon { 685552b385SBrandon PetscFunctionBegin; 695552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Model", dmB)); 705552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Context", dmB)); 715552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Model", dmB)); 725552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Context", dmB)); 735552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 745552b385SBrandon } 755552b385SBrandon 76e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */ 77d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout) 78d71ae5a4SJacob Faibussowitsch { 794fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 8012a88998SMatthew G. Knepley VecType vecType; 8112a88998SMatthew G. Knepley MatType matType; 82129f447cSJames Wright PetscBool dist, useCeed, balance_partition; 83adc21957SMatthew G. Knepley DMReorderDefaultFlag reorder; 84e600fa54SMatthew G. Knepley 85e600fa54SMatthew G. Knepley PetscFunctionBegin; 86835f2295SStefano Zampini if (dmin == dmout) PetscFunctionReturn(PETSC_SUCCESS); 8712a88998SMatthew G. Knepley PetscCall(DMGetVecType(dmin, &vecType)); 8812a88998SMatthew G. Knepley PetscCall(DMSetVecType(dmout, vecType)); 8912a88998SMatthew G. Knepley PetscCall(DMGetMatType(dmin, &matType)); 9012a88998SMatthew G. Knepley PetscCall(DMSetMatType(dmout, matType)); 91e600fa54SMatthew G. Knepley if (copyPeriodicity) { 924fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L)); 934fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L)); 943d0e8ed9SDavid Salac PetscCall(DMLocalizeCoordinates(dmout)); 95e600fa54SMatthew G. Knepley } 969566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dmin, &dist)); 979566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dmout, dist)); 986bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dmin, &reorder)); 996bc1bd01Sksagiyam PetscCall(DMPlexReorderSetDefault(dmout, reorder)); 1005962854dSMatthew G. Knepley PetscCall(DMPlexGetUseCeed(dmin, &useCeed)); 1015962854dSMatthew G. Knepley PetscCall(DMPlexSetUseCeed(dmout, useCeed)); 102129f447cSJames Wright PetscCall(DMPlexGetPartitionBalance(dmin, &balance_partition)); 103129f447cSJames Wright PetscCall(DMPlexSetPartitionBalance(dmout, balance_partition)); 104e600fa54SMatthew G. Knepley ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation; 1055962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printSetValues = ((DM_Plex *)dmin->data)->printSetValues; 1065962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printFEM = ((DM_Plex *)dmin->data)->printFEM; 1075962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printFVM = ((DM_Plex *)dmin->data)->printFVM; 1085962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printL2 = ((DM_Plex *)dmin->data)->printL2; 1095962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printLocate = ((DM_Plex *)dmin->data)->printLocate; 110a77a5016SMatthew G. Knepley ((DM_Plex *)dmout->data)->printProject = ((DM_Plex *)dmin->data)->printProject; 1115962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printTol = ((DM_Plex *)dmin->data)->printTol; 1121baa6e33SBarry Smith if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0)); 1135552b385SBrandon PetscCall(DMPlexCopyEGADSInfo_Internal(dmin, dmout)); 1143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 115e600fa54SMatthew G. Knepley } 116e600fa54SMatthew G. Knepley 1179318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 1189318fe57SMatthew G. Knepley - Share the DM_Plex structure 1199318fe57SMatthew G. Knepley - Share the coordinates 1209318fe57SMatthew G. Knepley - Share the SF 1219318fe57SMatthew G. Knepley */ 122d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm) 123d71ae5a4SJacob Faibussowitsch { 1249318fe57SMatthew G. Knepley PetscSF sf; 1259318fe57SMatthew G. Knepley DM dmNew = *ndm, coordDM, coarseDM; 1269318fe57SMatthew G. Knepley Vec coords; 1274fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 1289318fe57SMatthew G. Knepley PetscInt dim, cdim; 129e535cce4SJames Wright PetscBool use_natural; 1309318fe57SMatthew G. Knepley 1319318fe57SMatthew G. Knepley PetscFunctionBegin; 1329318fe57SMatthew G. Knepley if (dm == dmNew) { 1339566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 1343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1359318fe57SMatthew G. Knepley } 1369318fe57SMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 137d0812dedSMatthew G. Knepley if (!dm->hdr.name) { 138d0812dedSMatthew G. Knepley const char *name; 139d0812dedSMatthew G. Knepley 140d0812dedSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)*ndm, &name)); 141d0812dedSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, name)); 142d0812dedSMatthew G. Knepley } 1439566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dmNew, &dim)); 1449566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 1459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmNew, &cdim)); 1469566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 1479566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmNew, &sf)); 1489566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sf)); 1499566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmNew, &coordDM)); 1509566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmNew, &coords)); 1519566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dm, coordDM)); 1529566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 1536858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM)); 1546858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords)); 1556858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dm, coordDM)); 1566858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 1579318fe57SMatthew G. Knepley /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */ 1586858538eSMatthew G. Knepley PetscCall(DMFieldDestroy(&dm->coordinates[0].field)); 1596858538eSMatthew G. Knepley dm->coordinates[0].field = dmNew->coordinates[0].field; 16061a622f3SMatthew G. Knepley ((DM_Plex *)dmNew->data)->coordFunc = ((DM_Plex *)dm->data)->coordFunc; 1614fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L)); 1624fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 163e535cce4SJames Wright PetscCall(DMGetNaturalSF(dmNew, &sf)); 164e535cce4SJames Wright PetscCall(DMSetNaturalSF(dm, sf)); 165e535cce4SJames Wright PetscCall(DMGetUseNatural(dmNew, &use_natural)); 166e535cce4SJames Wright PetscCall(DMSetUseNatural(dm, use_natural)); 1679566063dSJacob Faibussowitsch PetscCall(DMDestroy_Plex(dm)); 1689566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 1699318fe57SMatthew G. Knepley dm->data = dmNew->data; 1709318fe57SMatthew G. Knepley ((DM_Plex *)dmNew->data)->refct++; 1711fca310dSJames Wright { 1721fca310dSJames Wright PetscInt num_face_sfs; 1731fca310dSJames Wright const PetscSF *sfs; 1741fca310dSJames Wright PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &sfs)); 1751fca310dSJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(dm, num_face_sfs, (PetscSF *)sfs)); // for the compose function effect on dm 1761fca310dSJames Wright } 1779566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 1789566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 1799566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmNew, &coarseDM)); 1809566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 1815552b385SBrandon PetscCall(DMPlexCopyEGADSInfo_Internal(dmNew, dm)); 1829566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 1833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1849318fe57SMatthew G. Knepley } 1859318fe57SMatthew G. Knepley 1869318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew 1879318fe57SMatthew G. Knepley - Swap the DM_Plex structure 1889318fe57SMatthew G. Knepley - Swap the coordinates 1899318fe57SMatthew G. Knepley - Swap the point PetscSF 1909318fe57SMatthew G. Knepley */ 191d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) 192d71ae5a4SJacob Faibussowitsch { 1939318fe57SMatthew G. Knepley DM coordDMA, coordDMB; 1949318fe57SMatthew G. Knepley Vec coordsA, coordsB; 1959318fe57SMatthew G. Knepley PetscSF sfA, sfB; 1969318fe57SMatthew G. Knepley DMField fieldTmp; 1979318fe57SMatthew G. Knepley void *tmp; 1989318fe57SMatthew G. Knepley DMLabelLink listTmp; 1999318fe57SMatthew G. Knepley DMLabel depthTmp; 2009318fe57SMatthew G. Knepley PetscInt tmpI; 2019318fe57SMatthew G. Knepley 2029318fe57SMatthew G. Knepley PetscFunctionBegin; 2033ba16761SJacob Faibussowitsch if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS); 2049566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmA, &sfA)); 2059566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmB, &sfB)); 2069566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sfA)); 2079566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmA, sfB)); 2089566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmB, sfA)); 2099566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)sfA)); 2109318fe57SMatthew G. Knepley 2119566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &coordDMA)); 2129566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &coordDMB)); 2139566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordDMA)); 2149566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmA, coordDMB)); 2159566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmB, coordDMA)); 2169566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 2179318fe57SMatthew G. Knepley 2189566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordsA)); 2199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmB, &coordsB)); 2209566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordsA)); 2219566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmA, coordsB)); 2229566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordsA)); 2239566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordsA)); 2249318fe57SMatthew G. Knepley 2256858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA)); 2266858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB)); 2276858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordDMA)); 2286858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmA, coordDMB)); 2296858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmB, coordDMA)); 2306858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 2316858538eSMatthew G. Knepley 2326858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA)); 2336858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB)); 2346858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordsA)); 2356858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB)); 2366858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA)); 2376858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordsA)); 2386858538eSMatthew G. Knepley 2395552b385SBrandon PetscCall(DMPlexSwapEGADSInfo_Private(dmA, dmB)); 2405552b385SBrandon 2416858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[0].field; 2426858538eSMatthew G. Knepley dmA->coordinates[0].field = dmB->coordinates[0].field; 2436858538eSMatthew G. Knepley dmB->coordinates[0].field = fieldTmp; 2446858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[1].field; 2456858538eSMatthew G. Knepley dmA->coordinates[1].field = dmB->coordinates[1].field; 2466858538eSMatthew G. Knepley dmB->coordinates[1].field = fieldTmp; 2479318fe57SMatthew G. Knepley tmp = dmA->data; 2489318fe57SMatthew G. Knepley dmA->data = dmB->data; 2499318fe57SMatthew G. Knepley dmB->data = tmp; 2509318fe57SMatthew G. Knepley listTmp = dmA->labels; 2519318fe57SMatthew G. Knepley dmA->labels = dmB->labels; 2529318fe57SMatthew G. Knepley dmB->labels = listTmp; 2539318fe57SMatthew G. Knepley depthTmp = dmA->depthLabel; 2549318fe57SMatthew G. Knepley dmA->depthLabel = dmB->depthLabel; 2559318fe57SMatthew G. Knepley dmB->depthLabel = depthTmp; 2569318fe57SMatthew G. Knepley depthTmp = dmA->celltypeLabel; 2579318fe57SMatthew G. Knepley dmA->celltypeLabel = dmB->celltypeLabel; 2589318fe57SMatthew G. Knepley dmB->celltypeLabel = depthTmp; 2599318fe57SMatthew G. Knepley tmpI = dmA->levelup; 2609318fe57SMatthew G. Knepley dmA->levelup = dmB->levelup; 2619318fe57SMatthew G. Knepley dmB->levelup = tmpI; 2623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2639318fe57SMatthew G. Knepley } 2649318fe57SMatthew G. Knepley 2653431e603SJed Brown PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm) 266d71ae5a4SJacob Faibussowitsch { 2679318fe57SMatthew G. Knepley DM idm; 2689318fe57SMatthew G. Knepley 2699318fe57SMatthew G. Knepley PetscFunctionBegin; 2709566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 2719566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 27269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 2733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2749318fe57SMatthew G. Knepley } 2759318fe57SMatthew G. Knepley 2769318fe57SMatthew G. Knepley /*@C 2779318fe57SMatthew G. Knepley DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates 2789318fe57SMatthew G. Knepley 27920f4b53cSBarry Smith Collective 2809318fe57SMatthew G. Knepley 2819318fe57SMatthew G. Knepley Input Parameters: 28260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 28320f4b53cSBarry Smith . degree - The degree of the finite element or `PETSC_DECIDE` 284e44f6aebSMatthew G. Knepley . project - Flag to project current coordinates into the space 2859318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface 2869318fe57SMatthew G. Knepley 2879318fe57SMatthew G. Knepley Level: advanced 2889318fe57SMatthew G. Knepley 2891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPointFunc`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()` 2909318fe57SMatthew G. Knepley @*/ 291e44f6aebSMatthew G. Knepley PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscBool project, PetscPointFunc coordFunc) 292d71ae5a4SJacob Faibussowitsch { 2939318fe57SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 294e44f6aebSMatthew G. Knepley PetscFE fe = NULL; 2959318fe57SMatthew G. Knepley DM cdm; 296ac9d17c7SMatthew G. Knepley PetscInt dim, cdim, dE, qorder, height; 2979318fe57SMatthew G. Knepley 298e44f6aebSMatthew G. Knepley PetscFunctionBegin; 2999566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 300ac9d17c7SMatthew G. Knepley cdim = dim; 3019566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 3029318fe57SMatthew G. Knepley qorder = degree; 303e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 304d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)cdm); 305dc431b0cSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0)); 306ac9d17c7SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_coordinate_dim", "Set the coordinate dimension", "DMPlexCreateCoordinateSpace", cdim, &cdim, NULL, dim)); 307d0609cedSBarry Smith PetscOptionsEnd(); 3081df12153SMatthew G. Knepley PetscCall(DMPlexGetVTKCellHeight(dm, &height)); 309ac9d17c7SMatthew G. Knepley if (cdim > dim) { 310ac9d17c7SMatthew G. Knepley DM cdm; 311ac9d17c7SMatthew G. Knepley PetscSection cs, csNew; 312ac9d17c7SMatthew G. Knepley Vec coordinates, coordinatesNew; 313ac9d17c7SMatthew G. Knepley VecType vectype; 314ac9d17c7SMatthew G. Knepley IS idx; 315ac9d17c7SMatthew G. Knepley PetscInt *indices; 316ac9d17c7SMatthew G. Knepley PetscInt bs, n; 317ac9d17c7SMatthew G. Knepley 318ac9d17c7SMatthew G. Knepley // Recreate coordinate section 319ac9d17c7SMatthew G. Knepley { 320ac9d17c7SMatthew G. Knepley const char *fieldName = NULL, *compName = NULL; 321ac9d17c7SMatthew G. Knepley PetscInt Nc, pStart, pEnd; 322ac9d17c7SMatthew G. Knepley 323ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 324ac9d17c7SMatthew G. Knepley PetscCall(DMGetLocalSection(cdm, &cs)); 325ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cs), &csNew)); 326ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetNumFields(csNew, 1)); 327ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetFieldName(cs, 0, &fieldName)); 328ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldName(csNew, 0, fieldName)); 329ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetFieldComponents(cs, 0, &Nc)); 330ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(csNew, 0, cdim)); 331ac9d17c7SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 332ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetComponentName(cs, 0, c, &compName)); 333ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetComponentName(csNew, 0, c, compName)); 334ac9d17c7SMatthew G. Knepley } 335ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetChart(cs, &pStart, &pEnd)); 336ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetChart(csNew, pStart, pEnd)); 337ac9d17c7SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 338ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetDof(csNew, p, cdim)); 339ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csNew, p, 0, cdim)); 340ac9d17c7SMatthew G. Knepley } 341ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetUp(csNew)); 342ac9d17c7SMatthew G. Knepley } 343ac9d17c7SMatthew G. Knepley PetscCall(DMSetLocalSection(cdm, csNew)); 344ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionDestroy(&csNew)); 345ac9d17c7SMatthew G. Knepley // Inject coordinates into higher dimension 346ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 347ac9d17c7SMatthew G. Knepley PetscCall(VecGetBlockSize(coordinates, &bs)); 348ac9d17c7SMatthew G. Knepley PetscCheck(bs == dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension"); 349ac9d17c7SMatthew G. Knepley PetscCall(VecCreate(PetscObjectComm((PetscObject)coordinates), &coordinatesNew)); 350ac9d17c7SMatthew G. Knepley PetscCall(VecGetType(coordinates, &vectype)); 351ac9d17c7SMatthew G. Knepley PetscCall(VecSetType(coordinatesNew, vectype)); 352ac9d17c7SMatthew G. Knepley PetscCall(VecGetLocalSize(coordinates, &n)); 353ac9d17c7SMatthew G. Knepley PetscCheck(!(n % bs), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension"); 354ac9d17c7SMatthew G. Knepley n /= bs; 355ac9d17c7SMatthew G. Knepley PetscCall(VecSetSizes(coordinatesNew, n * cdim, PETSC_DETERMINE)); 356ac9d17c7SMatthew G. Knepley PetscCall(VecSetUp(coordinatesNew)); 357ac9d17c7SMatthew G. Knepley PetscCall(PetscMalloc1(n * bs, &indices)); 358ac9d17c7SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) 359ac9d17c7SMatthew G. Knepley for (PetscInt b = 0; b < bs; ++b) indices[i * bs + b] = i * cdim + b; 360ac9d17c7SMatthew G. Knepley PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n * bs, indices, PETSC_OWN_POINTER, &idx)); 361ac9d17c7SMatthew G. Knepley PetscCall(VecISCopy(coordinatesNew, idx, SCATTER_FORWARD, coordinates)); 362ac9d17c7SMatthew G. Knepley PetscCall(ISDestroy(&idx)); 363ac9d17c7SMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinatesNew)); 364ac9d17c7SMatthew G. Knepley PetscCall(VecDestroy(&coordinatesNew)); 365ac9d17c7SMatthew G. Knepley PetscCall(DMSetCoordinateDim(dm, cdim)); 366ac9d17c7SMatthew G. Knepley { 367ac9d17c7SMatthew G. Knepley PetscInt gn; 368ac9d17c7SMatthew G. Knepley 369ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinates(dm, &coordinatesNew)); 370ac9d17c7SMatthew G. Knepley PetscCall(VecGetLocalSize(coordinatesNew, &gn)); 371ac9d17c7SMatthew G. Knepley PetscCheck(gn == n * cdim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Global coordinate size %" PetscInt_FMT " != %" PetscInt_FMT "local coordinate size", gn, n * cdim); 372ac9d17c7SMatthew G. Knepley } 373ac9d17c7SMatthew G. Knepley dE = cdim; 374ac9d17c7SMatthew G. Knepley } 375e44f6aebSMatthew G. Knepley if (degree >= 0) { 376e44f6aebSMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 377e44f6aebSMatthew G. Knepley PetscInt cStart, cEnd, gct; 378dc431b0cSMatthew G. Knepley 3791df12153SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd)); 380dc431b0cSMatthew G. Knepley if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 381e44f6aebSMatthew G. Knepley gct = (PetscInt)ct; 382462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &gct, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm))); 383e44f6aebSMatthew G. Knepley ct = (DMPolytopeType)gct; 384e44f6aebSMatthew G. Knepley // Work around current bug in PetscDualSpaceSetUp_Lagrange() 385e44f6aebSMatthew G. Knepley // Can be seen in plex_tutorials-ex10_1 386e44f6aebSMatthew G. Knepley if (ct != DM_POLYTOPE_SEG_PRISM_TENSOR && ct != DM_POLYTOPE_TRI_PRISM_TENSOR && ct != DM_POLYTOPE_QUAD_PRISM_TENSOR) PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe)); 3874f9ab2b4SJed Brown } 388e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinateDisc(dm, fe, project)); 3899566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 3909318fe57SMatthew G. Knepley mesh->coordFunc = coordFunc; 3913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3929318fe57SMatthew G. Knepley } 3939318fe57SMatthew G. Knepley 3941df5d5c5SMatthew G. Knepley /*@ 3951df5d5c5SMatthew G. Knepley DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 3961df5d5c5SMatthew G. Knepley 397d083f849SBarry Smith Collective 3981df5d5c5SMatthew G. Knepley 3991df5d5c5SMatthew G. Knepley Input Parameters: 400a1cb98faSBarry Smith + comm - The communicator for the `DM` object 4011df5d5c5SMatthew G. Knepley . dim - The spatial dimension 4021df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells 4031df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces) 4041df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 4051df5d5c5SMatthew G. Knepley 4061df5d5c5SMatthew G. Knepley Output Parameter: 40760225df5SJacob Faibussowitsch . newdm - The `DM` object 4081df5d5c5SMatthew G. Knepley 4091df5d5c5SMatthew G. Knepley Level: beginner 4101df5d5c5SMatthew G. Knepley 4111cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()` 4121df5d5c5SMatthew G. Knepley @*/ 413d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) 414d71ae5a4SJacob Faibussowitsch { 4151df5d5c5SMatthew G. Knepley DM dm; 4161df5d5c5SMatthew G. Knepley PetscMPIInt rank; 4171df5d5c5SMatthew G. Knepley 4181df5d5c5SMatthew G. Knepley PetscFunctionBegin; 4199566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &dm)); 4209566063dSJacob Faibussowitsch PetscCall(DMSetType(dm, DMPLEX)); 4219566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 42246139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 4239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 424ce78fa2fSMatthew G. Knepley switch (dim) { 425ce78fa2fSMatthew G. Knepley case 2: 4269566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular")); 4279566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral")); 428ce78fa2fSMatthew G. Knepley break; 429ce78fa2fSMatthew G. Knepley case 3: 4309566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral")); 4319566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral")); 432ce78fa2fSMatthew G. Knepley break; 433d71ae5a4SJacob Faibussowitsch default: 434d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 435ce78fa2fSMatthew G. Knepley } 4361df5d5c5SMatthew G. Knepley if (rank) { 4371df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {0, 0}; 4389566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL)); 4391df5d5c5SMatthew G. Knepley } else { 4401df5d5c5SMatthew G. Knepley switch (dim) { 4411df5d5c5SMatthew G. Knepley case 2: 4421df5d5c5SMatthew G. Knepley if (simplex) { 4431df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {4, 2}; 4441df5d5c5SMatthew G. Knepley PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 4451df5d5c5SMatthew G. Knepley PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 4461df5d5c5SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 4471df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 4481df5d5c5SMatthew G. Knepley 4499566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4501df5d5c5SMatthew G. Knepley } else { 4511df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {6, 2}; 4521df5d5c5SMatthew G. Knepley PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 4531df5d5c5SMatthew G. Knepley PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 4541df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 4551df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[12] = {-1.0, -0.5, 0.0, -0.5, 0.0, 0.5, -1.0, 0.5, 1.0, -0.5, 1.0, 0.5}; 4561df5d5c5SMatthew G. Knepley 4579566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4581df5d5c5SMatthew G. Knepley } 4591df5d5c5SMatthew G. Knepley break; 4601df5d5c5SMatthew G. Knepley case 3: 4611df5d5c5SMatthew G. Knepley if (simplex) { 4621df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {5, 2}; 4631df5d5c5SMatthew G. Knepley PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 4641df5d5c5SMatthew G. Knepley PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 4651df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 4661df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[15] = {-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0}; 4671df5d5c5SMatthew G. Knepley 4689566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4691df5d5c5SMatthew G. Knepley } else { 4701df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {12, 2}; 4711df5d5c5SMatthew G. Knepley PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 4721df5d5c5SMatthew G. Knepley PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 4731df5d5c5SMatthew G. Knepley PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 4749371c9d4SSatish Balay PetscScalar vertexCoords[36] = {-1.0, -0.5, -0.5, -1.0, 0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, -0.5, -1.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, -1.0, 0.5, 0.5, 1.0, 0.5, -0.5, 1.0, -0.5, -0.5, 1.0, -0.5, 0.5, 1.0, 0.5, 0.5}; 4751df5d5c5SMatthew G. Knepley 4769566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4771df5d5c5SMatthew G. Knepley } 4781df5d5c5SMatthew G. Knepley break; 479d71ae5a4SJacob Faibussowitsch default: 480d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 4811df5d5c5SMatthew G. Knepley } 4821df5d5c5SMatthew G. Knepley } 48346139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 4841df5d5c5SMatthew G. Knepley *newdm = dm; 4851df5d5c5SMatthew G. Knepley if (refinementLimit > 0.0) { 4861df5d5c5SMatthew G. Knepley DM rdm; 4871df5d5c5SMatthew G. Knepley const char *name; 4881df5d5c5SMatthew G. Knepley 4899566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 4909566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 4919566063dSJacob Faibussowitsch PetscCall(DMRefine(*newdm, comm, &rdm)); 4929566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)*newdm, &name)); 4939566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, name)); 4949566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 4951df5d5c5SMatthew G. Knepley *newdm = rdm; 4961df5d5c5SMatthew G. Knepley } 4971df5d5c5SMatthew G. Knepley if (interpolate) { 4985fd9971aSMatthew G. Knepley DM idm; 4991df5d5c5SMatthew G. Knepley 5009566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*newdm, &idm)); 5019566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 5021df5d5c5SMatthew G. Knepley *newdm = idm; 5031df5d5c5SMatthew G. Knepley } 5043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5051df5d5c5SMatthew G. Knepley } 5061df5d5c5SMatthew G. Knepley 507d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 508d71ae5a4SJacob Faibussowitsch { 5099318fe57SMatthew G. Knepley const PetscInt numVertices = 2; 5109318fe57SMatthew G. Knepley PetscInt markerRight = 1; 5119318fe57SMatthew G. Knepley PetscInt markerLeft = 1; 5129318fe57SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 5139318fe57SMatthew G. Knepley Vec coordinates; 5149318fe57SMatthew G. Knepley PetscSection coordSection; 5159318fe57SMatthew G. Knepley PetscScalar *coords; 5169318fe57SMatthew G. Knepley PetscInt coordSize; 5179318fe57SMatthew G. Knepley PetscMPIInt rank; 5189318fe57SMatthew G. Knepley PetscInt cdim = 1, v; 519552f7358SJed Brown 5209318fe57SMatthew G. Knepley PetscFunctionBegin; 5219566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 5229318fe57SMatthew G. Knepley if (markerSeparate) { 5239318fe57SMatthew G. Knepley markerRight = 2; 5249318fe57SMatthew G. Knepley markerLeft = 1; 5259318fe57SMatthew G. Knepley } 5269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 527c5853193SPierre Jolivet if (rank == 0) { 5289566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numVertices)); 5299566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 5309566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft)); 5319566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight)); 5329318fe57SMatthew G. Knepley } 5339566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 5349566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 5359318fe57SMatthew G. Knepley /* Build coordinates */ 5369566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 5379566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 5389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 5399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, 0, numVertices)); 5409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 5419318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 5429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 5439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 5449318fe57SMatthew G. Knepley } 5459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 5469566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 5479566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 5489566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 5499566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 5509566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 5519566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 5529566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5539318fe57SMatthew G. Knepley coords[0] = lower[0]; 5549318fe57SMatthew G. Knepley coords[1] = upper[0]; 5559566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 5569566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 5579566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 5583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5599318fe57SMatthew G. Knepley } 56026492d91SMatthew G. Knepley 561d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 562d71ae5a4SJacob Faibussowitsch { 5631df21d24SMatthew G. Knepley const PetscInt numVertices = (edges[0] + 1) * (edges[1] + 1); 5641df21d24SMatthew G. Knepley const PetscInt numEdges = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1]; 565552f7358SJed Brown PetscInt markerTop = 1; 566552f7358SJed Brown PetscInt markerBottom = 1; 567552f7358SJed Brown PetscInt markerRight = 1; 568552f7358SJed Brown PetscInt markerLeft = 1; 569552f7358SJed Brown PetscBool markerSeparate = PETSC_FALSE; 570552f7358SJed Brown Vec coordinates; 571552f7358SJed Brown PetscSection coordSection; 572552f7358SJed Brown PetscScalar *coords; 573552f7358SJed Brown PetscInt coordSize; 574552f7358SJed Brown PetscMPIInt rank; 575552f7358SJed Brown PetscInt v, vx, vy; 576552f7358SJed Brown 577552f7358SJed Brown PetscFunctionBegin; 5789566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 579552f7358SJed Brown if (markerSeparate) { 5801df21d24SMatthew G. Knepley markerTop = 3; 5811df21d24SMatthew G. Knepley markerBottom = 1; 5821df21d24SMatthew G. Knepley markerRight = 2; 5831df21d24SMatthew G. Knepley markerLeft = 4; 584552f7358SJed Brown } 5859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 586dd400576SPatrick Sanan if (rank == 0) { 587552f7358SJed Brown PetscInt e, ex, ey; 588552f7358SJed Brown 5899566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices)); 59048a46eb9SPierre Jolivet for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 5919566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 592552f7358SJed Brown for (vx = 0; vx <= edges[0]; vx++) { 593552f7358SJed Brown for (ey = 0; ey < edges[1]; ey++) { 594552f7358SJed Brown PetscInt edge = vx * edges[1] + ey + edges[0] * (edges[1] + 1); 595552f7358SJed Brown PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges; 596da80777bSKarl Rupp PetscInt cone[2]; 597552f7358SJed Brown 5989371c9d4SSatish Balay cone[0] = vertex; 5999371c9d4SSatish Balay cone[1] = vertex + edges[0] + 1; 6009566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 601552f7358SJed Brown if (vx == edges[0]) { 6029566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 6039566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 604552f7358SJed Brown if (ey == edges[1] - 1) { 6059566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 6069566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 607552f7358SJed Brown } 608552f7358SJed Brown } else if (vx == 0) { 6099566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 6109566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 611552f7358SJed Brown if (ey == edges[1] - 1) { 6129566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 6139566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft)); 614552f7358SJed Brown } 615552f7358SJed Brown } 616552f7358SJed Brown } 617552f7358SJed Brown } 618552f7358SJed Brown for (vy = 0; vy <= edges[1]; vy++) { 619552f7358SJed Brown for (ex = 0; ex < edges[0]; ex++) { 620552f7358SJed Brown PetscInt edge = vy * edges[0] + ex; 621552f7358SJed Brown PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges; 622da80777bSKarl Rupp PetscInt cone[2]; 623552f7358SJed Brown 6249371c9d4SSatish Balay cone[0] = vertex; 6259371c9d4SSatish Balay cone[1] = vertex + 1; 6269566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 627552f7358SJed Brown if (vy == edges[1]) { 6289566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 6299566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 630552f7358SJed Brown if (ex == edges[0] - 1) { 6319566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 6329566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 633552f7358SJed Brown } 634552f7358SJed Brown } else if (vy == 0) { 6359566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 6369566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 637552f7358SJed Brown if (ex == edges[0] - 1) { 6389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 6399566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 640552f7358SJed Brown } 641552f7358SJed Brown } 642552f7358SJed Brown } 643552f7358SJed Brown } 644552f7358SJed Brown } 6459566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 6469566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 647552f7358SJed Brown /* Build coordinates */ 6489566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 2)); 6499566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 6509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 6519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 6529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 653552f7358SJed Brown for (v = numEdges; v < numEdges + numVertices; ++v) { 6549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 2)); 6559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 656552f7358SJed Brown } 6579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6589566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 6599566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 6609566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 6619566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 6629566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 2)); 6639566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 6649566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 665552f7358SJed Brown for (vy = 0; vy <= edges[1]; ++vy) { 666552f7358SJed Brown for (vx = 0; vx <= edges[0]; ++vx) { 667552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx; 668552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy; 669552f7358SJed Brown } 670552f7358SJed Brown } 6719566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 6729566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 6739566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 6743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 675552f7358SJed Brown } 676552f7358SJed Brown 677d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 678d71ae5a4SJacob Faibussowitsch { 6799e8abbc3SMichael Lange PetscInt vertices[3], numVertices; 6807b59f5a9SMichael Lange PetscInt numFaces = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2]; 681c2df9bbfSMatthew G. Knepley PetscInt markerTop = 1; 682c2df9bbfSMatthew G. Knepley PetscInt markerBottom = 1; 683c2df9bbfSMatthew G. Knepley PetscInt markerFront = 1; 684c2df9bbfSMatthew G. Knepley PetscInt markerBack = 1; 685c2df9bbfSMatthew G. Knepley PetscInt markerRight = 1; 686c2df9bbfSMatthew G. Knepley PetscInt markerLeft = 1; 687c2df9bbfSMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 688552f7358SJed Brown Vec coordinates; 689552f7358SJed Brown PetscSection coordSection; 690552f7358SJed Brown PetscScalar *coords; 691552f7358SJed Brown PetscInt coordSize; 692552f7358SJed Brown PetscMPIInt rank; 693552f7358SJed Brown PetscInt v, vx, vy, vz; 6947b59f5a9SMichael Lange PetscInt voffset, iface = 0, cone[4]; 695552f7358SJed Brown 696552f7358SJed Brown PetscFunctionBegin; 6971dca8a05SBarry Smith PetscCheck(faces[0] >= 1 && faces[1] >= 1 && faces[2] >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Must have at least 1 face per side"); 6989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 699c2df9bbfSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 700c2df9bbfSMatthew G. Knepley if (markerSeparate) { 701c2df9bbfSMatthew G. Knepley markerBottom = 1; 702c2df9bbfSMatthew G. Knepley markerTop = 2; 703c2df9bbfSMatthew G. Knepley markerFront = 3; 704c2df9bbfSMatthew G. Knepley markerBack = 4; 705c2df9bbfSMatthew G. Knepley markerRight = 5; 706c2df9bbfSMatthew G. Knepley markerLeft = 6; 707c2df9bbfSMatthew G. Knepley } 7089371c9d4SSatish Balay vertices[0] = faces[0] + 1; 7099371c9d4SSatish Balay vertices[1] = faces[1] + 1; 7109371c9d4SSatish Balay vertices[2] = faces[2] + 1; 7119e8abbc3SMichael Lange numVertices = vertices[0] * vertices[1] * vertices[2]; 712dd400576SPatrick Sanan if (rank == 0) { 713552f7358SJed Brown PetscInt f; 714552f7358SJed Brown 7159566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices)); 71648a46eb9SPierre Jolivet for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 7179566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 7187b59f5a9SMichael Lange 7197b59f5a9SMichael Lange /* Side 0 (Top) */ 7207b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7217b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7227b59f5a9SMichael Lange voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx; 7239371c9d4SSatish Balay cone[0] = voffset; 7249371c9d4SSatish Balay cone[1] = voffset + 1; 7259371c9d4SSatish Balay cone[2] = voffset + vertices[0] + 1; 7269371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 7279566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 728c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop)); 729c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop)); 730c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop)); 731c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop)); 732c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop)); 7337b59f5a9SMichael Lange iface++; 734552f7358SJed Brown } 735552f7358SJed Brown } 7367b59f5a9SMichael Lange 7377b59f5a9SMichael Lange /* Side 1 (Bottom) */ 7387b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7397b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7407b59f5a9SMichael Lange voffset = numFaces + vy * (faces[0] + 1) + vx; 7419371c9d4SSatish Balay cone[0] = voffset + 1; 7429371c9d4SSatish Balay cone[1] = voffset; 7439371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 7449371c9d4SSatish Balay cone[3] = voffset + vertices[0] + 1; 7459566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 746c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom)); 747c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom)); 748c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom)); 749c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom)); 750c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom)); 7517b59f5a9SMichael Lange iface++; 752552f7358SJed Brown } 753552f7358SJed Brown } 7547b59f5a9SMichael Lange 7557b59f5a9SMichael Lange /* Side 2 (Front) */ 7567b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 7577b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7587b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vx; 7599371c9d4SSatish Balay cone[0] = voffset; 7609371c9d4SSatish Balay cone[1] = voffset + 1; 7619371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + 1; 7629371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1]; 7639566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 764c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront)); 765c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront)); 766c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront)); 767c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront)); 768c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront)); 7697b59f5a9SMichael Lange iface++; 770552f7358SJed Brown } 7717b59f5a9SMichael Lange } 7727b59f5a9SMichael Lange 7737b59f5a9SMichael Lange /* Side 3 (Back) */ 7747b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 7757b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7767b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx; 7779371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 7789371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1] + 1; 7799371c9d4SSatish Balay cone[2] = voffset + 1; 7809371c9d4SSatish Balay cone[3] = voffset; 7819566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 782c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack)); 783c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack)); 784c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack)); 785c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack)); 786c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack)); 7877b59f5a9SMichael Lange iface++; 7887b59f5a9SMichael Lange } 7897b59f5a9SMichael Lange } 7907b59f5a9SMichael Lange 7917b59f5a9SMichael Lange /* Side 4 (Left) */ 7927b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 7937b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7947b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0]; 7959371c9d4SSatish Balay cone[0] = voffset; 7969371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1]; 7979371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + vertices[0]; 7989371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 7999566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 800c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft)); 801c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft)); 802c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft)); 803c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft)); 804c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft)); 8057b59f5a9SMichael Lange iface++; 8067b59f5a9SMichael Lange } 8077b59f5a9SMichael Lange } 8087b59f5a9SMichael Lange 8097b59f5a9SMichael Lange /* Side 5 (Right) */ 8107b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8117b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 812aab5bcd8SJed Brown voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0]; 8139371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 8149371c9d4SSatish Balay cone[1] = voffset; 8159371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 8169371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1] + vertices[0]; 8179566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 818c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight)); 819c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight)); 820c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight)); 821c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight)); 822c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight)); 8237b59f5a9SMichael Lange iface++; 8247b59f5a9SMichael Lange } 825552f7358SJed Brown } 826552f7358SJed Brown } 8279566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 8289566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 829552f7358SJed Brown /* Build coordinates */ 8309566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 3)); 8319566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 8339566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 8349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 835552f7358SJed Brown for (v = numFaces; v < numFaces + numVertices; ++v) { 8369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 3)); 8379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 838552f7358SJed Brown } 8399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 8409566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 8419566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 8429566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 8439566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 8449566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 3)); 8459566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 8469566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 847552f7358SJed Brown for (vz = 0; vz <= faces[2]; ++vz) { 848552f7358SJed Brown for (vy = 0; vy <= faces[1]; ++vy) { 849552f7358SJed Brown for (vx = 0; vx <= faces[0]; ++vx) { 850552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx; 851552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy; 852552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz; 853552f7358SJed Brown } 854552f7358SJed Brown } 855552f7358SJed Brown } 8569566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 8579566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 8589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 8593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 860552f7358SJed Brown } 861552f7358SJed Brown 862d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) 863d71ae5a4SJacob Faibussowitsch { 8649318fe57SMatthew G. Knepley PetscFunctionBegin; 8659318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 86646139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 8679566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim - 1)); 8689566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim)); 8699318fe57SMatthew G. Knepley switch (dim) { 870d71ae5a4SJacob Faibussowitsch case 1: 871d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces)); 872d71ae5a4SJacob Faibussowitsch break; 873d71ae5a4SJacob Faibussowitsch case 2: 874d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces)); 875d71ae5a4SJacob Faibussowitsch break; 876d71ae5a4SJacob Faibussowitsch case 3: 877d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces)); 878d71ae5a4SJacob Faibussowitsch break; 879d71ae5a4SJacob Faibussowitsch default: 880d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim); 8819318fe57SMatthew G. Knepley } 88246139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 8839566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 8843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8859318fe57SMatthew G. Knepley } 8869318fe57SMatthew G. Knepley 8879318fe57SMatthew G. Knepley /*@C 8889318fe57SMatthew G. Knepley DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra). 8899318fe57SMatthew G. Knepley 8909318fe57SMatthew G. Knepley Collective 8919318fe57SMatthew G. Knepley 8929318fe57SMatthew G. Knepley Input Parameters: 893a1cb98faSBarry Smith + comm - The communicator for the `DM` object 89420f4b53cSBarry Smith . dim - The spatial dimension of the box, so the resulting mesh is has dimension `dim`-1 89520f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 89620f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 89720f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 8989318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 8999318fe57SMatthew G. Knepley 9009318fe57SMatthew G. Knepley Output Parameter: 901a1cb98faSBarry Smith . dm - The `DM` object 9029318fe57SMatthew G. Knepley 9039318fe57SMatthew G. Knepley Level: beginner 9049318fe57SMatthew G. Knepley 9051cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()` 9069318fe57SMatthew G. Knepley @*/ 907d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) 908d71ae5a4SJacob Faibussowitsch { 9099318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 9109318fe57SMatthew G. Knepley PetscReal low[3] = {0, 0, 0}; 9119318fe57SMatthew G. Knepley PetscReal upp[3] = {1, 1, 1}; 9129318fe57SMatthew G. Knepley 9139318fe57SMatthew G. Knepley PetscFunctionBegin; 9149566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 9159566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 9169566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate)); 9173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9189318fe57SMatthew G. Knepley } 9199318fe57SMatthew G. Knepley 920d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd) 921d71ae5a4SJacob Faibussowitsch { 922fdbf62faSLisandro Dalcin PetscInt i, fStart, fEnd, numCells = 0, numVerts = 0; 923fdbf62faSLisandro Dalcin PetscInt numPoints[2], *coneSize, *cones, *coneOrientations; 924fdbf62faSLisandro Dalcin PetscScalar *vertexCoords; 925fdbf62faSLisandro Dalcin PetscReal L, maxCell; 926fdbf62faSLisandro Dalcin PetscBool markerSeparate = PETSC_FALSE; 927fdbf62faSLisandro Dalcin PetscInt markerLeft = 1, faceMarkerLeft = 1; 928fdbf62faSLisandro Dalcin PetscInt markerRight = 1, faceMarkerRight = 2; 929fdbf62faSLisandro Dalcin PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 930fdbf62faSLisandro Dalcin PetscMPIInt rank; 931fdbf62faSLisandro Dalcin 932fdbf62faSLisandro Dalcin PetscFunctionBegin; 9334f572ea9SToby Isaac PetscAssertPointer(dm, 1); 934fdbf62faSLisandro Dalcin 9359566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, 1)); 9369566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 9379566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 938fdbf62faSLisandro Dalcin 9399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 940dd400576SPatrick Sanan if (rank == 0) numCells = segments; 941dd400576SPatrick Sanan if (rank == 0) numVerts = segments + (wrap ? 0 : 1); 942fdbf62faSLisandro Dalcin 9439371c9d4SSatish Balay numPoints[0] = numVerts; 9449371c9d4SSatish Balay numPoints[1] = numCells; 9459566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords)); 9469566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts)); 947ad540459SPierre Jolivet for (i = 0; i < numCells; ++i) coneSize[i] = 2; 948ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0; 9499371c9d4SSatish Balay for (i = 0; i < numCells; ++i) { 9509371c9d4SSatish Balay cones[2 * i] = numCells + i % numVerts; 9519371c9d4SSatish Balay cones[2 * i + 1] = numCells + (i + 1) % numVerts; 9529371c9d4SSatish Balay } 953ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells); 9549566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 9559566063dSJacob Faibussowitsch PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords)); 956fdbf62faSLisandro Dalcin 9579566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 9589371c9d4SSatish Balay if (markerSeparate) { 9599371c9d4SSatish Balay markerLeft = faceMarkerLeft; 9609371c9d4SSatish Balay markerRight = faceMarkerRight; 9619371c9d4SSatish Balay } 962dd400576SPatrick Sanan if (!wrap && rank == 0) { 9639566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 9649566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft)); 9659566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight)); 9669566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft)); 9679566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight)); 968fdbf62faSLisandro Dalcin } 969fdbf62faSLisandro Dalcin if (wrap) { 970fdbf62faSLisandro Dalcin L = upper - lower; 971fdbf62faSLisandro Dalcin maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments)); 9724fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L)); 973fdbf62faSLisandro Dalcin } 9749566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 9753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 976fdbf62faSLisandro Dalcin } 977fdbf62faSLisandro Dalcin 9784054ae39SJames Wright // Creates "Face Sets" label based on the standard box labeling conventions 979d7d2d1d2SJames Wright static PetscErrorCode DMPlexSetBoxLabel_Internal(DM dm, const DMBoundaryType periodicity[]) 9804054ae39SJames Wright { 9816ff49feeSJames Wright DM cdm; 9826ff49feeSJames Wright PetscSection csection; 9836ff49feeSJames Wright Vec coordinates; 9844054ae39SJames Wright DMLabel label; 9856ff49feeSJames Wright IS faces_is; 9862b4f33d9SJames Wright PetscInt dim, num_face = 0; 9874054ae39SJames Wright const PetscInt *faces; 9884054ae39SJames Wright PetscInt faceMarkerBottom, faceMarkerTop, faceMarkerFront, faceMarkerBack, faceMarkerRight, faceMarkerLeft; 9894054ae39SJames Wright 9904054ae39SJames Wright PetscFunctionBeginUser; 9914054ae39SJames Wright PetscCall(DMGetDimension(dm, &dim)); 992d7c1f440SPierre Jolivet PetscCheck((dim == 2) || (dim == 3), PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DMPlex box labeling only supports 2D and 3D meshes, received DM of dimension %" PetscInt_FMT, dim); 9934054ae39SJames Wright // Get Face Sets label 9944054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 9954054ae39SJames Wright if (label) { 9964054ae39SJames Wright PetscCall(DMLabelReset(label)); 9974054ae39SJames Wright } else { 9984054ae39SJames Wright PetscCall(DMCreateLabel(dm, "Face Sets")); 9994054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 10004054ae39SJames Wright } 10014054ae39SJames Wright PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label)); 10026ff49feeSJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", 1, &faces_is)); 10034054ae39SJames Wright 10044054ae39SJames Wright switch (dim) { 10054054ae39SJames Wright case 2: 10064054ae39SJames Wright faceMarkerTop = 3; 10074054ae39SJames Wright faceMarkerBottom = 1; 10084054ae39SJames Wright faceMarkerRight = 2; 10094054ae39SJames Wright faceMarkerLeft = 4; 10104054ae39SJames Wright break; 10114054ae39SJames Wright case 3: 10124054ae39SJames Wright faceMarkerBottom = 1; 10134054ae39SJames Wright faceMarkerTop = 2; 10144054ae39SJames Wright faceMarkerFront = 3; 10154054ae39SJames Wright faceMarkerBack = 4; 10164054ae39SJames Wright faceMarkerRight = 5; 10174054ae39SJames Wright faceMarkerLeft = 6; 10184054ae39SJames Wright break; 10194054ae39SJames Wright default: 10204054ae39SJames Wright SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 10214054ae39SJames Wright } 10224054ae39SJames Wright 10232b4f33d9SJames Wright if (faces_is) PetscCall(ISGetLocalSize(faces_is, &num_face)); 10242b4f33d9SJames Wright if (faces_is) PetscCall(ISGetIndices(faces_is, &faces)); 10256ff49feeSJames Wright PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 10266ff49feeSJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 10276ff49feeSJames Wright PetscCall(DMGetLocalSection(cdm, &csection)); 10284054ae39SJames Wright for (PetscInt f = 0; f < num_face; ++f) { 10296ff49feeSJames Wright PetscScalar *coords = NULL; 10306ff49feeSJames Wright PetscInt face = faces[f], flip = 1, label_value = -1, coords_size; 10314054ae39SJames Wright 10324054ae39SJames Wright { // Determine if orientation of face is flipped 10334054ae39SJames Wright PetscInt num_cells_support, num_faces, start = -1; 10344054ae39SJames Wright const PetscInt *orients, *cell_faces, *cells; 10354054ae39SJames Wright 10364054ae39SJames Wright PetscCall(DMPlexGetSupport(dm, face, &cells)); 10374054ae39SJames Wright PetscCall(DMPlexGetSupportSize(dm, face, &num_cells_support)); 10384054ae39SJames Wright PetscCheck(num_cells_support == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Expected one cell in support of exterior face, but got %" PetscInt_FMT " cells", num_cells_support); 10394054ae39SJames Wright PetscCall(DMPlexGetCone(dm, cells[0], &cell_faces)); 10404054ae39SJames Wright PetscCall(DMPlexGetConeSize(dm, cells[0], &num_faces)); 10414054ae39SJames Wright for (PetscInt i = 0; i < num_faces; i++) { 10424054ae39SJames Wright if (cell_faces[i] == face) start = i; 10434054ae39SJames Wright } 10444054ae39SJames Wright PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Could not find face %" PetscInt_FMT " in cone of its support", face); 10454054ae39SJames Wright PetscCall(DMPlexGetConeOrientation(dm, cells[0], &orients)); 10464054ae39SJames Wright if (orients[start] < 0) flip = -1; 10474054ae39SJames Wright } 10484054ae39SJames Wright 10496ff49feeSJames Wright // Cannot use DMPlexComputeCellGeometryFVM() for high-order geometry, so must calculate normal vectors manually 10506ff49feeSJames Wright // Use the vertices (depth 0) of coordinate DM to calculate normal vector 10516ff49feeSJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 10524054ae39SJames Wright switch (dim) { 10534054ae39SJames Wright case 2: { 10546ff49feeSJames Wright PetscScalar vec[2]; 10556ff49feeSJames Wright 10566ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) vec[d] = flip * (PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d])); 10576ff49feeSJames Wright PetscScalar normal[] = {vec[1], -vec[0]}; 10586ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 10596ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 10604054ae39SJames Wright } else { 10616ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerTop : faceMarkerBottom; 10624054ae39SJames Wright } 10634054ae39SJames Wright } break; 10644054ae39SJames Wright case 3: { 10656ff49feeSJames Wright PetscScalar vec1[3], vec2[3], normal[3]; 10666ff49feeSJames Wright 10676ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) { 10686ff49feeSJames Wright vec1[d] = PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]); 10696ff49feeSJames Wright vec2[d] = PetscRealPart(coords[2 * dim + d]) - PetscRealPart(coords[1 * dim + d]); 10706ff49feeSJames Wright } 10716ff49feeSJames Wright 10726ff49feeSJames Wright // Calculate normal vector via cross-product 10736ff49feeSJames Wright normal[0] = flip * ((vec1[1] * vec2[2]) - (vec1[2] * vec2[1])); 10746ff49feeSJames Wright normal[1] = flip * ((vec1[2] * vec2[0]) - (vec1[0] * vec2[2])); 10756ff49feeSJames Wright normal[2] = flip * ((vec1[0] * vec2[1]) - (vec1[1] * vec2[0])); 10766ff49feeSJames Wright 10776ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 10786ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[2])) { 10796ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 10804054ae39SJames Wright } else { 10816ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 10824054ae39SJames Wright } 10834054ae39SJames Wright } else { 10846ff49feeSJames Wright if (PetscAbsScalar(normal[1]) > PetscAbsScalar(normal[2])) { 10856ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerBack : faceMarkerFront; 10864054ae39SJames Wright } else { 10876ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 10884054ae39SJames Wright } 10894054ae39SJames Wright } 10904054ae39SJames Wright } break; 10914054ae39SJames Wright } 10924054ae39SJames Wright 10934054ae39SJames Wright PetscInt previous_label_value; // always 1 due to DMPlexMarkBoundaryFaces call above 10944054ae39SJames Wright PetscCall(DMGetLabelValue(dm, "Face Sets", face, &previous_label_value)); 10954054ae39SJames Wright PetscCall(DMClearLabelValue(dm, "Face Sets", face, previous_label_value)); 10964054ae39SJames Wright PetscCall(DMSetLabelValue(dm, "Face Sets", face, label_value)); 10976ff49feeSJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 10984054ae39SJames Wright } 10992b4f33d9SJames Wright if (faces_is) PetscCall(ISRestoreIndices(faces_is, &faces)); 11006ff49feeSJames Wright PetscCall(ISDestroy(&faces_is)); 1101d7d2d1d2SJames Wright 1102d7d2d1d2SJames Wright // Create Isoperiodic SF from newly-created face labels 1103d7d2d1d2SJames Wright PetscSF periodicsfs[3]; 1104d7d2d1d2SJames Wright PetscInt periodic_sf_index = 0; 1105d7d2d1d2SJames Wright PetscScalar transform[3][4][4] = {{{0.}}}; 1106d7d2d1d2SJames Wright for (PetscInt d = 0; d < dim; d++) { 1107d7d2d1d2SJames Wright IS donor_is, periodic_is; 1108d7d2d1d2SJames Wright const PetscInt *donor_faces = NULL, *periodic_faces = NULL; 1109d7d2d1d2SJames Wright PetscInt num_donor = 0, num_periodic = 0; 1110d7d2d1d2SJames Wright PetscSF centroidsf; 1111d7d2d1d2SJames Wright PetscReal donor_to_periodic_distance; 1112d7d2d1d2SJames Wright const PetscInt face_pairings[2][3][2] = { 1113d7d2d1d2SJames Wright // 2D face pairings, {donor, periodic} 1114d7d2d1d2SJames Wright {{4, 2}, {1, 3}}, 1115d7d2d1d2SJames Wright // 3D face pairings 1116d7d2d1d2SJames Wright {{5, 6}, {3, 4}, {1, 2}} 1117d7d2d1d2SJames Wright }; 1118d7d2d1d2SJames Wright 1119d7d2d1d2SJames Wright if (periodicity[d] != DM_BOUNDARY_PERIODIC) continue; 1120d7d2d1d2SJames Wright { 1121d7d2d1d2SJames Wright // Compute centroidsf, which is the mapping from donor faces to periodic faces 1122d7d2d1d2SJames Wright // Matches the centroid of the faces together, ignoring the periodic direction component (which should not match between donor and periodic face) 1123d7d2d1d2SJames Wright PetscInt coords_size, centroid_comps = dim - 1; 1124d7d2d1d2SJames Wright PetscScalar *coords = NULL; 1125d7d2d1d2SJames Wright PetscReal *donor_centroids, *periodic_centroids; 1126d7d2d1d2SJames Wright PetscReal loc_periodic[2] = {PETSC_MIN_REAL, PETSC_MIN_REAL}, loc_periodic_global[2]; // Location of donor (0) and periodic (1) faces in periodic direction 1127d7d2d1d2SJames Wright 1128d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][0], &donor_is)); 1129d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][1], &periodic_is)); 1130d7d2d1d2SJames Wright if (donor_is) { 1131d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(donor_is, &num_donor)); 1132d7d2d1d2SJames Wright PetscCall(ISGetIndices(donor_is, &donor_faces)); 1133d7d2d1d2SJames Wright } 1134d7d2d1d2SJames Wright if (periodic_is) { 1135d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(periodic_is, &num_periodic)); 1136d7d2d1d2SJames Wright PetscCall(ISGetIndices(periodic_is, &periodic_faces)); 1137d7d2d1d2SJames Wright } 1138d7d2d1d2SJames Wright PetscCall(PetscCalloc2(num_donor * centroid_comps, &donor_centroids, num_periodic * centroid_comps, &periodic_centroids)); 1139d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_donor; f++) { 1140d7d2d1d2SJames Wright PetscInt face = donor_faces[f], num_coords; 1141d7d2d1d2SJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 1142d7d2d1d2SJames Wright num_coords = coords_size / dim; 1143d7d2d1d2SJames Wright for (PetscInt c = 0; c < num_coords; c++) { 1144d7d2d1d2SJames Wright PetscInt comp_index = 0; 1145d7d2d1d2SJames Wright loc_periodic[0] = PetscRealPart(coords[c * dim + d]); 1146d7d2d1d2SJames Wright for (PetscInt i = 0; i < dim; i++) { 1147d7d2d1d2SJames Wright if (i == d) continue; // Periodic direction not used for centroid calculation 1148d7d2d1d2SJames Wright donor_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords; 1149d7d2d1d2SJames Wright comp_index++; 1150d7d2d1d2SJames Wright } 1151d7d2d1d2SJames Wright } 1152d7d2d1d2SJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 1153d7d2d1d2SJames Wright } 1154d7d2d1d2SJames Wright 1155d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_periodic; f++) { 1156d7d2d1d2SJames Wright PetscInt face = periodic_faces[f], num_coords; 1157d7d2d1d2SJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 1158d7d2d1d2SJames Wright num_coords = coords_size / dim; 1159d7d2d1d2SJames Wright for (PetscInt c = 0; c < num_coords; c++) { 1160d7d2d1d2SJames Wright PetscInt comp_index = 0; 1161d7d2d1d2SJames Wright loc_periodic[1] = PetscRealPart(coords[c * dim + d]); 1162d7d2d1d2SJames Wright for (PetscInt i = 0; i < dim; i++) { 1163d7d2d1d2SJames Wright if (i == d) continue; // Periodic direction not used for centroid calculation 1164d7d2d1d2SJames Wright periodic_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords; 1165d7d2d1d2SJames Wright comp_index++; 1166d7d2d1d2SJames Wright } 1167d7d2d1d2SJames Wright } 1168d7d2d1d2SJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 1169d7d2d1d2SJames Wright } 1170d7d2d1d2SJames Wright PetscCallMPI(MPIU_Allreduce(loc_periodic, loc_periodic_global, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm))); 1171d7d2d1d2SJames Wright donor_to_periodic_distance = loc_periodic_global[1] - loc_periodic_global[0]; 1172d7d2d1d2SJames Wright 1173d7d2d1d2SJames Wright PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), ¢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 1239*d698cf03SStefano Zampini static PetscErrorCode DMPlexCreateSquareMesh_Simplex_CrissCross(DM dm, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType bd[]) 1240*d698cf03SStefano Zampini { 1241*d698cf03SStefano Zampini PetscInt markerTop = 1, faceMarkerTop = 3; 1242*d698cf03SStefano Zampini PetscInt markerBottom = 1, faceMarkerBottom = 1; 1243*d698cf03SStefano Zampini PetscInt markerRight = 1, faceMarkerRight = 2; 1244*d698cf03SStefano Zampini PetscInt markerLeft = 1, faceMarkerLeft = 4; 1245*d698cf03SStefano Zampini PetscBool markerSeparate = PETSC_FALSE; 1246*d698cf03SStefano Zampini DMBoundaryType bdX = bd[0], bdY = bd[1]; 1247*d698cf03SStefano Zampini PetscMPIInt rank; 1248*d698cf03SStefano Zampini 1249*d698cf03SStefano Zampini PetscFunctionBegin; 1250*d698cf03SStefano Zampini PetscCheck(bdX == DM_BOUNDARY_NONE || bdX == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdX]); 1251*d698cf03SStefano Zampini PetscCheck(bdY == DM_BOUNDARY_NONE || bdY == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdY]); 1252*d698cf03SStefano Zampini PetscCall(DMSetDimension(dm, 2)); 1253*d698cf03SStefano Zampini PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1254*d698cf03SStefano Zampini PetscCall(DMCreateLabel(dm, "marker")); 1255*d698cf03SStefano Zampini PetscCall(DMCreateLabel(dm, "Face Sets")); 1256*d698cf03SStefano Zampini PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 1257*d698cf03SStefano Zampini if (markerSeparate) { 1258*d698cf03SStefano Zampini markerBottom = faceMarkerBottom; 1259*d698cf03SStefano Zampini markerTop = faceMarkerTop; 1260*d698cf03SStefano Zampini markerRight = faceMarkerRight; 1261*d698cf03SStefano Zampini markerLeft = faceMarkerLeft; 1262*d698cf03SStefano Zampini } 1263*d698cf03SStefano Zampini { 1264*d698cf03SStefano Zampini const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 1265*d698cf03SStefano Zampini const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 1266*d698cf03SStefano Zampini const PetscInt numZEdges = rank == 0 ? 4 * edges[0] * edges[1] : 0; /* Z-edges are the 4 internal edges per cell */ 1267*d698cf03SStefano Zampini const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC ? edges[0] : edges[0] + 1) : 0; 1268*d698cf03SStefano Zampini const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC ? edges[1] : edges[1] + 1) : 0; 1269*d698cf03SStefano Zampini const PetscInt numZVertices = rank == 0 ? edges[0] * edges[1] : 0; 1270*d698cf03SStefano Zampini const PetscInt numCells = 4 * numXEdges * numYEdges; 1271*d698cf03SStefano Zampini const PetscInt numTotXEdges = numXEdges * numYVertices; 1272*d698cf03SStefano Zampini const PetscInt numTotYEdges = numYEdges * numXVertices; 1273*d698cf03SStefano Zampini const PetscInt numVertices = numXVertices * numYVertices + numZVertices; 1274*d698cf03SStefano Zampini const PetscInt numEdges = numTotXEdges + numTotYEdges + numZEdges; 1275*d698cf03SStefano Zampini const PetscInt firstVertex = numCells; 1276*d698cf03SStefano Zampini const PetscInt firstXEdge = numCells + numVertices; 1277*d698cf03SStefano Zampini const PetscInt firstYEdge = firstXEdge + numTotXEdges; 1278*d698cf03SStefano Zampini const PetscInt firstZEdge = firstYEdge + numTotYEdges; 1279*d698cf03SStefano Zampini Vec coordinates; 1280*d698cf03SStefano Zampini PetscSection coordSection; 1281*d698cf03SStefano Zampini PetscScalar *coords; 1282*d698cf03SStefano Zampini PetscInt coordSize; 1283*d698cf03SStefano Zampini PetscInt v, vx, vy; 1284*d698cf03SStefano Zampini PetscInt c, e, ex, ey; 1285*d698cf03SStefano Zampini 1286*d698cf03SStefano Zampini PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVertices)); 1287*d698cf03SStefano Zampini for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 3)); 1288*d698cf03SStefano Zampini for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 1289*d698cf03SStefano Zampini PetscCall(DMSetUp(dm)); 1290*d698cf03SStefano Zampini 1291*d698cf03SStefano Zampini /* Build cells and Z-edges */ 1292*d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ++ey) { 1293*d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ++ex) { 1294*d698cf03SStefano Zampini const PetscInt exp1 = (ex + 1) % numXVertices; 1295*d698cf03SStefano Zampini const PetscInt eyp1 = (ey + 1) % numYVertices; 1296*d698cf03SStefano Zampini const PetscInt ez = firstZEdge + 4 * (ey * numXEdges + ex); 1297*d698cf03SStefano Zampini const PetscInt vc = firstVertex + numXVertices * numYVertices + ey * numXEdges + ex; 1298*d698cf03SStefano Zampini const PetscInt v0 = firstVertex + ey * numXVertices + ex; 1299*d698cf03SStefano Zampini const PetscInt v1 = firstVertex + ey * numXVertices + exp1; 1300*d698cf03SStefano Zampini const PetscInt v2 = firstVertex + eyp1 * numXVertices + exp1; 1301*d698cf03SStefano Zampini const PetscInt v3 = firstVertex + eyp1 * numXVertices + ex; 1302*d698cf03SStefano Zampini const PetscInt e0 = firstXEdge + ey * numXEdges + ex; 1303*d698cf03SStefano Zampini const PetscInt e1 = firstYEdge + exp1 * numYEdges + ey; 1304*d698cf03SStefano Zampini const PetscInt e2 = firstXEdge + eyp1 * numXEdges + ex; 1305*d698cf03SStefano Zampini const PetscInt e3 = firstYEdge + ex * numYEdges + ey; 1306*d698cf03SStefano Zampini 1307*d698cf03SStefano Zampini const PetscInt cones[] = {ez, e0, ez + 1, ez + 1, e1, ez + 2, ez + 2, e2, ez + 3, ez + 3, e3, ez}; 1308*d698cf03SStefano Zampini const PetscInt ornts[] = {-1, 0, 0, -1, 0, 0, -1, -1, 0, -1, -1, 0}; 1309*d698cf03SStefano Zampini const PetscInt verts[] = {v0, vc, v1, vc, v2, vc, v3, vc}; 1310*d698cf03SStefano Zampini 1311*d698cf03SStefano Zampini for (c = 0; c < 4; c++) { 1312*d698cf03SStefano Zampini PetscInt cell = 4 * (ey * numXEdges + ex) + c; 1313*d698cf03SStefano Zampini PetscInt edge = ez + c; 1314*d698cf03SStefano Zampini 1315*d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, cell, cones + 3 * c)); 1316*d698cf03SStefano Zampini PetscCall(DMPlexSetConeOrientation(dm, cell, ornts + 3 * c)); 1317*d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, verts + 2 * c)); 1318*d698cf03SStefano Zampini } 1319*d698cf03SStefano Zampini } 1320*d698cf03SStefano Zampini } 1321*d698cf03SStefano Zampini 1322*d698cf03SStefano Zampini /* Build Y edges*/ 1323*d698cf03SStefano Zampini for (vx = 0; vx < numXVertices; vx++) { 1324*d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ey++) { 1325*d698cf03SStefano Zampini const PetscInt edge = firstYEdge + vx * numYEdges + ey; 1326*d698cf03SStefano Zampini const PetscInt v0 = firstVertex + ey * numXVertices + vx; 1327*d698cf03SStefano Zampini const PetscInt v1 = firstVertex + ((ey + 1) % numYVertices) * numXVertices + vx; 1328*d698cf03SStefano Zampini const PetscInt cone[] = {v0, v1}; 1329*d698cf03SStefano Zampini 1330*d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, cone)); 1331*d698cf03SStefano Zampini if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 1332*d698cf03SStefano Zampini if (vx == numXVertices - 1) { 1333*d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 1334*d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1335*d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1336*d698cf03SStefano Zampini if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1337*d698cf03SStefano Zampini } else if (vx == 0) { 1338*d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 1339*d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1340*d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1341*d698cf03SStefano Zampini if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 1342*d698cf03SStefano Zampini } 1343*d698cf03SStefano Zampini } 1344*d698cf03SStefano Zampini } 1345*d698cf03SStefano Zampini } 1346*d698cf03SStefano Zampini 1347*d698cf03SStefano Zampini /* Build X edges*/ 1348*d698cf03SStefano Zampini for (vy = 0; vy < numYVertices; vy++) { 1349*d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ex++) { 1350*d698cf03SStefano Zampini const PetscInt edge = firstXEdge + vy * numXEdges + ex; 1351*d698cf03SStefano Zampini const PetscInt v0 = firstVertex + vy * numXVertices + ex; 1352*d698cf03SStefano Zampini const PetscInt v1 = firstVertex + vy * numXVertices + (ex + 1) % numXVertices; 1353*d698cf03SStefano Zampini const PetscInt cone[] = {v0, v1}; 1354*d698cf03SStefano Zampini 1355*d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, cone)); 1356*d698cf03SStefano Zampini if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 1357*d698cf03SStefano Zampini if (vy == numYVertices - 1) { 1358*d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 1359*d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1360*d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1361*d698cf03SStefano Zampini if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1362*d698cf03SStefano Zampini } else if (vy == 0) { 1363*d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 1364*d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1365*d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1366*d698cf03SStefano Zampini if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 1367*d698cf03SStefano Zampini } 1368*d698cf03SStefano Zampini } 1369*d698cf03SStefano Zampini } 1370*d698cf03SStefano Zampini } 1371*d698cf03SStefano Zampini 1372*d698cf03SStefano Zampini /* Compute support, stratify, and celltype label */ 1373*d698cf03SStefano Zampini PetscCall(DMPlexSymmetrize(dm)); 1374*d698cf03SStefano Zampini PetscCall(DMPlexStratify(dm)); 1375*d698cf03SStefano Zampini PetscCall(DMPlexComputeCellTypes(dm)); 1376*d698cf03SStefano Zampini 1377*d698cf03SStefano Zampini /* Build coordinates */ 1378*d698cf03SStefano Zampini PetscCall(DMGetCoordinateSection(dm, &coordSection)); 1379*d698cf03SStefano Zampini PetscCall(PetscSectionSetNumFields(coordSection, 1)); 1380*d698cf03SStefano Zampini PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 1381*d698cf03SStefano Zampini PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 1382*d698cf03SStefano Zampini for (v = firstVertex; v < firstVertex + numVertices; ++v) { 1383*d698cf03SStefano Zampini PetscCall(PetscSectionSetDof(coordSection, v, 2)); 1384*d698cf03SStefano Zampini PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 1385*d698cf03SStefano Zampini } 1386*d698cf03SStefano Zampini PetscCall(PetscSectionSetUp(coordSection)); 1387*d698cf03SStefano Zampini PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 1388*d698cf03SStefano Zampini PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 1389*d698cf03SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 1390*d698cf03SStefano Zampini PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 1391*d698cf03SStefano Zampini PetscCall(VecSetBlockSize(coordinates, 2)); 1392*d698cf03SStefano Zampini PetscCall(VecSetType(coordinates, VECSTANDARD)); 1393*d698cf03SStefano Zampini PetscCall(VecGetArray(coordinates, &coords)); 1394*d698cf03SStefano Zampini for (vy = 0; vy < numYVertices; ++vy) { 1395*d698cf03SStefano Zampini for (vx = 0; vx < numXVertices; ++vx) { 1396*d698cf03SStefano Zampini coords[2 * (vy * numXVertices + vx) + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 1397*d698cf03SStefano Zampini coords[2 * (vy * numXVertices + vx) + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1398*d698cf03SStefano Zampini } 1399*d698cf03SStefano Zampini } 1400*d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ++ey) { 1401*d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ++ex) { 1402*d698cf03SStefano Zampini const PetscInt c = ey * numXEdges + ex + numYVertices * numXVertices; 1403*d698cf03SStefano Zampini 1404*d698cf03SStefano Zampini coords[2 * c + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * (ex + 0.5); 1405*d698cf03SStefano Zampini coords[2 * c + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * (ey + 0.5); 1406*d698cf03SStefano Zampini } 1407*d698cf03SStefano Zampini } 1408*d698cf03SStefano Zampini PetscCall(VecRestoreArray(coordinates, &coords)); 1409*d698cf03SStefano Zampini PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 1410*d698cf03SStefano Zampini PetscCall(VecDestroy(&coordinates)); 1411*d698cf03SStefano Zampini 1412*d698cf03SStefano Zampini /* handle periodic BC */ 1413*d698cf03SStefano Zampini if (bdX == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_PERIODIC) { 1414*d698cf03SStefano Zampini PetscReal L[2] = {-1., -1.}; 1415*d698cf03SStefano Zampini PetscReal maxCell[2] = {-1., -1.}; 1416*d698cf03SStefano Zampini 1417*d698cf03SStefano Zampini for (PetscInt d = 0; d < 2; ++d) { 1418*d698cf03SStefano Zampini if (bd[d] != DM_BOUNDARY_NONE) { 1419*d698cf03SStefano Zampini L[d] = upper[d] - lower[d]; 1420*d698cf03SStefano Zampini maxCell[d] = 1.1 * (L[d] / PetscMax(1, edges[d])); 1421*d698cf03SStefano Zampini } 1422*d698cf03SStefano Zampini } 1423*d698cf03SStefano Zampini PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1424*d698cf03SStefano Zampini } 1425*d698cf03SStefano Zampini } 1426*d698cf03SStefano Zampini PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 1427*d698cf03SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1428*d698cf03SStefano Zampini } 1429*d698cf03SStefano Zampini 1430d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 1431d71ae5a4SJacob Faibussowitsch { 14329318fe57SMatthew G. Knepley DM boundary, vol; 1433c22d3578SMatthew G. Knepley DMLabel bdlabel; 1434*d698cf03SStefano Zampini PetscBool crisscross = PETSC_FALSE; 1435d6218766SMatthew G. Knepley 1436d6218766SMatthew G. Knepley PetscFunctionBegin; 14374f572ea9SToby Isaac PetscAssertPointer(dm, 1); 1438*d698cf03SStefano Zampini if (dim == 2) PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_box_crisscross", &crisscross, NULL)); 1439*d698cf03SStefano Zampini if (crisscross) { 1440*d698cf03SStefano Zampini PetscCall(DMPlexCreateSquareMesh_Simplex_CrissCross(dm, faces, lower, upper, periodicity)); 1441*d698cf03SStefano Zampini } else { 1442c22d3578SMatthew G. Knepley for (PetscInt i = 0; i < dim; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity is not supported for simplex meshes"); 14439566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary)); 14449566063dSJacob Faibussowitsch PetscCall(DMSetType(boundary, DMPLEX)); 1445*d698cf03SStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)boundary, ((PetscObject)dm)->prefix)); 14469566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 14479566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 1448c22d3578SMatthew G. Knepley PetscCall(DMGetLabel(vol, "marker", &bdlabel)); 1449c22d3578SMatthew G. Knepley if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel)); 14505de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol)); 145169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 1452*d698cf03SStefano Zampini PetscCall(DMDestroy(&boundary)); 1453*d698cf03SStefano Zampini } 14544054ae39SJames Wright if (interpolate) { 14554054ae39SJames Wright PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 1456d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, periodicity)); 14574054ae39SJames Wright } 14583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1459d6218766SMatthew G. Knepley } 1460d6218766SMatthew G. Knepley 1461d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 1462d71ae5a4SJacob Faibussowitsch { 1463ed0e4b50SMatthew G. Knepley DMLabel cutLabel = NULL; 1464f4eb4c5dSMatthew G. Knepley PetscInt markerTop = 1, faceMarkerTop = 1; 1465f4eb4c5dSMatthew G. Knepley PetscInt markerBottom = 1, faceMarkerBottom = 1; 1466f4eb4c5dSMatthew G. Knepley PetscInt markerFront = 1, faceMarkerFront = 1; 1467f4eb4c5dSMatthew G. Knepley PetscInt markerBack = 1, faceMarkerBack = 1; 1468f4eb4c5dSMatthew G. Knepley PetscInt markerRight = 1, faceMarkerRight = 1; 1469f4eb4c5dSMatthew G. Knepley PetscInt markerLeft = 1, faceMarkerLeft = 1; 14703dfda0b1SToby Isaac PetscInt dim; 1471d8211ee3SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 14723dfda0b1SToby Isaac PetscMPIInt rank; 14733dfda0b1SToby Isaac 14743dfda0b1SToby Isaac PetscFunctionBegin; 14759566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 14769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 14779566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 14789566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 14799566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 14809371c9d4SSatish Balay if (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST || bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST || bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST) { 14819371c9d4SSatish Balay if (cutMarker) { 14829371c9d4SSatish Balay PetscCall(DMCreateLabel(dm, "periodic_cut")); 14839371c9d4SSatish Balay PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 14849371c9d4SSatish Balay } 1485d8211ee3SMatthew G. Knepley } 14863dfda0b1SToby Isaac switch (dim) { 14873dfda0b1SToby Isaac case 2: 1488f4eb4c5dSMatthew G. Knepley faceMarkerTop = 3; 1489f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1490f4eb4c5dSMatthew G. Knepley faceMarkerRight = 2; 1491f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 4; 14923dfda0b1SToby Isaac break; 14933dfda0b1SToby Isaac case 3: 1494f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1495f4eb4c5dSMatthew G. Knepley faceMarkerTop = 2; 1496f4eb4c5dSMatthew G. Knepley faceMarkerFront = 3; 1497f4eb4c5dSMatthew G. Knepley faceMarkerBack = 4; 1498f4eb4c5dSMatthew G. Knepley faceMarkerRight = 5; 1499f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 6; 15003dfda0b1SToby Isaac break; 1501d71ae5a4SJacob Faibussowitsch default: 1502d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 15033dfda0b1SToby Isaac } 15049566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 1505f4eb4c5dSMatthew G. Knepley if (markerSeparate) { 1506f4eb4c5dSMatthew G. Knepley markerBottom = faceMarkerBottom; 1507f4eb4c5dSMatthew G. Knepley markerTop = faceMarkerTop; 1508f4eb4c5dSMatthew G. Knepley markerFront = faceMarkerFront; 1509f4eb4c5dSMatthew G. Knepley markerBack = faceMarkerBack; 1510f4eb4c5dSMatthew G. Knepley markerRight = faceMarkerRight; 1511f4eb4c5dSMatthew G. Knepley markerLeft = faceMarkerLeft; 15123dfda0b1SToby Isaac } 15133dfda0b1SToby Isaac { 1514dd400576SPatrick Sanan const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 1515dd400576SPatrick Sanan const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 1516dd400576SPatrick Sanan const PetscInt numZEdges = rank == 0 ? edges[2] : 0; 1517dd400576SPatrick Sanan const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0; 1518dd400576SPatrick Sanan const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0; 1519dd400576SPatrick Sanan const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0; 15203dfda0b1SToby Isaac const PetscInt numCells = numXEdges * numYEdges * numZEdges; 15213dfda0b1SToby Isaac const PetscInt numXFaces = numYEdges * numZEdges; 15223dfda0b1SToby Isaac const PetscInt numYFaces = numXEdges * numZEdges; 15233dfda0b1SToby Isaac const PetscInt numZFaces = numXEdges * numYEdges; 15243dfda0b1SToby Isaac const PetscInt numTotXFaces = numXVertices * numXFaces; 15253dfda0b1SToby Isaac const PetscInt numTotYFaces = numYVertices * numYFaces; 15263dfda0b1SToby Isaac const PetscInt numTotZFaces = numZVertices * numZFaces; 15273dfda0b1SToby Isaac const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 15283dfda0b1SToby Isaac const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices; 15293dfda0b1SToby Isaac const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices; 15303dfda0b1SToby Isaac const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices; 15313dfda0b1SToby Isaac const PetscInt numVertices = numXVertices * numYVertices * numZVertices; 15323dfda0b1SToby Isaac const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 15333dfda0b1SToby Isaac const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 15343dfda0b1SToby Isaac const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 15353dfda0b1SToby Isaac const PetscInt firstYFace = firstXFace + numTotXFaces; 15363dfda0b1SToby Isaac const PetscInt firstZFace = firstYFace + numTotYFaces; 15373dfda0b1SToby Isaac const PetscInt firstXEdge = numCells + numFaces + numVertices; 15383dfda0b1SToby Isaac const PetscInt firstYEdge = firstXEdge + numTotXEdges; 15393dfda0b1SToby Isaac const PetscInt firstZEdge = firstYEdge + numTotYEdges; 15403dfda0b1SToby Isaac Vec coordinates; 15413dfda0b1SToby Isaac PetscSection coordSection; 15423dfda0b1SToby Isaac PetscScalar *coords; 15433dfda0b1SToby Isaac PetscInt coordSize; 15443dfda0b1SToby Isaac PetscInt v, vx, vy, vz; 15453dfda0b1SToby Isaac PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 15463dfda0b1SToby Isaac 15479566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices)); 154848a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 154948a46eb9SPierre Jolivet for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 155048a46eb9SPierre Jolivet for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 15519566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 15523dfda0b1SToby Isaac /* Build cells */ 15533dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 15543dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 15553dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 15563dfda0b1SToby Isaac PetscInt cell = (fz * numYEdges + fy) * numXEdges + fx; 15573dfda0b1SToby Isaac PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 15583dfda0b1SToby Isaac PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices); 15593dfda0b1SToby Isaac PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 15603dfda0b1SToby Isaac PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices); 15613dfda0b1SToby Isaac PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 15623dfda0b1SToby Isaac PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices); 15633dfda0b1SToby Isaac /* B, T, F, K, R, L */ 1564b5a892a1SMatthew G. Knepley PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */ 156542206facSLisandro Dalcin PetscInt cone[6]; 15663dfda0b1SToby Isaac 15673dfda0b1SToby Isaac /* no boundary twisting in 3D */ 15689371c9d4SSatish Balay cone[0] = faceB; 15699371c9d4SSatish Balay cone[1] = faceT; 15709371c9d4SSatish Balay cone[2] = faceF; 15719371c9d4SSatish Balay cone[3] = faceK; 15729371c9d4SSatish Balay cone[4] = faceR; 15739371c9d4SSatish Balay cone[5] = faceL; 15749566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, cell, cone)); 15759566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, cell, ornt)); 15769566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 15779566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 15789566063dSJacob Faibussowitsch if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 15793dfda0b1SToby Isaac } 15803dfda0b1SToby Isaac } 15813dfda0b1SToby Isaac } 15823dfda0b1SToby Isaac /* Build x faces */ 15833dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 15843dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 15853dfda0b1SToby Isaac for (fx = 0; fx < numXVertices; ++fx) { 15863dfda0b1SToby Isaac PetscInt face = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 15873dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 15883dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz; 15893dfda0b1SToby Isaac PetscInt edgeB = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 15903dfda0b1SToby Isaac PetscInt edgeT = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy; 1591b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 15923dfda0b1SToby Isaac PetscInt cone[4]; 15933dfda0b1SToby Isaac 15943dfda0b1SToby Isaac if (dim == 3) { 15953dfda0b1SToby Isaac /* markers */ 15963dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 15973dfda0b1SToby Isaac if (fx == numXVertices - 1) { 15989566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 15999566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerRight)); 16009371c9d4SSatish Balay } else if (fx == 0) { 16019566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 16029566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft)); 16033dfda0b1SToby Isaac } 16043dfda0b1SToby Isaac } 16053dfda0b1SToby Isaac } 16069371c9d4SSatish Balay cone[0] = edgeB; 16079371c9d4SSatish Balay cone[1] = edgeR; 16089371c9d4SSatish Balay cone[2] = edgeT; 16099371c9d4SSatish Balay cone[3] = edgeL; 16109566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 16119566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 16123dfda0b1SToby Isaac } 16133dfda0b1SToby Isaac } 16143dfda0b1SToby Isaac } 16153dfda0b1SToby Isaac /* Build y faces */ 16163dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 161742206facSLisandro Dalcin for (fx = 0; fx < numXEdges; ++fx) { 16183dfda0b1SToby Isaac for (fy = 0; fy < numYVertices; ++fy) { 16193dfda0b1SToby Isaac PetscInt face = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 16203dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 16213dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz; 16223dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 16233dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx; 1624b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16253dfda0b1SToby Isaac PetscInt cone[4]; 16263dfda0b1SToby Isaac 16273dfda0b1SToby Isaac if (dim == 3) { 16283dfda0b1SToby Isaac /* markers */ 16293dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 16303dfda0b1SToby Isaac if (fy == numYVertices - 1) { 16319566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 16329566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBack)); 16339371c9d4SSatish Balay } else if (fy == 0) { 16349566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 16359566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerFront)); 16363dfda0b1SToby Isaac } 16373dfda0b1SToby Isaac } 16383dfda0b1SToby Isaac } 16399371c9d4SSatish Balay cone[0] = edgeB; 16409371c9d4SSatish Balay cone[1] = edgeR; 16419371c9d4SSatish Balay cone[2] = edgeT; 16429371c9d4SSatish Balay cone[3] = edgeL; 16439566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 16449566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 16453dfda0b1SToby Isaac } 16463dfda0b1SToby Isaac } 16473dfda0b1SToby Isaac } 16483dfda0b1SToby Isaac /* Build z faces */ 16493dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 16503dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 16513dfda0b1SToby Isaac for (fz = 0; fz < numZVertices; fz++) { 16523dfda0b1SToby Isaac PetscInt face = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 16533dfda0b1SToby Isaac PetscInt edgeL = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 16543dfda0b1SToby Isaac PetscInt edgeR = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy; 16553dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 16563dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx; 1657b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16583dfda0b1SToby Isaac PetscInt cone[4]; 16593dfda0b1SToby Isaac 16603dfda0b1SToby Isaac if (dim == 2) { 16619371c9d4SSatish Balay if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) { 16629371c9d4SSatish Balay edgeR += numYEdges - 1 - 2 * fy; 16639371c9d4SSatish Balay ornt[1] = -1; 16649371c9d4SSatish Balay } 16659371c9d4SSatish Balay if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) { 16669371c9d4SSatish Balay edgeT += numXEdges - 1 - 2 * fx; 16679371c9d4SSatish Balay ornt[2] = 0; 16689371c9d4SSatish Balay } 16699566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 16709566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 1671d1c88043SMatthew G. Knepley } else { 16723dfda0b1SToby Isaac /* markers */ 16733dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 16743dfda0b1SToby Isaac if (fz == numZVertices - 1) { 16759566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 16769566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerTop)); 16779371c9d4SSatish Balay } else if (fz == 0) { 16789566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 16799566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom)); 16803dfda0b1SToby Isaac } 16813dfda0b1SToby Isaac } 16823dfda0b1SToby Isaac } 16839371c9d4SSatish Balay cone[0] = edgeB; 16849371c9d4SSatish Balay cone[1] = edgeR; 16859371c9d4SSatish Balay cone[2] = edgeT; 16869371c9d4SSatish Balay cone[3] = edgeL; 16879566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 16889566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 16893dfda0b1SToby Isaac } 16903dfda0b1SToby Isaac } 16913dfda0b1SToby Isaac } 16923dfda0b1SToby Isaac /* Build Z edges*/ 16933dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 16943dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 16953dfda0b1SToby Isaac for (ez = 0; ez < numZEdges; ez++) { 16963dfda0b1SToby Isaac const PetscInt edge = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez; 16973dfda0b1SToby Isaac const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx; 16983dfda0b1SToby Isaac const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx; 16993dfda0b1SToby Isaac PetscInt cone[2]; 17003dfda0b1SToby Isaac 17019371c9d4SSatish Balay cone[0] = vertexB; 17029371c9d4SSatish Balay cone[1] = vertexT; 1703c2df9bbfSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, edge, cone)); 17043dfda0b1SToby Isaac if (dim == 3) { 17053dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 17063dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17079566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1708c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1709c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1710c2df9bbfSMatthew G. Knepley } else if (vx == 0) { 17119566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1712c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1713c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 17143dfda0b1SToby Isaac } 17153dfda0b1SToby Isaac } 17163dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 17173dfda0b1SToby Isaac if (vy == numYVertices - 1) { 17189566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1719c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1720c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1721c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 17229566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1723c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1724c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 17253dfda0b1SToby Isaac } 17263dfda0b1SToby Isaac } 17273dfda0b1SToby Isaac } 17283dfda0b1SToby Isaac } 17293dfda0b1SToby Isaac } 17303dfda0b1SToby Isaac } 17313dfda0b1SToby Isaac /* Build Y edges*/ 17323dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 17333dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 17343dfda0b1SToby Isaac for (ey = 0; ey < numYEdges; ey++) { 17353dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx; 17363dfda0b1SToby Isaac const PetscInt edge = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey; 17373dfda0b1SToby Isaac const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx; 17383dfda0b1SToby Isaac const PetscInt vertexK = firstVertex + nextv; 17393dfda0b1SToby Isaac PetscInt cone[2]; 17403dfda0b1SToby Isaac 17419371c9d4SSatish Balay cone[0] = vertexF; 17429371c9d4SSatish Balay cone[1] = vertexK; 17439566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 17443dfda0b1SToby Isaac if (dim == 2) { 17453dfda0b1SToby Isaac if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 17463dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17479566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 17489566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 17499566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1750c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1751d8211ee3SMatthew G. Knepley } else if (vx == 0) { 17529566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 17539566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 17549566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1755c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 17563dfda0b1SToby Isaac } 1757d8211ee3SMatthew G. Knepley } else { 17584c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 17599566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 17609566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1761c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 17623dfda0b1SToby Isaac } 1763d8211ee3SMatthew G. Knepley } 1764d8211ee3SMatthew G. Knepley } else { 17653dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 17663dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17679566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1768c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1769c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1770d8211ee3SMatthew G. Knepley } else if (vx == 0) { 17719566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1772c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1773c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 17743dfda0b1SToby Isaac } 17753dfda0b1SToby Isaac } 17763dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 17773dfda0b1SToby Isaac if (vz == numZVertices - 1) { 17789566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1779c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1780c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1781d8211ee3SMatthew G. Knepley } else if (vz == 0) { 17829566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1783c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1784c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 17853dfda0b1SToby Isaac } 17863dfda0b1SToby Isaac } 17873dfda0b1SToby Isaac } 17883dfda0b1SToby Isaac } 17893dfda0b1SToby Isaac } 17903dfda0b1SToby Isaac } 17913dfda0b1SToby Isaac /* Build X edges*/ 17923dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 17933dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 17943dfda0b1SToby Isaac for (ex = 0; ex < numXEdges; ex++) { 17953dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices; 17963dfda0b1SToby Isaac const PetscInt edge = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex; 17973dfda0b1SToby Isaac const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex; 17983dfda0b1SToby Isaac const PetscInt vertexR = firstVertex + nextv; 17993dfda0b1SToby Isaac PetscInt cone[2]; 18003dfda0b1SToby Isaac 18019371c9d4SSatish Balay cone[0] = vertexL; 18029371c9d4SSatish Balay cone[1] = vertexR; 18039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 18043dfda0b1SToby Isaac if (dim == 2) { 18053dfda0b1SToby Isaac if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 18063dfda0b1SToby Isaac if (vy == numYVertices - 1) { 18079566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 18089566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 18099566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1810c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1811d8211ee3SMatthew G. Knepley } else if (vy == 0) { 18129566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 18139566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 18149566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1815c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 18163dfda0b1SToby Isaac } 1817d8211ee3SMatthew G. Knepley } else { 18184c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 18199566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 18209566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1821c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 18223dfda0b1SToby Isaac } 1823d8211ee3SMatthew G. Knepley } 1824d8211ee3SMatthew G. Knepley } else { 18253dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 18263dfda0b1SToby Isaac if (vy == numYVertices - 1) { 18279566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1828c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1829c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1830c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 18319566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1832c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1833c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 18343dfda0b1SToby Isaac } 18353dfda0b1SToby Isaac } 18363dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 18373dfda0b1SToby Isaac if (vz == numZVertices - 1) { 18389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1839c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1840c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1841c2df9bbfSMatthew G. Knepley } else if (vz == 0) { 18429566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1843c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1844c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 18453dfda0b1SToby Isaac } 18463dfda0b1SToby Isaac } 18473dfda0b1SToby Isaac } 18483dfda0b1SToby Isaac } 18493dfda0b1SToby Isaac } 18503dfda0b1SToby Isaac } 18519566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 18529566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 18533dfda0b1SToby Isaac /* Build coordinates */ 18549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 18559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 18569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 18579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 18583dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex + numVertices; ++v) { 18599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 18609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 18613dfda0b1SToby Isaac } 18629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 18639566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 18649566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 18659566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 18669566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 18679566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 18689566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 18699566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 18703dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; ++vz) { 18713dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; ++vy) { 18723dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; ++vx) { 18733dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 18743dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1875ad540459SPierre Jolivet if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz; 18763dfda0b1SToby Isaac } 18773dfda0b1SToby Isaac } 18783dfda0b1SToby Isaac } 18799566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 18809566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 18819566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 18823dfda0b1SToby Isaac } 18833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18843dfda0b1SToby Isaac } 18853dfda0b1SToby Isaac 1886d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1887d71ae5a4SJacob Faibussowitsch { 18889318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 18899318fe57SMatthew G. Knepley PetscInt fac[3] = {0, 0, 0}, d; 1890552f7358SJed Brown 1891552f7358SJed Brown PetscFunctionBegin; 18924f572ea9SToby Isaac PetscAssertPointer(dm, 1); 18939318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 18949566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 18959371c9d4SSatish Balay for (d = 0; d < dim; ++d) { 18969371c9d4SSatish Balay fac[d] = faces[d]; 18979371c9d4SSatish Balay bdt[d] = periodicity[d]; 18989371c9d4SSatish Balay } 18999566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2])); 19009371c9d4SSatish Balay if (periodicity[0] == DM_BOUNDARY_PERIODIC || periodicity[0] == DM_BOUNDARY_TWIST || periodicity[1] == DM_BOUNDARY_PERIODIC || periodicity[1] == DM_BOUNDARY_TWIST || (dim > 2 && (periodicity[2] == DM_BOUNDARY_PERIODIC || periodicity[2] == DM_BOUNDARY_TWIST))) { 19016858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 19026858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1903552f7358SJed Brown 19049318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19056858538eSMatthew G. Knepley if (periodicity[d] != DM_BOUNDARY_NONE) { 19069318fe57SMatthew G. Knepley L[d] = upper[d] - lower[d]; 19079318fe57SMatthew G. Knepley maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d])); 1908768d5fceSMatthew G. Knepley } 19096858538eSMatthew G. Knepley } 19104fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1911768d5fceSMatthew G. Knepley } 19129566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 19133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19149318fe57SMatthew G. Knepley } 19159318fe57SMatthew G. Knepley 19165dca41c3SJed Brown static PetscErrorCode DMPlexCreateBoxMesh_Internal(DM dm, DMPlexShape shape, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 1917d71ae5a4SJacob Faibussowitsch { 19189318fe57SMatthew G. Knepley PetscFunctionBegin; 191946139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 19205dca41c3SJed Brown if (shape == DM_SHAPE_ZBOX) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 19216725e60dSJed Brown else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 19229566063dSJacob Faibussowitsch else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 19239566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity)); 19249318fe57SMatthew G. Knepley if (!interpolate && dim > 1 && !simplex) { 1925768d5fceSMatthew G. Knepley DM udm; 1926768d5fceSMatthew G. Knepley 19279566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 19289566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, udm)); 192969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 1930768d5fceSMatthew G. Knepley } 193146139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 19323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1933c8c68bd8SToby Isaac } 1934c8c68bd8SToby Isaac 19355d83a8b1SBarry Smith /*@ 1936768d5fceSMatthew G. Knepley DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 1937768d5fceSMatthew G. Knepley 1938d083f849SBarry Smith Collective 1939768d5fceSMatthew G. Knepley 1940768d5fceSMatthew G. Knepley Input Parameters: 1941a1cb98faSBarry Smith + comm - The communicator for the `DM` object 1942768d5fceSMatthew G. Knepley . dim - The spatial dimension 1943a1cb98faSBarry Smith . simplex - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells 194420f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 194520f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 194620f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 194720f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 194842108689Sksagiyam . interpolate - Flag to create intermediate mesh pieces (edges, faces) 194942108689Sksagiyam . localizationHeight - Flag to localize edges and faces in addition to cells; only significant for periodic meshes 195042108689Sksagiyam - sparseLocalize - Flag to localize coordinates only for cells near the periodic boundary; only significant for periodic meshes 1951768d5fceSMatthew G. Knepley 1952768d5fceSMatthew G. Knepley Output Parameter: 1953a1cb98faSBarry Smith . dm - The `DM` object 1954768d5fceSMatthew G. Knepley 1955768d5fceSMatthew G. Knepley Level: beginner 1956768d5fceSMatthew G. Knepley 1957a1cb98faSBarry Smith Note: 1958a1cb98faSBarry Smith To customize this mesh using options, use 1959a1cb98faSBarry Smith .vb 1960a1cb98faSBarry Smith DMCreate(comm, &dm); 1961a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 1962a1cb98faSBarry Smith DMSetFromOptions(dm); 1963a1cb98faSBarry Smith .ve 1964a1cb98faSBarry Smith and use the options in `DMSetFromOptions()`. 1965a1cb98faSBarry Smith 1966a4e35b19SJacob Faibussowitsch Here is the numbering returned for 2 faces in each direction for tensor cells\: 1967a1cb98faSBarry Smith .vb 1968a1cb98faSBarry Smith 10---17---11---18----12 1969a1cb98faSBarry Smith | | | 1970a1cb98faSBarry Smith | | | 1971a1cb98faSBarry Smith 20 2 22 3 24 1972a1cb98faSBarry Smith | | | 1973a1cb98faSBarry Smith | | | 1974a1cb98faSBarry Smith 7---15----8---16----9 1975a1cb98faSBarry Smith | | | 1976a1cb98faSBarry Smith | | | 1977a1cb98faSBarry Smith 19 0 21 1 23 1978a1cb98faSBarry Smith | | | 1979a1cb98faSBarry Smith | | | 1980a1cb98faSBarry Smith 4---13----5---14----6 1981a1cb98faSBarry Smith .ve 1982a1cb98faSBarry Smith and for simplicial cells 1983a1cb98faSBarry Smith .vb 1984a1cb98faSBarry Smith 14----8---15----9----16 1985a1cb98faSBarry Smith |\ 5 |\ 7 | 1986a1cb98faSBarry Smith | \ | \ | 1987a1cb98faSBarry Smith 13 2 14 3 15 1988a1cb98faSBarry Smith | 4 \ | 6 \ | 1989a1cb98faSBarry Smith | \ | \ | 1990a1cb98faSBarry Smith 11----6---12----7----13 1991a1cb98faSBarry Smith |\ |\ | 1992a1cb98faSBarry Smith | \ 1 | \ 3 | 1993a1cb98faSBarry Smith 10 0 11 1 12 1994a1cb98faSBarry Smith | 0 \ | 2 \ | 1995a1cb98faSBarry Smith | \ | \ | 1996a1cb98faSBarry Smith 8----4----9----5----10 1997a1cb98faSBarry Smith .ve 1998a1cb98faSBarry Smith 19991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 2000768d5fceSMatthew G. Knepley @*/ 200142108689Sksagiyam PetscErrorCode DMPlexCreateBoxMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate, PetscInt localizationHeight, PetscBool sparseLocalize, DM *dm) 2002d71ae5a4SJacob Faibussowitsch { 20039318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 2004fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 2005fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 2006fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 2007552f7358SJed Brown 2008768d5fceSMatthew G. Knepley PetscFunctionBegin; 20099566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 20109566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 20115dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(*dm, DM_SHAPE_BOX, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 201242108689Sksagiyam if (periodicity) { 201342108689Sksagiyam DM cdm; 201442108689Sksagiyam 201542108689Sksagiyam PetscCall(DMGetCoordinateDM(*dm, &cdm)); 201642108689Sksagiyam PetscCall(DMPlexSetMaxProjectionHeight(cdm, localizationHeight)); 201742108689Sksagiyam PetscCall(DMSetSparseLocalize(*dm, sparseLocalize)); 201842108689Sksagiyam PetscCall(DMLocalizeCoordinates(*dm)); 201942108689Sksagiyam } 20203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20219318fe57SMatthew G. Knepley } 2022fdbf62faSLisandro Dalcin 2023d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 2024d71ae5a4SJacob Faibussowitsch { 20259318fe57SMatthew G. Knepley DM bdm, vol; 20269318fe57SMatthew G. Knepley PetscInt i; 20279318fe57SMatthew G. Knepley 20289318fe57SMatthew G. Knepley PetscFunctionBegin; 20291fcf445aSMatthew G. Knepley // TODO Now we can support periodicity 203008401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 20319566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 20329566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 20339566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 203446139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, bdm, 0, 0, 0)); 20359566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 20361fcf445aSMatthew G. Knepley PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, NULL, NULL, &vol)); 203746139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, bdm, 0, 0, 0)); 20389566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 203969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 20409318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 20419318fe57SMatthew G. Knepley Vec v; 20429318fe57SMatthew G. Knepley PetscScalar *x; 20439318fe57SMatthew G. Knepley PetscInt cDim, n; 20449318fe57SMatthew G. Knepley 20459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 20469566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 20479566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 20489566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 20499318fe57SMatthew G. Knepley x += cDim; 20509318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 20519566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 20529566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 20539318fe57SMatthew G. Knepley } 20543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2055552f7358SJed Brown } 2056552f7358SJed Brown 205700dabe28SStefano Zampini /*@ 205839f4f5dbSPierre Jolivet DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tessellating the (x,y) plane and extruding in the third direction using wedge cells. 205900dabe28SStefano Zampini 2060d083f849SBarry Smith Collective 206100dabe28SStefano Zampini 206200dabe28SStefano Zampini Input Parameters: 2063a1cb98faSBarry Smith + comm - The communicator for the `DM` object 206420f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1, 1, 1) 206520f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 206620f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 206720f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 2068a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 206900dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 207000dabe28SStefano Zampini 207100dabe28SStefano Zampini Output Parameter: 2072a1cb98faSBarry Smith . dm - The `DM` object 207300dabe28SStefano Zampini 207400dabe28SStefano Zampini Level: beginner 207500dabe28SStefano Zampini 20761cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 207700dabe28SStefano Zampini @*/ 2078d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 2079d71ae5a4SJacob Faibussowitsch { 20809318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 208100dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 208200dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 208300dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 208400dabe28SStefano Zampini 208500dabe28SStefano Zampini PetscFunctionBegin; 20869566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 20879566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 20889566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 2089d410b0cfSMatthew G. Knepley if (!interpolate) { 2090d410b0cfSMatthew G. Knepley DM udm; 209100dabe28SStefano Zampini 20929566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 209369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 209400dabe28SStefano Zampini } 20957ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 20963ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 209700dabe28SStefano Zampini } 209800dabe28SStefano Zampini 2099cfb853baSMatthew G. Knepley /* 2100cfb853baSMatthew G. Knepley DMPlexTensorPointLexicographic_Private - Returns all tuples of size 'len' with nonnegative integers that are all less than or equal to 'max' for that dimension. 2101cfb853baSMatthew G. Knepley 2102cfb853baSMatthew G. Knepley Input Parameters: 2103cfb853baSMatthew G. Knepley + len - The length of the tuple 2104cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max) 2105cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition 2106cfb853baSMatthew G. Knepley 2107cfb853baSMatthew G. Knepley Output Parameter: 210820f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max` 2109cfb853baSMatthew G. Knepley 2110cfb853baSMatthew G. Knepley Level: developer 2111cfb853baSMatthew G. Knepley 211220f4b53cSBarry Smith Note: 211320f4b53cSBarry Smith Ordering is lexicographic with lowest index as least significant in ordering. 211420f4b53cSBarry Smith e.g. for len == 2 and max == 2, this will return, in order, {0,0}, {1,0}, {2,0}, {0,1}, {1,1}, {2,1}, {0,2}, {1,2}, {2,2}. 211520f4b53cSBarry Smith 2116cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal() 2117cfb853baSMatthew G. Knepley */ 2118cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[]) 2119cfb853baSMatthew G. Knepley { 2120cfb853baSMatthew G. Knepley PetscInt i; 2121cfb853baSMatthew G. Knepley 2122cfb853baSMatthew G. Knepley PetscFunctionBegin; 2123cfb853baSMatthew G. Knepley for (i = 0; i < len; ++i) { 2124cfb853baSMatthew G. Knepley if (tup[i] < max[i] - 1) { 2125cfb853baSMatthew G. Knepley break; 2126cfb853baSMatthew G. Knepley } else { 2127cfb853baSMatthew G. Knepley tup[i] = 0; 2128cfb853baSMatthew G. Knepley } 2129cfb853baSMatthew G. Knepley } 2130cfb853baSMatthew G. Knepley if (i == len) tup[i - 1] = max[i - 1]; 2131cfb853baSMatthew G. Knepley else ++tup[i]; 21323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2133cfb853baSMatthew G. Knepley } 2134cfb853baSMatthew G. Knepley 2135cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[]) 2136cfb853baSMatthew G. Knepley { 21378d2ec52aSSatish Balay PetscInt idx = tup[len - 1]; 2138cfb853baSMatthew G. Knepley 21398d2ec52aSSatish Balay for (PetscInt i = len - 2; i >= 0; --i) { 2140cfb853baSMatthew G. Knepley idx *= max[i]; 2141cfb853baSMatthew G. Knepley idx += tup[i]; 2142cfb853baSMatthew G. Knepley } 2143cfb853baSMatthew G. Knepley return idx; 2144cfb853baSMatthew G. Knepley } 2145cfb853baSMatthew G. Knepley 21468d2ec52aSSatish Balay static void IndexToTuple_Private(PetscInt len, const PetscInt max[], PetscInt idx, PetscInt tup[]) 2147cfb853baSMatthew G. Knepley { 21488d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21498d2ec52aSSatish Balay tup[i] = idx % max[i]; 21508d2ec52aSSatish Balay idx = (idx - tup[i]) / max[i]; 21518d2ec52aSSatish Balay } 21528d2ec52aSSatish Balay } 21538d2ec52aSSatish Balay 21548d2ec52aSSatish Balay static void TupleToRanks_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt tup[], PetscInt ranks[]) 21558d2ec52aSSatish Balay { 21568d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21578d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 21588d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 21598d2ec52aSSatish Balay const PetscInt idx = (tup[i] < 0 ? max[i] + tup[i] : tup[i]) % max[i]; 21608d2ec52aSSatish Balay 21618d2ec52aSSatish Balay if (idx < rem * (div + 1)) ranks[i] = idx / (div + 1); 21628d2ec52aSSatish Balay else ranks[i] = rem + (idx - rem * (div + 1)) / div; 21638d2ec52aSSatish Balay } 21648d2ec52aSSatish Balay } 21658d2ec52aSSatish Balay 21668d2ec52aSSatish Balay static void RanksToSizes_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt ranks[], PetscInt sizes[]) 21678d2ec52aSSatish Balay { 21688d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21698d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 21708d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 21718d2ec52aSSatish Balay 21728d2ec52aSSatish Balay sizes[i] = ranks[i] < rem ? div + 1 : div; 21738d2ec52aSSatish Balay } 21748d2ec52aSSatish Balay } 21758d2ec52aSSatish Balay 21768d2ec52aSSatish Balay /* 21778d2ec52aSSatish Balay In serial, the mesh is completely periodic. In parallel, we will include a layer of ghost vertices around the patch, so our edges will not wrap around in parallel. This will instead be handled by the SF. 21788d2ec52aSSatish Balay 21798d2ec52aSSatish Balay The cone for all edges will always be complete. Even in the presence of boundaries, we will keep all support sizes constant. When an edge would not exist in the support, we will create one to wrap back periodically. This allows for uniform stencils, and that edge will not be used for computation. 21808d2ec52aSSatish Balay 21818d2ec52aSSatish Balay All point which do not attain the vertex lower or upper bound in any dimension are owned, the rest are leaves owned by another process and present in the SF. 2182dfe9cfe5SMatthew Knepley 2183dfe9cfe5SMatthew Knepley Parallel Layout: 2184dfe9cfe5SMatthew Knepley 2185dfe9cfe5SMatthew Knepley We create a cubic process grid of dimension P^{1/d} on each side. The IndexToTuple_Private() function maps the global rank to the local rank in each dimension. We divide edges using the PETSc distribution rule in each dimension, and then add overlap. TupleToRanks_Private() returns the local rank in ech dimension for a tuple. RanksToSizes_Private() gives the size in each dimension for the domain with those local ranks. 21868d2ec52aSSatish Balay */ 21878d2ec52aSSatish Balay static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], PetscInt overlap, const DMBoundaryType bd[]) 21888d2ec52aSSatish Balay { 21898d2ec52aSSatish Balay const PetscInt debug = ((DM_Plex *)dm->data)->printAdj; 21908d2ec52aSSatish Balay PetscSF sf; 2191cfb853baSMatthew G. Knepley Vec coordinates; 2192cfb853baSMatthew G. Knepley PetscSection coordSection; 2193cfb853baSMatthew G. Knepley DMLabel cutLabel = NULL; 2194cfb853baSMatthew G. Knepley PetscBool cutMarker = PETSC_FALSE; 2195cfb853baSMatthew G. Knepley PetscBool periodic = PETSC_FALSE; 21968d2ec52aSSatish Balay PetscInt numCells = 1; 21978d2ec52aSSatish Balay PetscInt numVertices = 1; 21988d2ec52aSSatish Balay PetscSFNode *remotes; 2199cfb853baSMatthew G. Knepley PetscScalar *coords; 22008d2ec52aSSatish Balay PetscInt *procs; // The number of processes along each dimension 22018d2ec52aSSatish Balay PetscInt *lrank; // Rank in each dimension, lrank[d] \in [0, procs[d]) 22028d2ec52aSSatish Balay PetscInt *ledges; // The number of edges along each dimension for this process 22038d2ec52aSSatish Balay PetscInt *vstart; // The first vertex along each dimension on this processes 22048d2ec52aSSatish Balay PetscInt *vertices; // The number of vertices along each dimension on this process 22058d2ec52aSSatish Balay PetscInt *rvert; // The global (not local) vertex number along each dimension 22068d2ec52aSSatish Balay PetscInt *rrank; // The rank along each dimension for the process owning rvert[] 22078d2ec52aSSatish Balay PetscInt *rvertices; // The number of vertices along each dimension for the process rrank[] 22088d2ec52aSSatish Balay PetscInt *vert, *vtmp, *supp, cone[2], *leaves; 22098d2ec52aSSatish Balay PetscInt cell = 0, coordSize, Nl = 0, Nl2 = 0; 22108d2ec52aSSatish Balay PetscMPIInt rank, size; 22118d2ec52aSSatish Balay MPI_Comm comm; 2212cfb853baSMatthew G. Knepley 2213cfb853baSMatthew G. Knepley PetscFunctionBegin; 22148d2ec52aSSatish Balay PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 22158d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_rank(comm, &rank)); 22168d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_size(comm, &size)); 2217cfb853baSMatthew G. Knepley PetscCall(DMSetDimension(dm, dim)); 22188d2ec52aSSatish Balay PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 22198d2ec52aSSatish Balay PetscCall(PetscCalloc4(dim, &procs, dim, &lrank, dim, &rrank, 2 * dim, &supp)); 22208d2ec52aSSatish Balay PetscCall(PetscCalloc7(dim, &ledges, dim, &vertices, dim, &rvertices, dim, &vert, dim, &rvert, dim, &vstart, dim, &vtmp)); 2221cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 2222cfb853baSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 22238d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE; 2224cfb853baSMatthew G. Knepley if (periodic && cutMarker) { 2225cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "periodic_cut")); 2226cfb853baSMatthew G. Knepley PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 2227cfb853baSMatthew G. Knepley } 22288d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, comm, PETSC_ERR_SUP, "Hypercubic mesh must be periodic now"); 22298d2ec52aSSatish Balay overlap = overlap == PETSC_DETERMINE ? 1 : overlap; 22308d2ec52aSSatish Balay PetscCheck(overlap >= 1, comm, PETSC_ERR_SUP, "Overlap %" PetscInt_FMT " must be greater than 0", overlap); 22318d2ec52aSSatish Balay if (size > 1) { 22328d2ec52aSSatish Balay PetscInt Npr = 1; 22338d2ec52aSSatish Balay 22348d2ec52aSSatish Balay // Make process grid 22358d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "Process grid:")); 22368d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22378d2ec52aSSatish Balay procs[d] = PetscRintReal(PetscPowReal(size, 1. / dim)); 22388d2ec52aSSatish Balay Npr *= procs[d]; 22398d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, " %" PetscInt_FMT, procs[d])); 22408d2ec52aSSatish Balay } 22418d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "\n")); 22428d2ec52aSSatish Balay PetscCheck(Npr == size, comm, PETSC_ERR_PLIB, "Process grid size %" PetscInt_FMT " != %d comm size", Npr, size); 22438d2ec52aSSatish Balay IndexToTuple_Private(dim, procs, rank, lrank); 22448d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22458d2ec52aSSatish Balay ledges[d] = edges[d] / procs[d] + (edges[d] % procs[d] > lrank[d] ? 1 : 0); 22468d2ec52aSSatish Balay vstart[d] = 0; 22478d2ec52aSSatish Balay for (PetscInt r = 0; r < lrank[d]; ++r) vstart[d] += edges[d] / procs[d] + (edges[d] % procs[d] > r ? 1 : 0); 22488d2ec52aSSatish Balay vstart[d] -= overlap; // For halo 22498d2ec52aSSatish Balay } 22508d2ec52aSSatish Balay } else { 22518d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22528d2ec52aSSatish Balay procs[d] = 1; 22538d2ec52aSSatish Balay ledges[d] = edges[d]; 22548d2ec52aSSatish Balay } 22558d2ec52aSSatish Balay } 22568d2ec52aSSatish Balay // Calculate local patch size 22578d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22588d2ec52aSSatish Balay vertices[d] = ledges[d] + (procs[d] > 1 ? 2 * overlap : 0); 2259cfb853baSMatthew G. Knepley numVertices *= vertices[d]; 2260cfb853baSMatthew G. Knepley } 2261cfb853baSMatthew G. Knepley numCells = numVertices * dim; 2262cfb853baSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 22638d2ec52aSSatish Balay for (PetscInt c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2)); 22648d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim)); 2265cfb853baSMatthew G. Knepley PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */ 2266cfb853baSMatthew G. Knepley /* Build cell cones and vertex supports */ 2267cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "celltype")); 22688d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Topology for rank %d:\n", rank)); 2269cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2270cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells; 2271cfb853baSMatthew G. Knepley PetscInt s = 0; 22728d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2273cfb853baSMatthew G. Knepley 22748d2ec52aSSatish Balay if (debug) { 22758d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 22768d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d])); 22778d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 22788d2ec52aSSatish Balay } 2279cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT)); 22808d2ec52aSSatish Balay // Define edge cones 22818d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22828d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2283cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + 1) % vertices[d]; 2284cfb853baSMatthew G. Knepley cone[0] = vertex; 2285cfb853baSMatthew G. Knepley cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells; 22868d2ec52aSSatish Balay if (debug) { 22878d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ":", cone[1])); 22888d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vtmp[e])); 22898d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 22908d2ec52aSSatish Balay } 2291cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, cell, cone)); 2292cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT)); 22938d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1])); 2294cfb853baSMatthew G. Knepley ++cell; 22958d2ec52aSSatish Balay // Shared vertices are any in the first or last overlap layers 22968d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 2297cfb853baSMatthew G. Knepley } 22988d2ec52aSSatish Balay if (size > 1 && leaf) ++Nl; 22998d2ec52aSSatish Balay // Define vertex supports 23008d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23018d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2302cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + vertices[d] - 1) % vertices[d]; 2303cfb853baSMatthew G. Knepley supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d; 2304cfb853baSMatthew G. Knepley supp[s++] = (vertex - numCells) * dim + d; 2305cfb853baSMatthew G. Knepley PetscCall(DMPlexSetSupport(dm, vertex, supp)); 2306cfb853baSMatthew G. Knepley } 2307cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2308cfb853baSMatthew G. Knepley } 23098d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2310cfb853baSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 23118d2ec52aSSatish Balay // Allocate for SF 23128d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &leaves)); 23138d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &remotes)); 23148d2ec52aSSatish Balay // Build coordinates 2315cfb853baSMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 2316cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(coordSection, 1)); 2317cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 2318cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 23198d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) { 2320cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetDof(coordSection, v, dim)); 2321cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 2322cfb853baSMatthew G. Knepley } 2323cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetUp(coordSection)); 2324cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 23258d2ec52aSSatish Balay PetscCall(VecCreate(comm, &coordinates)); 2326cfb853baSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 2327cfb853baSMatthew G. Knepley PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 2328cfb853baSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinates, dim)); 2329cfb853baSMatthew G. Knepley PetscCall(VecSetType(coordinates, VECSTANDARD)); 2330cfb853baSMatthew G. Knepley PetscCall(VecGetArray(coordinates, &coords)); 23318d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Geometry for rank %d:\n", rank)); 23328d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) vert[d] = 0; 2333cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2334cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert); 23358d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2336cfb853baSMatthew G. Knepley 23378d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23388d2ec52aSSatish Balay coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / edges[d]) * (vert[d] + vstart[d]); 23398d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 23408d2ec52aSSatish Balay } 23418d2ec52aSSatish Balay if (size > 1 && leaf) { 23428d2ec52aSSatish Balay PetscInt rnumCells = 1; 23438d2ec52aSSatish Balay 23448d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) rvert[d] = vert[d] + vstart[d]; 23458d2ec52aSSatish Balay TupleToRanks_Private(dim, edges, procs, rvert, rrank); 23468d2ec52aSSatish Balay leaves[Nl2] = vertex + numCells; 23478d2ec52aSSatish Balay remotes[Nl2].rank = TupleToIndex_Private(dim, procs, rrank); 23488d2ec52aSSatish Balay RanksToSizes_Private(dim, edges, procs, rrank, rvertices); 23498d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23508d2ec52aSSatish Balay rvertices[d] += 2 * overlap; // Add halo 23518d2ec52aSSatish Balay rnumCells *= rvertices[d]; 23528d2ec52aSSatish Balay } 23538d2ec52aSSatish Balay rnumCells *= dim; 23548d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23558d2ec52aSSatish Balay const PetscInt diff = rrank[d] - lrank[d]; 23568d2ec52aSSatish Balay 23578d2ec52aSSatish Balay if (!diff) rvert[d] = vert[d]; // Vertex is local 23588d2ec52aSSatish Balay else if (rvert[d] < 0) rvert[d] = rvertices[d] - 1 + rvert[d]; // Wrap around at the bottom 23598d2ec52aSSatish Balay else if (rvert[d] >= edges[d]) rvert[d] = rvert[d] - edges[d] + 1; // Wrap around at the top 23608d2ec52aSSatish Balay else if (diff == -1) rvert[d] = rvertices[d] - 1 + (vert[d] - overlap); 23618d2ec52aSSatish Balay else if (diff == 1) rvert[d] = (vertices[d] - vert[d] - 1) + overlap; 23628d2ec52aSSatish Balay else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Process distance %" PetscInt_FMT " in direction %" PetscInt_FMT " should not be possible", diff, d); 23638d2ec52aSSatish Balay } 23648d2ec52aSSatish Balay remotes[Nl2].index = TupleToIndex_Private(dim, rvertices, rvert) + rnumCells; 23658d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Shared Vertex %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", leaves[Nl2], remotes[Nl2].rank, remotes[Nl2].index)); 23668d2ec52aSSatish Balay ++Nl2; 23678d2ec52aSSatish Balay } 23688d2ec52aSSatish Balay if (debug) { 23698d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 23708d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d] + vstart[d])); 23718d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %g", (double)PetscRealPart(coords[vertex * dim + d]))); 23728d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 23738d2ec52aSSatish Balay } 2374cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2375cfb853baSMatthew G. Knepley } 23768d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2377cfb853baSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &coords)); 2378cfb853baSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 2379cfb853baSMatthew G. Knepley PetscCall(VecDestroy(&coordinates)); 23808d2ec52aSSatish Balay // Build SF 23818d2ec52aSSatish Balay PetscCheck(Nl == Nl2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Initial number of leaves %" PetscInt_FMT " != %" PetscInt_FMT " final number", Nl, Nl2); 23828d2ec52aSSatish Balay PetscCall(DMGetPointSF(dm, &sf)); 23838d2ec52aSSatish Balay PetscCall(PetscSFSetGraph(sf, numCells + numVertices, Nl, leaves, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 23848d2ec52aSSatish Balay if (debug) PetscCall(PetscSFView(sf, PETSC_VIEWER_STDOUT_WORLD)); 2385cfb853baSMatthew G. Knepley //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper)); 2386cfb853baSMatthew G. Knepley // Attach the extent 2387cfb853baSMatthew G. Knepley { 2388cfb853baSMatthew G. Knepley PetscContainer c; 23898d2ec52aSSatish Balay PetscInt *extent, *lextent; 2390cfb853baSMatthew G. Knepley 2391cfb853baSMatthew G. Knepley PetscCall(PetscMalloc1(dim, &extent)); 23928d2ec52aSSatish Balay PetscCall(PetscMalloc1(dim, &lextent)); 23938d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23948d2ec52aSSatish Balay extent[d] = edges[d]; 23958d2ec52aSSatish Balay lextent[d] = ledges[d]; 23968d2ec52aSSatish Balay } 2397cfb853baSMatthew G. Knepley PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 239849abdd8aSBarry Smith PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 2399cfb853baSMatthew G. Knepley PetscCall(PetscContainerSetPointer(c, extent)); 2400cfb853baSMatthew G. Knepley PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c)); 2401cfb853baSMatthew G. Knepley PetscCall(PetscContainerDestroy(&c)); 24028d2ec52aSSatish Balay PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 24038d2ec52aSSatish Balay PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 24048d2ec52aSSatish Balay PetscCall(PetscContainerSetPointer(c, lextent)); 24058d2ec52aSSatish Balay PetscCall(PetscObjectCompose((PetscObject)dm, "_lextent", (PetscObject)c)); 24068d2ec52aSSatish Balay PetscCall(PetscContainerDestroy(&c)); 2407cfb853baSMatthew G. Knepley } 24088d2ec52aSSatish Balay PetscCall(PetscFree4(procs, lrank, rrank, supp)); 24098d2ec52aSSatish Balay PetscCall(PetscFree7(ledges, vertices, rvertices, vert, rvert, vstart, vtmp)); 24103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2411cfb853baSMatthew G. Knepley } 2412cfb853baSMatthew G. Knepley 2413cfb853baSMatthew G. Knepley /*@C 2414aaa8cc7dSPierre Jolivet DMPlexCreateHypercubicMesh - Creates a periodic mesh on the tensor product of unit intervals using only vertices and edges. 2415cfb853baSMatthew G. Knepley 2416cfb853baSMatthew G. Knepley Collective 2417cfb853baSMatthew G. Knepley 2418cfb853baSMatthew G. Knepley Input Parameters: 24198d2ec52aSSatish Balay + comm - The communicator for the `DM` object 2420cfb853baSMatthew G. Knepley . dim - The spatial dimension 242120f4b53cSBarry Smith . edges - Number of edges per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 242220f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 24238d2ec52aSSatish Balay . upper - The upper right corner, or `NULL` for (1, 1, 1) 24248d2ec52aSSatish Balay - overlap - The number of vertices in each direction to include in the overlap (default is 1) 2425cfb853baSMatthew G. Knepley 2426cfb853baSMatthew G. Knepley Output Parameter: 2427cfb853baSMatthew G. Knepley . dm - The DM object 2428cfb853baSMatthew G. Knepley 242920f4b53cSBarry Smith Level: beginner 243020f4b53cSBarry Smith 243120f4b53cSBarry Smith Note: 243220f4b53cSBarry Smith If you want to customize this mesh using options, you just need to 243320f4b53cSBarry Smith .vb 243420f4b53cSBarry Smith DMCreate(comm, &dm); 243520f4b53cSBarry Smith DMSetType(dm, DMPLEX); 243620f4b53cSBarry Smith DMSetFromOptions(dm); 243720f4b53cSBarry Smith .ve 243820f4b53cSBarry Smith and use the options on the `DMSetFromOptions()` page. 2439cfb853baSMatthew G. Knepley 2440cfb853baSMatthew G. Knepley The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively, 244120f4b53cSBarry Smith .vb 244220f4b53cSBarry Smith 18--0-19--2-20--4-18 244320f4b53cSBarry Smith | | | | 244420f4b53cSBarry Smith 13 15 17 13 244520f4b53cSBarry Smith | | | | 244620f4b53cSBarry Smith 24-12-25-14-26-16-24 244720f4b53cSBarry Smith | | | | 244820f4b53cSBarry Smith 7 9 11 7 244920f4b53cSBarry Smith | | | | 245020f4b53cSBarry Smith 21--6-22--8-23-10-21 245120f4b53cSBarry Smith | | | | 245220f4b53cSBarry Smith 1 3 5 1 245320f4b53cSBarry Smith | | | | 245420f4b53cSBarry Smith 18--0-19--2-20--4-18 245520f4b53cSBarry Smith .ve 2456cfb853baSMatthew G. Knepley 245776fbde31SPierre Jolivet .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 2458cfb853baSMatthew G. Knepley @*/ 24598d2ec52aSSatish Balay PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], PetscInt overlap, DM *dm) 2460cfb853baSMatthew G. Knepley { 2461cfb853baSMatthew G. Knepley PetscInt *edg; 2462cfb853baSMatthew G. Knepley PetscReal *low, *upp; 2463cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 2464cfb853baSMatthew G. Knepley PetscInt d; 2465cfb853baSMatthew G. Knepley 2466cfb853baSMatthew G. Knepley PetscFunctionBegin; 2467cfb853baSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 2468cfb853baSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 2469cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt)); 2470cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 2471cfb853baSMatthew G. Knepley edg[d] = edges ? edges[d] : 1; 2472cfb853baSMatthew G. Knepley low[d] = lower ? lower[d] : 0.; 2473cfb853baSMatthew G. Knepley upp[d] = upper ? upper[d] : 1.; 2474cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 2475cfb853baSMatthew G. Knepley } 24768d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, overlap, bdt)); 2477cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edg, low, upp, bdt)); 24783ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2479cfb853baSMatthew G. Knepley } 2480cfb853baSMatthew G. Knepley 2481cc4c1da9SBarry Smith /*@ 2482a1cb98faSBarry Smith DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database. 2483a9074c1eSMatthew G. Knepley 248420f4b53cSBarry Smith Logically Collective 2485a9074c1eSMatthew G. Knepley 2486a9074c1eSMatthew G. Knepley Input Parameters: 248720f4b53cSBarry Smith + dm - the `DM` context 2488a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 2489a9074c1eSMatthew G. Knepley 2490a1cb98faSBarry Smith Level: advanced 2491a1cb98faSBarry Smith 2492a1cb98faSBarry Smith Note: 2493a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 2494a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 2495a9074c1eSMatthew G. Knepley 24961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()` 2497a9074c1eSMatthew G. Knepley @*/ 2498d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 2499d71ae5a4SJacob Faibussowitsch { 2500a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2501a9074c1eSMatthew G. Knepley 2502a9074c1eSMatthew G. Knepley PetscFunctionBegin; 2503a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25049566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 25059566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 25063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2507a9074c1eSMatthew G. Knepley } 2508a9074c1eSMatthew G. Knepley 25099318fe57SMatthew G. Knepley /* Remap geometry to cylinder 251061a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 251161a622f3SMatthew G. Knepley 25129318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 25139318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 25149318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 25150510c589SMatthew G. Knepley 25169318fe57SMatthew G. Knepley phi = arctan(y/x) 25179318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 25189318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 25190510c589SMatthew G. Knepley 25209318fe57SMatthew G. Knepley so we remap them using 25210510c589SMatthew G. Knepley 25229318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 25239318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 25240510c589SMatthew G. Knepley 25259318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 25269318fe57SMatthew G. Knepley */ 2527d71ae5a4SJacob Faibussowitsch static void snapToCylinder(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 2528d71ae5a4SJacob Faibussowitsch { 25299318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 25309318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 253122cc497dSMatthew G. Knepley 25329318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 25339318fe57SMatthew G. Knepley f0[0] = u[0]; 25349318fe57SMatthew G. Knepley f0[1] = u[1]; 25359318fe57SMatthew G. Knepley } else { 25369318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 25370510c589SMatthew G. Knepley 25389318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 25399318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 25409318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 25419318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 25429318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 25439318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 25449318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 25459318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 25469318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 25479318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 25489318fe57SMatthew G. Knepley } else { 25499318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 25509318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 25519318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 25529318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 25539318fe57SMatthew G. Knepley } 25549318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 25559318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 25569318fe57SMatthew G. Knepley } 25579318fe57SMatthew G. Knepley f0[2] = u[2]; 25589318fe57SMatthew G. Knepley } 25590510c589SMatthew G. Knepley 256049704ca5SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ, PetscInt Nr) 2561d71ae5a4SJacob Faibussowitsch { 25620510c589SMatthew G. Knepley const PetscInt dim = 3; 25639318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 2564d8c47e87SMatthew G. Knepley PetscMPIInt rank; 25650510c589SMatthew G. Knepley 25660510c589SMatthew G. Knepley PetscFunctionBegin; 256746139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 25689566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 25699566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 25700510c589SMatthew G. Knepley /* Create topology */ 25710510c589SMatthew G. Knepley { 25720510c589SMatthew G. Knepley PetscInt cone[8], c; 25730510c589SMatthew G. Knepley 2574dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 2575dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 2576006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 2577ae8bcbbbSMatthew G. Knepley numCells *= 3; 2578dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 2579006a8963SMatthew G. Knepley } 25809566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 25819566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 25829566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 2583dd400576SPatrick Sanan if (rank == 0) { 2584006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 25859371c9d4SSatish Balay cone[0] = 15; 25869371c9d4SSatish Balay cone[1] = 18; 25879371c9d4SSatish Balay cone[2] = 17; 25889371c9d4SSatish Balay cone[3] = 16; 25899371c9d4SSatish Balay cone[4] = 31; 25909371c9d4SSatish Balay cone[5] = 32; 25919371c9d4SSatish Balay cone[6] = 33; 25929371c9d4SSatish Balay cone[7] = 34; 25939566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 25949371c9d4SSatish Balay cone[0] = 16; 25959371c9d4SSatish Balay cone[1] = 17; 25969371c9d4SSatish Balay cone[2] = 24; 25979371c9d4SSatish Balay cone[3] = 23; 25989371c9d4SSatish Balay cone[4] = 32; 25999371c9d4SSatish Balay cone[5] = 36; 26009371c9d4SSatish Balay cone[6] = 37; 26019371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 26029566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 26039371c9d4SSatish Balay cone[0] = 18; 26049371c9d4SSatish Balay cone[1] = 27; 26059371c9d4SSatish Balay cone[2] = 24; 26069371c9d4SSatish Balay cone[3] = 17; 26079371c9d4SSatish Balay cone[4] = 34; 26089371c9d4SSatish Balay cone[5] = 33; 26099371c9d4SSatish Balay cone[6] = 37; 26109371c9d4SSatish Balay cone[7] = 38; 26119566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 26129371c9d4SSatish Balay cone[0] = 29; 26139371c9d4SSatish Balay cone[1] = 27; 26149371c9d4SSatish Balay cone[2] = 18; 26159371c9d4SSatish Balay cone[3] = 15; 26169371c9d4SSatish Balay cone[4] = 35; 26179371c9d4SSatish Balay cone[5] = 31; 26189371c9d4SSatish Balay cone[6] = 34; 26199371c9d4SSatish Balay cone[7] = 38; 26209566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 26219371c9d4SSatish Balay cone[0] = 29; 26229371c9d4SSatish Balay cone[1] = 15; 26239371c9d4SSatish Balay cone[2] = 16; 26249371c9d4SSatish Balay cone[3] = 23; 26259371c9d4SSatish Balay cone[4] = 35; 26269371c9d4SSatish Balay cone[5] = 36; 26279371c9d4SSatish Balay cone[6] = 32; 26289371c9d4SSatish Balay cone[7] = 31; 26299566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2630006a8963SMatthew G. Knepley 26319371c9d4SSatish Balay cone[0] = 31; 26329371c9d4SSatish Balay cone[1] = 34; 26339371c9d4SSatish Balay cone[2] = 33; 26349371c9d4SSatish Balay cone[3] = 32; 26359371c9d4SSatish Balay cone[4] = 19; 26369371c9d4SSatish Balay cone[5] = 22; 26379371c9d4SSatish Balay cone[6] = 21; 26389371c9d4SSatish Balay cone[7] = 20; 26399566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 26409371c9d4SSatish Balay cone[0] = 32; 26419371c9d4SSatish Balay cone[1] = 33; 26429371c9d4SSatish Balay cone[2] = 37; 26439371c9d4SSatish Balay cone[3] = 36; 26449371c9d4SSatish Balay cone[4] = 22; 26459371c9d4SSatish Balay cone[5] = 25; 26469371c9d4SSatish Balay cone[6] = 26; 26479371c9d4SSatish Balay cone[7] = 21; 26489566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 26499371c9d4SSatish Balay cone[0] = 34; 26509371c9d4SSatish Balay cone[1] = 38; 26519371c9d4SSatish Balay cone[2] = 37; 26529371c9d4SSatish Balay cone[3] = 33; 26539371c9d4SSatish Balay cone[4] = 20; 26549371c9d4SSatish Balay cone[5] = 21; 26559371c9d4SSatish Balay cone[6] = 26; 26569371c9d4SSatish Balay cone[7] = 28; 26579566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 26589371c9d4SSatish Balay cone[0] = 35; 26599371c9d4SSatish Balay cone[1] = 38; 26609371c9d4SSatish Balay cone[2] = 34; 26619371c9d4SSatish Balay cone[3] = 31; 26629371c9d4SSatish Balay cone[4] = 30; 26639371c9d4SSatish Balay cone[5] = 19; 26649371c9d4SSatish Balay cone[6] = 20; 26659371c9d4SSatish Balay cone[7] = 28; 26669566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 26679371c9d4SSatish Balay cone[0] = 35; 26689371c9d4SSatish Balay cone[1] = 31; 26699371c9d4SSatish Balay cone[2] = 32; 26709371c9d4SSatish Balay cone[3] = 36; 26719371c9d4SSatish Balay cone[4] = 30; 26729371c9d4SSatish Balay cone[5] = 25; 26739371c9d4SSatish Balay cone[6] = 22; 26749371c9d4SSatish Balay cone[7] = 19; 26759566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 2676ae8bcbbbSMatthew G. Knepley 26779371c9d4SSatish Balay cone[0] = 19; 26789371c9d4SSatish Balay cone[1] = 20; 26799371c9d4SSatish Balay cone[2] = 21; 26809371c9d4SSatish Balay cone[3] = 22; 26819371c9d4SSatish Balay cone[4] = 15; 26829371c9d4SSatish Balay cone[5] = 16; 26839371c9d4SSatish Balay cone[6] = 17; 26849371c9d4SSatish Balay cone[7] = 18; 26859566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 26869371c9d4SSatish Balay cone[0] = 22; 26879371c9d4SSatish Balay cone[1] = 21; 26889371c9d4SSatish Balay cone[2] = 26; 26899371c9d4SSatish Balay cone[3] = 25; 26909371c9d4SSatish Balay cone[4] = 16; 26919371c9d4SSatish Balay cone[5] = 23; 26929371c9d4SSatish Balay cone[6] = 24; 26939371c9d4SSatish Balay cone[7] = 17; 26949566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 26959371c9d4SSatish Balay cone[0] = 20; 26969371c9d4SSatish Balay cone[1] = 28; 26979371c9d4SSatish Balay cone[2] = 26; 26989371c9d4SSatish Balay cone[3] = 21; 26999371c9d4SSatish Balay cone[4] = 18; 27009371c9d4SSatish Balay cone[5] = 17; 27019371c9d4SSatish Balay cone[6] = 24; 27029371c9d4SSatish Balay cone[7] = 27; 27039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 27049371c9d4SSatish Balay cone[0] = 30; 27059371c9d4SSatish Balay cone[1] = 28; 27069371c9d4SSatish Balay cone[2] = 20; 27079371c9d4SSatish Balay cone[3] = 19; 27089371c9d4SSatish Balay cone[4] = 29; 27099371c9d4SSatish Balay cone[5] = 15; 27109371c9d4SSatish Balay cone[6] = 18; 27119371c9d4SSatish Balay cone[7] = 27; 27129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 27139371c9d4SSatish Balay cone[0] = 30; 27149371c9d4SSatish Balay cone[1] = 19; 27159371c9d4SSatish Balay cone[2] = 22; 27169371c9d4SSatish Balay cone[3] = 25; 27179371c9d4SSatish Balay cone[4] = 29; 27189371c9d4SSatish Balay cone[5] = 23; 27199371c9d4SSatish Balay cone[6] = 16; 27209371c9d4SSatish Balay cone[7] = 15; 27219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 2722006a8963SMatthew G. Knepley } else { 27239371c9d4SSatish Balay cone[0] = 5; 27249371c9d4SSatish Balay cone[1] = 8; 27259371c9d4SSatish Balay cone[2] = 7; 27269371c9d4SSatish Balay cone[3] = 6; 27279371c9d4SSatish Balay cone[4] = 9; 27289371c9d4SSatish Balay cone[5] = 12; 27299371c9d4SSatish Balay cone[6] = 11; 27309371c9d4SSatish Balay cone[7] = 10; 27319566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 27329371c9d4SSatish Balay cone[0] = 6; 27339371c9d4SSatish Balay cone[1] = 7; 27349371c9d4SSatish Balay cone[2] = 14; 27359371c9d4SSatish Balay cone[3] = 13; 27369371c9d4SSatish Balay cone[4] = 12; 27379371c9d4SSatish Balay cone[5] = 15; 27389371c9d4SSatish Balay cone[6] = 16; 27399371c9d4SSatish Balay cone[7] = 11; 27409566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 27419371c9d4SSatish Balay cone[0] = 8; 27429371c9d4SSatish Balay cone[1] = 17; 27439371c9d4SSatish Balay cone[2] = 14; 27449371c9d4SSatish Balay cone[3] = 7; 27459371c9d4SSatish Balay cone[4] = 10; 27469371c9d4SSatish Balay cone[5] = 11; 27479371c9d4SSatish Balay cone[6] = 16; 27489371c9d4SSatish Balay cone[7] = 18; 27499566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 27509371c9d4SSatish Balay cone[0] = 19; 27519371c9d4SSatish Balay cone[1] = 17; 27529371c9d4SSatish Balay cone[2] = 8; 27539371c9d4SSatish Balay cone[3] = 5; 27549371c9d4SSatish Balay cone[4] = 20; 27559371c9d4SSatish Balay cone[5] = 9; 27569371c9d4SSatish Balay cone[6] = 10; 27579371c9d4SSatish Balay cone[7] = 18; 27589566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 27599371c9d4SSatish Balay cone[0] = 19; 27609371c9d4SSatish Balay cone[1] = 5; 27619371c9d4SSatish Balay cone[2] = 6; 27629371c9d4SSatish Balay cone[3] = 13; 27639371c9d4SSatish Balay cone[4] = 20; 27649371c9d4SSatish Balay cone[5] = 15; 27659371c9d4SSatish Balay cone[6] = 12; 27669371c9d4SSatish Balay cone[7] = 9; 27679566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2768006a8963SMatthew G. Knepley } 2769d8c47e87SMatthew G. Knepley } 27709566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 27719566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 27720510c589SMatthew G. Knepley } 2773dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 27740510c589SMatthew G. Knepley { 27750510c589SMatthew G. Knepley Vec coordinates; 27760510c589SMatthew G. Knepley PetscSection coordSection; 27770510c589SMatthew G. Knepley PetscScalar *coords; 27780510c589SMatthew G. Knepley PetscInt coordSize, v; 27790510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 27800510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 27810510c589SMatthew G. Knepley 27820510c589SMatthew G. Knepley /* Build coordinates */ 27839566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 27849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 27859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 27869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 27870510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 27889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 27899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 27900510c589SMatthew G. Knepley } 27919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 27929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 27939566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 27949566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 27959566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 27969566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 27979566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 27989566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 2799dd400576SPatrick Sanan if (rank == 0) { 28009371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 28019371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 28029371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 28039371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 28049371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 28059371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 28069371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 28079371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 28089371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 28099371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 28109371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 28119371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 28129371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 28139371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 28149371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 28159371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 28169371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 28179371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 28189371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 28199371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 28209371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 28219371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 28229371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 28239371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 28249371c9d4SSatish Balay coords[8 * dim + 0] = dis; 28259371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 28269371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 28279371c9d4SSatish Balay coords[9 * dim + 0] = dis; 28289371c9d4SSatish Balay coords[9 * dim + 1] = dis; 28299371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 28309371c9d4SSatish Balay coords[10 * dim + 0] = dis; 28319371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 28329371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 28339371c9d4SSatish Balay coords[11 * dim + 0] = dis; 28349371c9d4SSatish Balay coords[11 * dim + 1] = dis; 28359371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 28369371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 28379371c9d4SSatish Balay coords[12 * dim + 1] = dis; 28389371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 28399371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 28409371c9d4SSatish Balay coords[13 * dim + 1] = dis; 28419371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 28429371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 28439371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 28449371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 28459371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 28469371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 28479371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 2848ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 28499371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 28509371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 28519371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 28529371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 28539371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 28549371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 28559371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 28569371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 28579371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 28589371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 28599371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 28609371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 28619371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 28629371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 28639371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 28649371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 28659371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 28669371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 28679371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 28689371c9d4SSatish Balay coords[22 * dim + 1] = dis; 28699371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 28709371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 28719371c9d4SSatish Balay coords[23 * dim + 1] = dis; 28729371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 2873ae8bcbbbSMatthew G. Knepley } 2874d8c47e87SMatthew G. Knepley } 28759566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 28769566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 28779566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 28780510c589SMatthew G. Knepley } 2879006a8963SMatthew G. Knepley /* Create periodicity */ 2880006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 28816858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 28826858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 2883006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 2884ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 28856858538eSMatthew G. Knepley PetscInt numZCells = 3; 2886006a8963SMatthew G. Knepley 28876858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 28886858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 28894fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 2890006a8963SMatthew G. Knepley } 2891dbc1dc17SMatthew G. Knepley { 28929318fe57SMatthew G. Knepley DM cdm; 28939318fe57SMatthew G. Knepley PetscDS cds; 28949318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 2895dbc1dc17SMatthew G. Knepley 289649704ca5SMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL)); 28979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 28989566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 28999566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 2900dbc1dc17SMatthew G. Knepley } 290146139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 290246139095SJed Brown 29039318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 29049566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 290549704ca5SMatthew G. Knepley 290649704ca5SMatthew G. Knepley char oldprefix[PETSC_MAX_PATH_LEN]; 290749704ca5SMatthew G. Knepley const char *prefix; 290849704ca5SMatthew G. Knepley 290949704ca5SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 291049704ca5SMatthew G. Knepley PetscCall(PetscStrncpy(oldprefix, prefix, PETSC_MAX_PATH_LEN)); 291149704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, "petsc_cyl_ref_")); 291249704ca5SMatthew G. Knepley for (PetscInt r = 0; r < PetscMax(0, Nr); ++r) { 291349704ca5SMatthew G. Knepley DM rdm; 291449704ca5SMatthew G. Knepley 291549704ca5SMatthew G. Knepley PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 291649704ca5SMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &rdm)); 291749704ca5SMatthew G. Knepley } 291849704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldprefix)); 291949704ca5SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, snapToCylinder)); 292049704ca5SMatthew G. Knepley 292149704ca5SMatthew G. Knepley DMLabel bdlabel, edgelabel; 292249704ca5SMatthew G. Knepley IS faceIS; 292349704ca5SMatthew G. Knepley const PetscInt *faces; 292449704ca5SMatthew G. Knepley PetscInt Nf; 292549704ca5SMatthew G. Knepley 292649704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 292749704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 292849704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "generatrix")); 292949704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "generatrix", &edgelabel)); 293049704ca5SMatthew G. Knepley PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 293149704ca5SMatthew G. Knepley // Remove faces on top and bottom 293249704ca5SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(bdlabel, 1, &faceIS)); 2933ba1b3593SJeremy L Thompson if (faceIS) { 293449704ca5SMatthew G. Knepley PetscCall(ISGetLocalSize(faceIS, &Nf)); 293549704ca5SMatthew G. Knepley PetscCall(ISGetIndices(faceIS, &faces)); 293649704ca5SMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 293749704ca5SMatthew G. Knepley PetscReal vol, normal[3]; 293849704ca5SMatthew G. Knepley 293949704ca5SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFVM(dm, faces[f], &vol, NULL, normal)); 294049704ca5SMatthew G. Knepley if (PetscAbsReal(normal[2]) < PETSC_SMALL) PetscCall(DMLabelSetValue(edgelabel, faces[f], 1)); 294149704ca5SMatthew G. Knepley } 294249704ca5SMatthew G. Knepley PetscCall(ISRestoreIndices(faceIS, &faces)); 294349704ca5SMatthew G. Knepley PetscCall(ISDestroy(&faceIS)); 2944ba1b3593SJeremy L Thompson } 294549704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, bdlabel)); 294649704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, edgelabel)); 29473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29480510c589SMatthew G. Knepley } 29490510c589SMatthew G. Knepley 295024119c2aSMatthew G. Knepley /*@ 29519318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 295224119c2aSMatthew G. Knepley 2953d083f849SBarry Smith Collective 295424119c2aSMatthew G. Knepley 295524119c2aSMatthew G. Knepley Input Parameters: 2956a1cb98faSBarry Smith + comm - The communicator for the `DM` object 295749704ca5SMatthew G. Knepley . periodicZ - The boundary type for the Z direction 295849704ca5SMatthew G. Knepley - Nr - The number of refinements to carry out 295924119c2aSMatthew G. Knepley 296024119c2aSMatthew G. Knepley Output Parameter: 296120f4b53cSBarry Smith . dm - The `DM` object 296224119c2aSMatthew G. Knepley 296324119c2aSMatthew G. Knepley Level: beginner 296424119c2aSMatthew G. Knepley 2965a1cb98faSBarry Smith Note: 2966a4e35b19SJacob Faibussowitsch Here is the output numbering looking from the bottom of the cylinder\: 2967a1cb98faSBarry Smith .vb 2968a1cb98faSBarry Smith 17-----14 2969a1cb98faSBarry Smith | | 2970a1cb98faSBarry Smith | 2 | 2971a1cb98faSBarry Smith | | 2972a1cb98faSBarry Smith 17-----8-----7-----14 2973a1cb98faSBarry Smith | | | | 2974a1cb98faSBarry Smith | 3 | 0 | 1 | 2975a1cb98faSBarry Smith | | | | 2976a1cb98faSBarry Smith 19-----5-----6-----13 2977a1cb98faSBarry Smith | | 2978a1cb98faSBarry Smith | 4 | 2979a1cb98faSBarry Smith | | 2980a1cb98faSBarry Smith 19-----13 2981a1cb98faSBarry Smith 2982a1cb98faSBarry Smith and up through the top 2983a1cb98faSBarry Smith 2984a1cb98faSBarry Smith 18-----16 2985a1cb98faSBarry Smith | | 2986a1cb98faSBarry Smith | 2 | 2987a1cb98faSBarry Smith | | 2988a1cb98faSBarry Smith 18----10----11-----16 2989a1cb98faSBarry Smith | | | | 2990a1cb98faSBarry Smith | 3 | 0 | 1 | 2991a1cb98faSBarry Smith | | | | 2992a1cb98faSBarry Smith 20-----9----12-----15 2993a1cb98faSBarry Smith | | 2994a1cb98faSBarry Smith | 4 | 2995a1cb98faSBarry Smith | | 2996a1cb98faSBarry Smith 20-----15 2997a1cb98faSBarry Smith .ve 2998a1cb98faSBarry Smith 29991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 300024119c2aSMatthew G. Knepley @*/ 300149704ca5SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, PetscInt Nr, DM *dm) 3002d71ae5a4SJacob Faibussowitsch { 30039318fe57SMatthew G. Knepley PetscFunctionBegin; 300449704ca5SMatthew G. Knepley PetscAssertPointer(dm, 4); 30059566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 30069566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 300749704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ, Nr)); 30083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30099318fe57SMatthew G. Knepley } 30109318fe57SMatthew G. Knepley 3011d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 3012d71ae5a4SJacob Faibussowitsch { 301324119c2aSMatthew G. Knepley const PetscInt dim = 3; 3014412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 30159fe9f049SMatthew G. Knepley PetscMPIInt rank; 301624119c2aSMatthew G. Knepley 301724119c2aSMatthew G. Knepley PetscFunctionBegin; 301863a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 301946139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 30209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 30219566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 3022412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 30239566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 302424119c2aSMatthew G. Knepley /* Create topology */ 302524119c2aSMatthew G. Knepley { 302624119c2aSMatthew G. Knepley PetscInt cone[6], c; 302724119c2aSMatthew G. Knepley 3028dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 3029dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 30309566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 30319566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 30329566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 303324119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 30349371c9d4SSatish Balay cone[0] = c + n * 1; 30359371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 30369371c9d4SSatish Balay cone[2] = 0 + 3 * n; 30379371c9d4SSatish Balay cone[3] = c + n * 2; 30389371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 30399371c9d4SSatish Balay cone[5] = 1 + 3 * n; 30409566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 30419566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 304224119c2aSMatthew G. Knepley } 30439566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 30449566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 304524119c2aSMatthew G. Knepley } 304648a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 304724119c2aSMatthew G. Knepley /* Create cylinder geometry */ 304824119c2aSMatthew G. Knepley { 304924119c2aSMatthew G. Knepley Vec coordinates; 305024119c2aSMatthew G. Knepley PetscSection coordSection; 305124119c2aSMatthew G. Knepley PetscScalar *coords; 3052412e9a14SMatthew G. Knepley PetscInt coordSize, c; 305324119c2aSMatthew G. Knepley 305424119c2aSMatthew G. Knepley /* Build coordinates */ 30559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 30569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 30579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 30589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 305924119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 30609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 30619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 306224119c2aSMatthew G. Knepley } 30639566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 30649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 30659566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 30669566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 30679566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 30689566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 30699566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 30709566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 307124119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 30729371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 30739371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 30749371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 30759371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 30769371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 30779371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 307824119c2aSMatthew G. Knepley } 3079dd400576SPatrick Sanan if (rank == 0) { 30809371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 30819371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 30829371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 30839371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 30849371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 30859371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 30869fe9f049SMatthew G. Knepley } 30879566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 30889566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 30899566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 309024119c2aSMatthew G. Knepley } 309146139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 30929318fe57SMatthew G. Knepley /* Interpolate */ 30939566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 30943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30959318fe57SMatthew G. Knepley } 30969318fe57SMatthew G. Knepley 30979318fe57SMatthew G. Knepley /*@ 30989318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 30999318fe57SMatthew G. Knepley 31009318fe57SMatthew G. Knepley Collective 31019318fe57SMatthew G. Knepley 31029318fe57SMatthew G. Knepley Input Parameters: 3103a1cb98faSBarry Smith + comm - The communicator for the `DM` object 31049318fe57SMatthew G. Knepley . n - The number of wedges around the origin 31059318fe57SMatthew G. Knepley - interpolate - Create edges and faces 31069318fe57SMatthew G. Knepley 31079318fe57SMatthew G. Knepley Output Parameter: 3108a1cb98faSBarry Smith . dm - The `DM` object 31099318fe57SMatthew G. Knepley 31109318fe57SMatthew G. Knepley Level: beginner 31119318fe57SMatthew G. Knepley 31121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 31139318fe57SMatthew G. Knepley @*/ 3114d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 3115d71ae5a4SJacob Faibussowitsch { 31169318fe57SMatthew G. Knepley PetscFunctionBegin; 31174f572ea9SToby Isaac PetscAssertPointer(dm, 4); 31189566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 31199566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 31209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 31213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 312224119c2aSMatthew G. Knepley } 312324119c2aSMatthew G. Knepley 3124d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 3125d71ae5a4SJacob Faibussowitsch { 312665a81367SMatthew G. Knepley PetscReal prod = 0.0; 312765a81367SMatthew G. Knepley PetscInt i; 312865a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 312965a81367SMatthew G. Knepley return PetscSqrtReal(prod); 313065a81367SMatthew G. Knepley } 3131dd2b43ebSStefano Zampini 3132d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 3133d71ae5a4SJacob Faibussowitsch { 313465a81367SMatthew G. Knepley PetscReal prod = 0.0; 313565a81367SMatthew G. Knepley PetscInt i; 313665a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += x[i] * y[i]; 313765a81367SMatthew G. Knepley return prod; 313865a81367SMatthew G. Knepley } 313965a81367SMatthew G. Knepley 314051a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 3141d71ae5a4SJacob Faibussowitsch static void snapToSphere(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 3142d71ae5a4SJacob Faibussowitsch { 314351a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 314451a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 314551a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 314651a74b61SMatthew G. Knepley 314751a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 314851a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 314951a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 315051a74b61SMatthew G. Knepley } 315151a74b61SMatthew G. Knepley 3152d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 3153d71ae5a4SJacob Faibussowitsch { 315465a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 315565a81367SMatthew G. Knepley PetscSection coordSection; 315665a81367SMatthew G. Knepley Vec coordinates; 315765a81367SMatthew G. Knepley PetscScalar *coords; 315865a81367SMatthew G. Knepley PetscReal *coordsIn; 315907c565c5SJose E. Roman PetscInt numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, e; 316065a81367SMatthew G. Knepley PetscMPIInt rank; 316165a81367SMatthew G. Knepley 316265a81367SMatthew G. Knepley PetscFunctionBegin; 31639318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 316446139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 31659566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 31669566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 31679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 316865a81367SMatthew G. Knepley switch (dim) { 31695c344501SMatthew G. Knepley case 1: 31705c344501SMatthew G. Knepley numCells = 16; 31715c344501SMatthew G. Knepley numVerts = numCells; 31725c344501SMatthew G. Knepley 31735c344501SMatthew G. Knepley // Build Topology 31745c344501SMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 31755c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 31765c344501SMatthew G. Knepley PetscCall(DMSetUp(dm)); 31775c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 31785c344501SMatthew G. Knepley PetscInt cone[2]; 31795c344501SMatthew G. Knepley 31805c344501SMatthew G. Knepley cone[0] = c + numCells; 31815c344501SMatthew G. Knepley cone[1] = (c + 1) % numVerts + numCells; 31825c344501SMatthew G. Knepley PetscCall(DMPlexSetCone(dm, c, cone)); 31835c344501SMatthew G. Knepley } 31845c344501SMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 31855c344501SMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 31865c344501SMatthew G. Knepley PetscCall(PetscMalloc1(numVerts * embedDim, &coordsIn)); 31875c344501SMatthew G. Knepley for (PetscInt v = 0; v < numVerts; ++v) { 31885c344501SMatthew G. Knepley const PetscReal rad = 2. * PETSC_PI * v / numVerts; 31895c344501SMatthew G. Knepley 31905c344501SMatthew G. Knepley coordsIn[v * embedDim + 0] = PetscCosReal(rad); 31915c344501SMatthew G. Knepley coordsIn[v * embedDim + 1] = PetscSinReal(rad); 31925c344501SMatthew G. Knepley } 31935c344501SMatthew G. Knepley break; 319465a81367SMatthew G. Knepley case 2: 319565a81367SMatthew G. Knepley if (simplex) { 319651a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 319751a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 319865a81367SMatthew G. Knepley const PetscInt degree = 5; 319951a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 320065a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 320165a81367SMatthew G. Knepley PetscInt cone[3]; 320207c565c5SJose E. Roman PetscInt *graph; 320365a81367SMatthew G. Knepley 32049371c9d4SSatish Balay vertex[0] *= R / radius; 32059371c9d4SSatish Balay vertex[1] *= R / radius; 32069371c9d4SSatish Balay vertex[2] *= R / radius; 3207dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 3208dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 320965a81367SMatthew G. Knepley firstVertex = numCells; 321051a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 321165a81367SMatthew G. Knepley 321265a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 321365a81367SMatthew G. Knepley 321465a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 321551a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 321665a81367SMatthew G. Knepley */ 321765a81367SMatthew G. Knepley /* Construct vertices */ 32189566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3219dd400576SPatrick Sanan if (rank == 0) { 322007c565c5SJose E. Roman for (PetscInt p = 0, i = 0; p < embedDim; ++p) { 322165a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 322265a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 322365a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 322465a81367SMatthew G. Knepley ++i; 322565a81367SMatthew G. Knepley } 322665a81367SMatthew G. Knepley } 322765a81367SMatthew G. Knepley } 322845da822fSValeria Barra } 322965a81367SMatthew G. Knepley /* Construct graph */ 32309566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 323107c565c5SJose E. Roman for (PetscInt i = 0; i < numVerts; ++i) { 323207c565c5SJose E. Roman PetscInt k = 0; 323307c565c5SJose E. Roman for (PetscInt j = 0; j < numVerts; ++j) { 32349371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 32359371c9d4SSatish Balay graph[i * numVerts + j] = 1; 32369371c9d4SSatish Balay ++k; 32379371c9d4SSatish Balay } 323865a81367SMatthew G. Knepley } 323963a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 324065a81367SMatthew G. Knepley } 324165a81367SMatthew G. Knepley /* Build Topology */ 32429566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 324307c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 32449566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 324565a81367SMatthew G. Knepley /* Cells */ 324607c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 324707c565c5SJose E. Roman for (PetscInt j = 0; j < i; ++j) { 324807c565c5SJose E. Roman for (PetscInt k = 0; k < j; ++k) { 324965a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 32509371c9d4SSatish Balay cone[0] = firstVertex + i; 32519371c9d4SSatish Balay cone[1] = firstVertex + j; 32529371c9d4SSatish Balay cone[2] = firstVertex + k; 325365a81367SMatthew G. Knepley /* Check orientation */ 325465a81367SMatthew G. Knepley { 32559371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 32569371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 32579371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 32589371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 32599371c9d4SSatish Balay }; 326065a81367SMatthew G. Knepley PetscReal normal[3]; 326165a81367SMatthew G. Knepley PetscInt e, f; 326265a81367SMatthew G. Knepley 326365a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 326465a81367SMatthew G. Knepley normal[d] = 0.0; 326565a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3266ad540459SPierre Jolivet for (f = 0; f < embedDim; ++f) normal[d] += epsilon[d][e][f] * (coordsIn[j * embedDim + e] - coordsIn[i * embedDim + e]) * (coordsIn[k * embedDim + f] - coordsIn[i * embedDim + f]); 326765a81367SMatthew G. Knepley } 326865a81367SMatthew G. Knepley } 32699371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 32709371c9d4SSatish Balay PetscInt tmp = cone[1]; 32719371c9d4SSatish Balay cone[1] = cone[2]; 32729371c9d4SSatish Balay cone[2] = tmp; 327365a81367SMatthew G. Knepley } 327465a81367SMatthew G. Knepley } 32759566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 327665a81367SMatthew G. Knepley } 327765a81367SMatthew G. Knepley } 327865a81367SMatthew G. Knepley } 327965a81367SMatthew G. Knepley } 32809566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 32819566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 32829566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 328365a81367SMatthew G. Knepley } else { 32842829fed8SMatthew G. Knepley /* 32852829fed8SMatthew G. Knepley 12-21--13 32862829fed8SMatthew G. Knepley | | 32872829fed8SMatthew G. Knepley 25 4 24 32882829fed8SMatthew G. Knepley | | 32892829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 32902829fed8SMatthew G. Knepley | | | | 32912829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 32922829fed8SMatthew G. Knepley | | | | 32932829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 32942829fed8SMatthew G. Knepley | | 32952829fed8SMatthew G. Knepley 20 1 19 32962829fed8SMatthew G. Knepley | | 32972829fed8SMatthew G. Knepley 10-18--11 32982829fed8SMatthew G. Knepley | | 32992829fed8SMatthew G. Knepley 23 2 22 33002829fed8SMatthew G. Knepley | | 33012829fed8SMatthew G. Knepley 12-21--13 33022829fed8SMatthew G. Knepley */ 33032829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 33042829fed8SMatthew G. Knepley 3305dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 3306dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 3307dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 330865a81367SMatthew G. Knepley firstVertex = numCells; 330965a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 33102829fed8SMatthew G. Knepley /* Build Topology */ 33119566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 331207c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 331348a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 33149566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3315dd400576SPatrick Sanan if (rank == 0) { 33162829fed8SMatthew G. Knepley /* Cell 0 */ 33179371c9d4SSatish Balay cone[0] = 14; 33189371c9d4SSatish Balay cone[1] = 15; 33199371c9d4SSatish Balay cone[2] = 16; 33209371c9d4SSatish Balay cone[3] = 17; 33219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 33229371c9d4SSatish Balay ornt[0] = 0; 33239371c9d4SSatish Balay ornt[1] = 0; 33249371c9d4SSatish Balay ornt[2] = 0; 33259371c9d4SSatish Balay ornt[3] = 0; 33269566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 33272829fed8SMatthew G. Knepley /* Cell 1 */ 33289371c9d4SSatish Balay cone[0] = 18; 33299371c9d4SSatish Balay cone[1] = 19; 33309371c9d4SSatish Balay cone[2] = 14; 33319371c9d4SSatish Balay cone[3] = 20; 33329566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 33339371c9d4SSatish Balay ornt[0] = 0; 33349371c9d4SSatish Balay ornt[1] = 0; 33359371c9d4SSatish Balay ornt[2] = -1; 33369371c9d4SSatish Balay ornt[3] = 0; 33379566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 33382829fed8SMatthew G. Knepley /* Cell 2 */ 33399371c9d4SSatish Balay cone[0] = 21; 33409371c9d4SSatish Balay cone[1] = 22; 33419371c9d4SSatish Balay cone[2] = 18; 33429371c9d4SSatish Balay cone[3] = 23; 33439566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 33449371c9d4SSatish Balay ornt[0] = 0; 33459371c9d4SSatish Balay ornt[1] = 0; 33469371c9d4SSatish Balay ornt[2] = -1; 33479371c9d4SSatish Balay ornt[3] = 0; 33489566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 33492829fed8SMatthew G. Knepley /* Cell 3 */ 33509371c9d4SSatish Balay cone[0] = 19; 33519371c9d4SSatish Balay cone[1] = 22; 33529371c9d4SSatish Balay cone[2] = 24; 33539371c9d4SSatish Balay cone[3] = 15; 33549566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 33559371c9d4SSatish Balay ornt[0] = -1; 33569371c9d4SSatish Balay ornt[1] = -1; 33579371c9d4SSatish Balay ornt[2] = 0; 33589371c9d4SSatish Balay ornt[3] = -1; 33599566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 33602829fed8SMatthew G. Knepley /* Cell 4 */ 33619371c9d4SSatish Balay cone[0] = 16; 33629371c9d4SSatish Balay cone[1] = 24; 33639371c9d4SSatish Balay cone[2] = 21; 33649371c9d4SSatish Balay cone[3] = 25; 33659566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 33669371c9d4SSatish Balay ornt[0] = -1; 33679371c9d4SSatish Balay ornt[1] = -1; 33689371c9d4SSatish Balay ornt[2] = -1; 33699371c9d4SSatish Balay ornt[3] = 0; 33709566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 33712829fed8SMatthew G. Knepley /* Cell 5 */ 33729371c9d4SSatish Balay cone[0] = 20; 33739371c9d4SSatish Balay cone[1] = 17; 33749371c9d4SSatish Balay cone[2] = 25; 33759371c9d4SSatish Balay cone[3] = 23; 33769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 33779371c9d4SSatish Balay ornt[0] = -1; 33789371c9d4SSatish Balay ornt[1] = -1; 33799371c9d4SSatish Balay ornt[2] = -1; 33809371c9d4SSatish Balay ornt[3] = -1; 33819566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 33822829fed8SMatthew G. Knepley /* Edges */ 33839371c9d4SSatish Balay cone[0] = 6; 33849371c9d4SSatish Balay cone[1] = 7; 33859566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 33869371c9d4SSatish Balay cone[0] = 7; 33879371c9d4SSatish Balay cone[1] = 8; 33889566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 33899371c9d4SSatish Balay cone[0] = 8; 33909371c9d4SSatish Balay cone[1] = 9; 33919566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 33929371c9d4SSatish Balay cone[0] = 9; 33939371c9d4SSatish Balay cone[1] = 6; 33949566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 33959371c9d4SSatish Balay cone[0] = 10; 33969371c9d4SSatish Balay cone[1] = 11; 33979566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 33989371c9d4SSatish Balay cone[0] = 11; 33999371c9d4SSatish Balay cone[1] = 7; 34009566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 34019371c9d4SSatish Balay cone[0] = 6; 34029371c9d4SSatish Balay cone[1] = 10; 34039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 34049371c9d4SSatish Balay cone[0] = 12; 34059371c9d4SSatish Balay cone[1] = 13; 34069566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 34079371c9d4SSatish Balay cone[0] = 13; 34089371c9d4SSatish Balay cone[1] = 11; 34099566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 34109371c9d4SSatish Balay cone[0] = 10; 34119371c9d4SSatish Balay cone[1] = 12; 34129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 34139371c9d4SSatish Balay cone[0] = 13; 34149371c9d4SSatish Balay cone[1] = 8; 34159566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 34169371c9d4SSatish Balay cone[0] = 12; 34179371c9d4SSatish Balay cone[1] = 9; 34189566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 341945da822fSValeria Barra } 34209566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 34219566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 34222829fed8SMatthew G. Knepley /* Build coordinates */ 34239566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3424dd400576SPatrick Sanan if (rank == 0) { 34259371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 34269371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 34279371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 34289371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 34299371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 34309371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 34319371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 34329371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 34339371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 34349371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 34359371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 34369371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 34379371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 34389371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 34399371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 34409371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 34419371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 34429371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 34439371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 34449371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 34459371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 34469371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 34479371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 34489371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 344965a81367SMatthew G. Knepley } 345045da822fSValeria Barra } 345165a81367SMatthew G. Knepley break; 345265a81367SMatthew G. Knepley case 3: 3453116ded15SMatthew G. Knepley if (simplex) { 3454116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 345551a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 345651a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 345751a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 3458116ded15SMatthew G. Knepley const PetscInt degree = 12; 3459116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 34609371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 34619371c9d4SSatish Balay {0, 1, 2, 3}, 34629371c9d4SSatish Balay {0, 2, 3, 1}, 34639371c9d4SSatish Balay {0, 3, 1, 2}, 34649371c9d4SSatish Balay {1, 0, 3, 2}, 34659371c9d4SSatish Balay {1, 2, 0, 3}, 34669371c9d4SSatish Balay {1, 3, 2, 0}, 34679371c9d4SSatish Balay {2, 0, 1, 3}, 34689371c9d4SSatish Balay {2, 1, 3, 0}, 34699371c9d4SSatish Balay {2, 3, 0, 1}, 34709371c9d4SSatish Balay {3, 0, 2, 1}, 34719371c9d4SSatish Balay {3, 1, 0, 2}, 34729371c9d4SSatish Balay {3, 2, 1, 0} 34739371c9d4SSatish Balay }; 3474116ded15SMatthew G. Knepley PetscInt cone[4]; 3475116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 3476116ded15SMatthew G. Knepley 34779371c9d4SSatish Balay vertexA[0] *= R; 34789371c9d4SSatish Balay vertexA[1] *= R; 34799371c9d4SSatish Balay vertexA[2] *= R; 34809371c9d4SSatish Balay vertexA[3] *= R; 34819371c9d4SSatish Balay vertexB[0] *= R; 34829371c9d4SSatish Balay vertexB[1] *= R; 34839371c9d4SSatish Balay vertexB[2] *= R; 34849371c9d4SSatish Balay vertexB[3] *= R; 34859371c9d4SSatish Balay vertexC[0] *= R; 34869371c9d4SSatish Balay vertexC[1] *= R; 34879371c9d4SSatish Balay vertexC[2] *= R; 34889371c9d4SSatish Balay vertexC[3] *= R; 3489dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 3490dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 3491116ded15SMatthew G. Knepley firstVertex = numCells; 3492116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 3493116ded15SMatthew G. Knepley 3494116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 3495116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 3496116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 3497116ded15SMatthew G. Knepley 3498116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 34996333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 3500116ded15SMatthew G. Knepley 3501116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 3502116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 3503116ded15SMatthew G. Knepley */ 3504116ded15SMatthew G. Knepley /* Construct vertices */ 35059566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3506116ded15SMatthew G. Knepley i = 0; 3507dd400576SPatrick Sanan if (rank == 0) { 3508116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3509116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3510116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3511116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 3512116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 3513116ded15SMatthew G. Knepley ++i; 3514116ded15SMatthew G. Knepley } 3515116ded15SMatthew G. Knepley } 3516116ded15SMatthew G. Knepley } 3517116ded15SMatthew G. Knepley } 3518116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 3519116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 3520116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3521116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 3522116ded15SMatthew G. Knepley ++i; 3523116ded15SMatthew G. Knepley } 3524116ded15SMatthew G. Knepley } 3525116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 3526116ded15SMatthew G. Knepley s[3] = 1; 3527116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3528116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3529116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3530116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 3531116ded15SMatthew G. Knepley ++i; 3532116ded15SMatthew G. Knepley } 3533116ded15SMatthew G. Knepley } 3534116ded15SMatthew G. Knepley } 3535116ded15SMatthew G. Knepley } 353645da822fSValeria Barra } 353763a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 3538116ded15SMatthew G. Knepley /* Construct graph */ 35399566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 3540116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 3541116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 35429371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 35439371c9d4SSatish Balay graph[i * numVerts + j] = 1; 35449371c9d4SSatish Balay ++k; 35459371c9d4SSatish Balay } 3546116ded15SMatthew G. Knepley } 354763a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 3548116ded15SMatthew G. Knepley } 3549116ded15SMatthew G. Knepley /* Build Topology */ 35509566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 355107c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 35529566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3553116ded15SMatthew G. Knepley /* Cells */ 3554dd400576SPatrick Sanan if (rank == 0) { 355507c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 3556116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 3557116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 3558116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 35599371c9d4SSatish Balay if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i] && graph[l * numVerts + i] && graph[l * numVerts + j] && graph[l * numVerts + k]) { 35609371c9d4SSatish Balay cone[0] = firstVertex + i; 35619371c9d4SSatish Balay cone[1] = firstVertex + j; 35629371c9d4SSatish Balay cone[2] = firstVertex + k; 35639371c9d4SSatish Balay cone[3] = firstVertex + l; 3564116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 3565116ded15SMatthew G. Knepley { 35669371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 35679371c9d4SSatish Balay {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 1}, {0, 0, -1, 0}}, {{0, 0, 0, 0}, {0, 0, 0, -1}, {0, 0, 0, 0}, {0, 1, 0, 0}}, {{0, 0, 0, 0}, {0, 0, 1, 0}, {0, -1, 0, 0}, {0, 0, 0, 0}}}, 3568116ded15SMatthew G. Knepley 35699371c9d4SSatish Balay {{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, -1}, {0, 0, 1, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, {{0, 0, 0, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}, {-1, 0, 0, 0}}, {{0, 0, -1, 0}, {0, 0, 0, 0}, {1, 0, 0, 0}, {0, 0, 0, 0}}}, 3570116ded15SMatthew G. Knepley 35719371c9d4SSatish Balay {{{0, 0, 0, 0}, {0, 0, 0, 1}, {0, 0, 0, 0}, {0, -1, 0, 0}}, {{0, 0, 0, -1}, {0, 0, 0, 0}, {0, 0, 0, 0}, {1, 0, 0, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, {{0, 1, 0, 0}, {-1, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}}, 3572116ded15SMatthew G. Knepley 35739371c9d4SSatish Balay {{{0, 0, 0, 0}, {0, 0, -1, 0}, {0, 1, 0, 0}, {0, 0, 0, 0}}, {{0, 0, 1, 0}, {0, 0, 0, 0}, {-1, 0, 0, 0}, {0, 0, 0, 0}}, {{0, -1, 0, 0}, {1, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}} } 35749371c9d4SSatish Balay }; 3575116ded15SMatthew G. Knepley PetscReal normal[4]; 3576116ded15SMatthew G. Knepley PetscInt e, f, g; 3577116ded15SMatthew G. Knepley 3578116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 3579116ded15SMatthew G. Knepley normal[d] = 0.0; 3580116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3581116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 3582116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 3583116ded15SMatthew G. Knepley normal[d] += epsilon[d][e][f][g] * (coordsIn[j * embedDim + e] - coordsIn[i * embedDim + e]) * (coordsIn[k * embedDim + f] - coordsIn[i * embedDim + f]) * (coordsIn[l * embedDim + f] - coordsIn[i * embedDim + f]); 3584116ded15SMatthew G. Knepley } 3585116ded15SMatthew G. Knepley } 3586116ded15SMatthew G. Knepley } 3587116ded15SMatthew G. Knepley } 35889371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 35899371c9d4SSatish Balay PetscInt tmp = cone[1]; 35909371c9d4SSatish Balay cone[1] = cone[2]; 35919371c9d4SSatish Balay cone[2] = tmp; 35929371c9d4SSatish Balay } 3593116ded15SMatthew G. Knepley } 35949566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 3595116ded15SMatthew G. Knepley } 3596116ded15SMatthew G. Knepley } 3597116ded15SMatthew G. Knepley } 3598116ded15SMatthew G. Knepley } 3599116ded15SMatthew G. Knepley } 360045da822fSValeria Barra } 36019566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 36029566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 36039566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 3604116ded15SMatthew G. Knepley } 3605f4d061e9SPierre Jolivet break; 3606d71ae5a4SJacob Faibussowitsch default: 3607d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 360865a81367SMatthew G. Knepley } 360965a81367SMatthew G. Knepley /* Create coordinates */ 36109566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 36119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 36129566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 36139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 36142829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 36159566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 36169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 36172829fed8SMatthew G. Knepley } 36189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 36199566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 36209566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 36219566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 36229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 36239566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 36249566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 36259566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 36269371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 3627ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 36289566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 36299566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 36309566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 36319566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 363251a74b61SMatthew G. Knepley { 363351a74b61SMatthew G. Knepley DM cdm; 363451a74b61SMatthew G. Knepley PetscDS cds; 36359318fe57SMatthew G. Knepley PetscScalar c = R; 363651a74b61SMatthew G. Knepley 3637e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, snapToSphere)); 36389566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 36399566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 36409566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 364151a74b61SMatthew G. Knepley } 364246139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 36439318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 36449566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 36453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36469318fe57SMatthew G. Knepley } 36479318fe57SMatthew G. Knepley 3648b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 3649b7f5c055SJed Brown 3650b7f5c055SJed Brown /* 3651b7f5c055SJed Brown The Schwarz P implicit surface is 3652b7f5c055SJed Brown 3653b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 3654b7f5c055SJed Brown */ 3655d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3656d71ae5a4SJacob Faibussowitsch { 3657b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 3658b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 3659b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 3660b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3661b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 3662ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 3663b7f5c055SJed Brown } 3664b7f5c055SJed Brown } 3665b7f5c055SJed Brown 36664663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3667d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3668d71ae5a4SJacob Faibussowitsch { 3669ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 36703ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 36714663dae6SJed Brown } 36724663dae6SJed Brown 3673b7f5c055SJed Brown /* 3674b7f5c055SJed Brown The Gyroid implicit surface is 3675b7f5c055SJed Brown 3676b7f5c055SJed Brown f(x,y,z) = sin(pi * x) * cos (pi * (y + 1/2)) + sin(pi * (y + 1/2)) * cos(pi * (z + 1/4)) + sin(pi * (z + 1/4)) * cos(pi * x) 3677b7f5c055SJed Brown 3678b7f5c055SJed Brown */ 3679d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3680d71ae5a4SJacob Faibussowitsch { 3681b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 3682b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 3683b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 3684b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 3685b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 3686b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 3687b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 3688b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3689b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3690b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 3691b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3692b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3693b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 3694b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3695b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3696b7f5c055SJed Brown } 3697b7f5c055SJed Brown 36984663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3699d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3700d71ae5a4SJacob Faibussowitsch { 37014663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 37024663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 37034663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 37044663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 37054663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 37063ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 37074663dae6SJed Brown } 37084663dae6SJed Brown 3709b7f5c055SJed Brown /* 3710b7f5c055SJed Brown We wish to solve 3711b7f5c055SJed Brown 3712b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 3713b7f5c055SJed Brown 3714b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 3715b7f5c055SJed Brown f(y) = 0 and (y-x) is parallel to g(y). We do this by using Householder QR to obtain a basis for the 3716b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 3717b7f5c055SJed Brown 3718b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 3719b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 3720b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 3721b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 3722da81f932SPierre Jolivet Since Q is symmetric, this is equivalent to multiplying by Q and taking the last two entries. 3723b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 3724b7f5c055SJed Brown 3725b7f5c055SJed Brown f(y) = 0 1 equation 3726b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 3727b7f5c055SJed Brown 3728b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 3729b7f5c055SJed Brown */ 3730d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 3731d71ae5a4SJacob Faibussowitsch { 3732b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 3733b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 37342f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 37359371c9d4SSatish Balay PetscReal n_y[3][3] = { 37369371c9d4SSatish Balay {0, 0, 0}, 37379371c9d4SSatish Balay {0, 0, 0}, 37389371c9d4SSatish Balay {0, 0, 0} 37399371c9d4SSatish Balay }; 3740b7f5c055SJed Brown 3741b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 3742b7f5c055SJed Brown 3743b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 3744b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3745ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 3746b7f5c055SJed Brown 3747b7f5c055SJed Brown // Define the Householder reflector 3748b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 3749b7f5c055SJed Brown n[0] += norm * sign; 3750b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 3751b7f5c055SJed Brown 3752b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3753b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 3754b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 3755b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 3756b7f5c055SJed Brown 3757b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3758b7f5c055SJed Brown n[i] /= norm; 3759b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3760b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 3761b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 3762b7f5c055SJed Brown } 3763b7f5c055SJed Brown } 3764b7f5c055SJed Brown 3765b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 3766b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) nd_y[i] = n[i] + n_y[0][i] * d[0] + n_y[1][i] * d[1] + n_y[2][i] * d[2]; 3767b7f5c055SJed Brown 3768b7f5c055SJed Brown res[0] = f; 3769b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 3770b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 3771b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 3772b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3773b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 3774b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 3775b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 3776b7f5c055SJed Brown } 3777b7f5c055SJed Brown } 3778b7f5c055SJed Brown 3779b7f5c055SJed Brown /* 3780b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 3781b7f5c055SJed Brown */ 3782d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 3783d71ae5a4SJacob Faibussowitsch { 3784b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 3785b7f5c055SJed Brown 3786b7f5c055SJed Brown PetscFunctionBegin; 3787b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 3788b7f5c055SJed Brown PetscScalar res[3], J[9]; 3789b7f5c055SJed Brown PetscReal resnorm; 3790b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 3791b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 3792b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 379363a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_SELF, "[%" PetscInt_FMT "] res [%g %g %g]\n", iter, (double)PetscRealPart(res[0]), (double)PetscRealPart(res[1]), (double)PetscRealPart(res[2]))); 3794b7f5c055SJed Brown } 3795b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 3796b7f5c055SJed Brown 3797b7f5c055SJed Brown // Take the Newton step 37989566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 3799b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 3800b7f5c055SJed Brown } 3801b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 38023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3803b7f5c055SJed Brown } 3804b7f5c055SJed Brown 3805b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 3806b7f5c055SJed Brown 3807d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 3808d71ae5a4SJacob Faibussowitsch { 3809b7f5c055SJed Brown PetscMPIInt rank; 3810b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 3811b7f5c055SJed Brown PetscInt (*edges)[2] = NULL, *edgeSets = NULL; 3812b7f5c055SJed Brown PetscInt *cells_flat = NULL; 3813b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 3814b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 38158434afd1SBarry Smith PetscSimplePointFn *normalFunc = NULL; 3816b7f5c055SJed Brown DMLabel label; 3817b7f5c055SJed Brown 3818b7f5c055SJed Brown PetscFunctionBegin; 381946139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 38209566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 382163a3b9bcSJacob Faibussowitsch PetscCheck((layers != 0) ^ (thickness == 0.), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_INCOMP, "Layers %" PetscInt_FMT " must be nonzero iff thickness %g is nonzero", layers, (double)thickness); 3822b7f5c055SJed Brown switch (tpstype) { 3823b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 3824b7f5c055SJed Brown PetscCheck(!periodic || (periodic[0] == DM_BOUNDARY_NONE && periodic[1] == DM_BOUNDARY_NONE && periodic[2] == DM_BOUNDARY_NONE), PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Schwarz P does not support periodic meshes"); 3825c5853193SPierre Jolivet if (rank == 0) { 3826b7f5c055SJed Brown PetscInt (*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 3827b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 3828b7f5c055SJed Brown PetscReal L = 1; 3829b7f5c055SJed Brown 3830b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 3831b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 3832b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 3833b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 3834b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 3835b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 38369566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 38379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 38389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 38399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 3840b7f5c055SJed Brown // x-normal pipes 3841b7f5c055SJed Brown vcount = 0; 3842b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 3843b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3844b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3845b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3846b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 3847b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3848b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3849b7f5c055SJed Brown } 3850b7f5c055SJed Brown } 3851b7f5c055SJed Brown } 3852b7f5c055SJed Brown } 3853b7f5c055SJed Brown // y-normal pipes 3854b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3855b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 3856b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3857b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3858b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3859b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 3860b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3861b7f5c055SJed Brown } 3862b7f5c055SJed Brown } 3863b7f5c055SJed Brown } 3864b7f5c055SJed Brown } 3865b7f5c055SJed Brown // z-normal pipes 3866b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3867b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3868b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 3869b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3870b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3871b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3872b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 3873b7f5c055SJed Brown } 3874b7f5c055SJed Brown } 3875b7f5c055SJed Brown } 3876b7f5c055SJed Brown } 3877b7f5c055SJed Brown // junctions 3878b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3879b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3880b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3881b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 3882b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 3883b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 3884b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 3885b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 3886b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 3887b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 3888b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 3889b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 3890b7f5c055SJed Brown } 3891b7f5c055SJed Brown } 3892b7f5c055SJed Brown } 3893b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 3894b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 3895b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 3896b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 3897b7f5c055SJed Brown }; 3898b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 38999371c9d4SSatish Balay ((i * extent[1] + j) * extent[2] + k) * 4, ((i * (extent[1] + 1) + j) * extent[2] + k + Npipes[0]) * 4, ((i * extent[1] + j) * (extent[2] + 1) + k + Npipes[0] + Npipes[1]) * 4}; 3900b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 39019371c9d4SSatish Balay (((i + 1) * extent[1] + j) * extent[2] + k) * 4, ((i * (extent[1] + 1) + j + 1) * extent[2] + k + Npipes[0]) * 4, ((i * extent[1] + j) * (extent[2] + 1) + k + 1 + Npipes[0] + Npipes[1]) * 4}; 3902b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 3903b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 3904b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 3905b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 3906b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 3907b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 3908b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 3909b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 3910b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 3911b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 3912b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 3913b7f5c055SJed Brown if (ijk[dir] == 0) { 3914b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 3915b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 3916b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 3917b7f5c055SJed Brown numEdges++; 3918b7f5c055SJed Brown } 3919b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 3920b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 3921b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 3922b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 3923b7f5c055SJed Brown numEdges++; 3924b7f5c055SJed Brown } 3925b7f5c055SJed Brown } 3926b7f5c055SJed Brown } 3927b7f5c055SJed Brown } 3928b7f5c055SJed Brown } 3929b7f5c055SJed Brown } 393063a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 3931b7f5c055SJed Brown numFaces = 24 * Njunctions; 3932b7f5c055SJed Brown cells_flat = cells[0][0][0]; 3933b7f5c055SJed Brown } 3934b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 39354663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 3936b7f5c055SJed Brown break; 3937b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 3938c5853193SPierre Jolivet if (rank == 0) { 3939b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 3940b7f5c055SJed Brown // 3941b7f5c055SJed Brown // sin(pi*x)*cos(pi*(y+1/2)) + sin(pi*(y+1/2))*cos(pi*(z+1/4)) + sin(pi*(z+1/4))*cos(x) 3942b7f5c055SJed Brown // 3943b7f5c055SJed Brown // on the cell [0,2]^3. 3944b7f5c055SJed Brown // 3945b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 3946b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 3947b7f5c055SJed Brown // like a boomerang: 3948b7f5c055SJed Brown // 3949b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 3950b7f5c055SJed Brown // ----- ------- ------- ------- // 3951b7f5c055SJed Brown // // 3952b7f5c055SJed Brown // + + + + + + + \ + // 3953b7f5c055SJed Brown // \ / \ // 3954b7f5c055SJed Brown // \ `-_ _-' / } // 3955b7f5c055SJed Brown // *-_ `-' _-' / // 3956b7f5c055SJed Brown // + `-+ + + +-' + + / + // 3957b7f5c055SJed Brown // // 3958b7f5c055SJed Brown // // 3959b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 3960b7f5c055SJed Brown // ----- ------- ------- ------- // 3961b7f5c055SJed Brown // // 3962b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 3963b7f5c055SJed Brown // `-_ _-_ _-` / // 3964b7f5c055SJed Brown // \ _-' `-_ / { // 3965b7f5c055SJed Brown // \ / \ // 3966b7f5c055SJed Brown // + + + + + + + \ + // 3967b7f5c055SJed Brown // 3968b7f5c055SJed Brown // 3969b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 3970b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 3971b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 3972b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 3973b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 3974b7f5c055SJed Brown // 3975b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 3976b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 3977b7f5c055SJed Brown // 3978b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 3979b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 3980b7f5c055SJed Brown 3981b7f5c055SJed Brown PetscInt facesPerBlock = 64; 3982b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 3983b7f5c055SJed Brown PetscInt extentPlus[3]; 3984b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 39859371c9d4SSatish Balay const PetscInt A = 0, B = 1, C = 2, D = 3, E = 4, F = 5, G = 6, H = 7, II = 8, J = 9, K = 10, L = 11, M = 12, N = 13, O = 14, P = 15, Q = 16, R = 17, S = 18, T = 19, U = 20, V = 21, W = 22, X = 23, Y = 24, Z = 25, Ap = 26, Bp = 27, Cp = 28, Dp = 29, Ep = 30, Fp = 31, Gp = 32, Hp = 33, Ip = 34, Jp = 35, Kp = 36, Lp = 37, Mp = 38, Np = 39, Op = 40, Pp = 41, Qp = 42, Rp = 43, Sp = 44, Tp = 45, Up = 46, Vp = 47, Wp = 48, Xp = 49, Yp = 50, Zp = 51, Aq = 52, Bq = 53, Cq = 54, Dq = 55; 39869371c9d4SSatish Balay const PetscInt pattern[64][4] = { 39879371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 3988b7f5c055SJed Brown /* layer 0 */ 39899371c9d4SSatish Balay {A, C, K, G }, 39909371c9d4SSatish Balay {C, B, II, K }, 39919371c9d4SSatish Balay {D, A, H, L }, 39929371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 39939371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 39949371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 39959371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 39969371c9d4SSatish Balay {B, F, M, II }, 3997b7f5c055SJed Brown /* layer 1 */ 39989371c9d4SSatish Balay {G, K, Q, O }, 39999371c9d4SSatish Balay {K, II, P, Q }, 40009371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 40019371c9d4SSatish Balay {J, L, R, P }, 40029371c9d4SSatish Balay {N, J, P, S }, 40039371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 40049371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 40059371c9d4SSatish Balay {II, M, T, P }, 4006b7f5c055SJed Brown /* layer 2 */ 40079371c9d4SSatish Balay {O, Q, Y, U }, 40089371c9d4SSatish Balay {Q, P, W, Y }, 40099371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 40109371c9d4SSatish Balay {P, R, Ap, W }, 40119371c9d4SSatish Balay {S, P, X, Bp }, 40129371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 40139371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 40149371c9d4SSatish Balay {P, T, Z, X }, 4015b7f5c055SJed Brown /* layer 3 */ 40169371c9d4SSatish Balay {U, Y, Ep, Dp }, 40179371c9d4SSatish Balay {Y, W, Cp, Ep }, 40189371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 40199371c9d4SSatish Balay {W, Ap, Gp, Cp }, 40209371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 40219371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 40229371c9d4SSatish Balay {Z, V, Dp, Hp }, 40239371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 4024b7f5c055SJed Brown /* layer 4 */ 40259371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 40269371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 40279371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 40289371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 40299371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 40309371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 40319371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 40329371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 4033b7f5c055SJed Brown /* layer 5 */ 40349371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 40359371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 40369371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 40379371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 40389371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 40399371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 40409371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 40419371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 4042b7f5c055SJed Brown /* layer 6 */ 40439371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 40449371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 40459371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 40469371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 40479371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 40489371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 40499371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 40509371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 4051b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 40529371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 40539371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 40549371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 40559371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 40569371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 40579371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 40589371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 40599371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 4060b7f5c055SJed Brown }; 4061b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 40629371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 4063bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 4064bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 4065bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 4066bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 4067bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 4068bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 4069b7f5c055SJed Brown 4070bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 4071bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 4072bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 4073bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 4074bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 4075bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 4076bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 4077bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 4078b7f5c055SJed Brown 4079bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 4080bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 4081bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 4082bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 4083bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 4084bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 4085b7f5c055SJed Brown 4086bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 4087bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 4088bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 4089bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 4090bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 4091bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 4092bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 4093bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 4094b7f5c055SJed Brown 4095bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 4096bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 4097bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 4098bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 4099bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 4100bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 4101b7f5c055SJed Brown 4102bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 4103bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 4104bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 4105bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 4106bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 4107bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 4108bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 4109bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 4110b7f5c055SJed Brown 4111bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 4112bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 4113bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 4114bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 4115bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 4116bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 4117b7f5c055SJed Brown 4118bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 4119bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 4120bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 4121bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 4122bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 4123bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 4124bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 4125bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 4126b7f5c055SJed Brown }; 4127b7f5c055SJed Brown PetscInt (*cells)[64][4] = NULL; 4128b7f5c055SJed Brown PetscBool *seen; 4129b7f5c055SJed Brown PetscInt *vertToTrueVert; 4130b7f5c055SJed Brown PetscInt count; 4131b7f5c055SJed Brown 4132b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 4133b7f5c055SJed Brown numBlocks = 1; 4134b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 4135b7f5c055SJed Brown numBlocksPlus = 1; 4136b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 4137b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 41389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 41399566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 4140b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 4141b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 4142b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 4143b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 4144b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 4145b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 4146b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 4147b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 4148b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 4149b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 4150b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 4151b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 4152b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 4153b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 4154b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 4155b7f5c055SJed Brown 4156b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 4157b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 4158b7f5c055SJed Brown } 4159b7f5c055SJed Brown } 4160b7f5c055SJed Brown } 4161b7f5c055SJed Brown } 4162b7f5c055SJed Brown } 41639371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 41649371c9d4SSatish Balay if (seen[i]) numVertices++; 4165b7f5c055SJed Brown count = 0; 41669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 41679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 4168b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 4169b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 4170b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 4171b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 4172b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 4173b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 4174b7f5c055SJed Brown 4175b7f5c055SJed Brown if (seen[vIdx]) { 4176b7f5c055SJed Brown PetscInt thisVert; 4177b7f5c055SJed Brown 4178b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 4179b7f5c055SJed Brown 4180b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 4181b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 4182b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 4183b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 4184b7f5c055SJed Brown } 4185b7f5c055SJed Brown } 4186b7f5c055SJed Brown } 4187b7f5c055SJed Brown } 4188b7f5c055SJed Brown } 4189b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 4190b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 4191ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 4192b7f5c055SJed Brown } 4193b7f5c055SJed Brown } 41949566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 41959566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 4196b7f5c055SJed Brown cells_flat = cells[0][0]; 4197b7f5c055SJed Brown numEdges = 0; 4198b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 4199b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 4200b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 4201b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 4202b7f5c055SJed Brown 4203b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 4204b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 4205b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 4206b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 4207b7f5c055SJed Brown } 4208b7f5c055SJed Brown } 4209b7f5c055SJed Brown } 4210b7f5c055SJed Brown } 42119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 42129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 4213b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 4214b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 4215b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 4216b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 4217b7f5c055SJed Brown 4218b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 4219b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 4220b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 4221b7f5c055SJed Brown edges[edge][0] = ev[0]; 4222b7f5c055SJed Brown edges[edge][1] = ev[1]; 4223b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 4224b7f5c055SJed Brown } 4225b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 4226b7f5c055SJed Brown edges[edge][0] = ev[0]; 4227b7f5c055SJed Brown edges[edge][1] = ev[1]; 4228b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 4229b7f5c055SJed Brown } 4230b7f5c055SJed Brown } 4231b7f5c055SJed Brown } 4232b7f5c055SJed Brown } 4233b7f5c055SJed Brown } 4234b7f5c055SJed Brown } 4235b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 42364663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 4237b7f5c055SJed Brown break; 4238b7f5c055SJed Brown } 4239b7f5c055SJed Brown 42409566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 4241c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 42429566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 42439566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 4244b7f5c055SJed Brown { 4245b7f5c055SJed Brown DM idm; 42469566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 424769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 4248b7f5c055SJed Brown } 4249c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 42509566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 42519566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 4252b7f5c055SJed Brown 42539566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 42549566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 4255b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 4256b7f5c055SJed Brown PetscInt njoin; 4257b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 42589566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 425963a3b9bcSJacob Faibussowitsch PetscCheck(njoin == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected unique join of vertices %" PetscInt_FMT " and %" PetscInt_FMT, edges[e][0], edges[e][1]); 42609566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 42619566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 4262b7f5c055SJed Brown } 42639566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 42649566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 42651436d7faSJed Brown if (tps_distribute) { 42661436d7faSJed Brown DM pdm = NULL; 42671436d7faSJed Brown PetscPartitioner part; 42681436d7faSJed Brown 42699566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 42709566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 42719566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 427248a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 42731436d7faSJed Brown // Do not auto-distribute again 42749566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 42751436d7faSJed Brown } 4276b7f5c055SJed Brown 42779566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 4278b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 4279b7f5c055SJed Brown PetscInt m; 4280b7f5c055SJed Brown DM dmf; 4281b7f5c055SJed Brown Vec X; 4282b7f5c055SJed Brown PetscScalar *x; 42839566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 428469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 4285b7f5c055SJed Brown 42869566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 42879566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 42889566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 428948a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 42909566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 4291b7f5c055SJed Brown } 4292b7f5c055SJed Brown 4293b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 42949566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 42959566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 4296b7f5c055SJed Brown 429746139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 429846139095SJed Brown 4299b7f5c055SJed Brown if (thickness > 0) { 43004663dae6SJed Brown DM edm, cdm, ecdm; 43014663dae6SJed Brown DMPlexTransform tr; 43024663dae6SJed Brown const char *prefix; 43034663dae6SJed Brown PetscOptions options; 43044663dae6SJed Brown // Code from DMPlexExtrude 43054663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 43064663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 4307ce78bad3SBarry Smith PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDETYPE)); 43084663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 43094663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 43104663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 43114663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 43124663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 43134663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 43144663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 43154663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 43164663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 43174663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 43184663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 43194663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 43204663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 43214663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 43224663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 43234663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 43244663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 43254663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 43264663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 43274663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 4328a77a5016SMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, edm)); 432969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 4330b7f5c055SJed Brown } 43313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4332b7f5c055SJed Brown } 4333b7f5c055SJed Brown 4334b7f5c055SJed Brown /*@ 4335b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 4336b7f5c055SJed Brown 4337b7f5c055SJed Brown Collective 4338b7f5c055SJed Brown 4339b7f5c055SJed Brown Input Parameters: 4340a1cb98faSBarry Smith + comm - The communicator for the `DM` object 4341b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 4342b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 434320f4b53cSBarry Smith . periodic - array of length 3 with periodicity, or `NULL` for non-periodic 43441436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 4345817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 43461436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 4347817da375SSatish Balay - thickness - Thickness in normal direction 4348b7f5c055SJed Brown 4349b7f5c055SJed Brown Output Parameter: 4350a1cb98faSBarry Smith . dm - The `DM` object 4351a1cb98faSBarry Smith 4352a1cb98faSBarry Smith Level: beginner 4353b7f5c055SJed Brown 4354b7f5c055SJed Brown Notes: 435515229ffcSPierre Jolivet This meshes the surface of the Schwarz P or Gyroid surfaces. Schwarz P is the simplest member of the triply-periodic minimal surfaces. 43561d27aa22SBarry Smith <https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22)> and can be cut with "clean" boundaries. 43571d27aa22SBarry Smith The Gyroid <https://en.wikipedia.org/wiki/Gyroid> is another triply-periodic minimal surface with applications in additive manufacturing; it is much more difficult to "cut" since there are no planes of symmetry. 4358b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 4359b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 4360b7f5c055SJed Brown This projection could readily be extended to related surfaces. 4361b7f5c055SJed Brown 43621d27aa22SBarry Smith See {cite}`maskery2018insights` 43631d27aa22SBarry Smith 43641d27aa22SBarry Smith The face (edge) sets for the Schwarz P surface are numbered $1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z)$. 43651d27aa22SBarry Smith When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). 43661d27aa22SBarry Smith Use `DMPlexLabelComplete()` to propagate to coarse-level vertices. 4367b7f5c055SJed Brown 436860225df5SJacob Faibussowitsch Developer Notes: 4369b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 4370b7f5c055SJed Brown 43711cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 4372b7f5c055SJed Brown @*/ 4373d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateTPSMesh(MPI_Comm comm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness, DM *dm) 4374d71ae5a4SJacob Faibussowitsch { 4375b7f5c055SJed Brown PetscFunctionBegin; 43769566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 43779566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 43789566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 43793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4380b7f5c055SJed Brown } 4381b7f5c055SJed Brown 43829318fe57SMatthew G. Knepley /*@ 43839318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 43849318fe57SMatthew G. Knepley 43859318fe57SMatthew G. Knepley Collective 43869318fe57SMatthew G. Knepley 43879318fe57SMatthew G. Knepley Input Parameters: 4388a1cb98faSBarry Smith + comm - The communicator for the `DM` object 43899318fe57SMatthew G. Knepley . dim - The dimension 43909318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 43919318fe57SMatthew G. Knepley - R - The radius 43929318fe57SMatthew G. Knepley 43939318fe57SMatthew G. Knepley Output Parameter: 4394a1cb98faSBarry Smith . dm - The `DM` object 43959318fe57SMatthew G. Knepley 43969318fe57SMatthew G. Knepley Level: beginner 43979318fe57SMatthew G. Knepley 43981cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 43999318fe57SMatthew G. Knepley @*/ 4400d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 4401d71ae5a4SJacob Faibussowitsch { 44029318fe57SMatthew G. Knepley PetscFunctionBegin; 44034f572ea9SToby Isaac PetscAssertPointer(dm, 5); 44049566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44059566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 44069566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 44073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44089318fe57SMatthew G. Knepley } 44099318fe57SMatthew G. Knepley 4410d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 4411d71ae5a4SJacob Faibussowitsch { 44129318fe57SMatthew G. Knepley DM sdm, vol; 44139318fe57SMatthew G. Knepley DMLabel bdlabel; 4414dd2b43ebSStefano Zampini const char *prefix; 44159318fe57SMatthew G. Knepley 44169318fe57SMatthew G. Knepley PetscFunctionBegin; 44179566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 44189566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 4419dd2b43ebSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 4420dd2b43ebSStefano Zampini PetscCall(DMSetOptionsPrefix(sdm, prefix)); 4421dd2b43ebSStefano Zampini PetscCall(DMAppendOptionsPrefix(sdm, "bd_")); 4422dd2b43ebSStefano Zampini PetscCall(DMPlexDistributeSetDefault(sdm, PETSC_FALSE)); 44239566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 44249566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 44259566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 44269566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 44279566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 442869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 44299566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 44309566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 44319566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 44329566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 44333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 443451a74b61SMatthew G. Knepley } 443551a74b61SMatthew G. Knepley 443651a74b61SMatthew G. Knepley /*@ 443751a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 443851a74b61SMatthew G. Knepley 443951a74b61SMatthew G. Knepley Collective 444051a74b61SMatthew G. Knepley 444151a74b61SMatthew G. Knepley Input Parameters: 4442a1cb98faSBarry Smith + comm - The communicator for the `DM` object 444351a74b61SMatthew G. Knepley . dim - The dimension 444451a74b61SMatthew G. Knepley - R - The radius 444551a74b61SMatthew G. Knepley 444651a74b61SMatthew G. Knepley Output Parameter: 4447a1cb98faSBarry Smith . dm - The `DM` object 444851a74b61SMatthew G. Knepley 4449a1cb98faSBarry Smith Options Database Key: 445060225df5SJacob Faibussowitsch . bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 445151a74b61SMatthew G. Knepley 445251a74b61SMatthew G. Knepley Level: beginner 445351a74b61SMatthew G. Knepley 44541cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 445551a74b61SMatthew G. Knepley @*/ 4456d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 4457d71ae5a4SJacob Faibussowitsch { 445851a74b61SMatthew G. Knepley PetscFunctionBegin; 44599566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44609566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 44619566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 44623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44632829fed8SMatthew G. Knepley } 44642829fed8SMatthew G. Knepley 4465d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 4466d71ae5a4SJacob Faibussowitsch { 44670a6ba040SMatthew G. Knepley PetscFunctionBegin; 44689318fe57SMatthew G. Knepley switch (ct) { 44699371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 44709318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 44719318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 44729318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 44739318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 44749318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 44759318fe57SMatthew G. Knepley 44769566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 44779566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 44789371c9d4SSatish Balay } break; 44799371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 44809318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 44819318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 44829318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 44839318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 44849318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 44859318fe57SMatthew G. Knepley 44869566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 44879566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 44889371c9d4SSatish Balay } break; 44899371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 4490b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 4491b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 4492b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 4493b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 4494b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 4495b5a892a1SMatthew G. Knepley 44969566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 44979566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 44989371c9d4SSatish Balay } break; 44999371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 45009318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 45019318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 45029318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 45039318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 45049318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 45059318fe57SMatthew G. Knepley 45069566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45079566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45089371c9d4SSatish Balay } break; 45099371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 45109318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45119318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 45129318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45139318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 45149318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 45159318fe57SMatthew G. Knepley 45169566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45179566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45189371c9d4SSatish Balay } break; 45199371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 45209318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45219318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 45229318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45239318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 45249318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 45259318fe57SMatthew G. Knepley 45269566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45279566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45289371c9d4SSatish Balay } break; 45299371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 45309318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45319318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 4532f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45339318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 4534f0edb160SMatthew G. Knepley PetscScalar vertexCoords[12] = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0}; 45359318fe57SMatthew G. Knepley 45369566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45379566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45389371c9d4SSatish Balay } break; 45399371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 45409318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 45419318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 4542f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 45439318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 45449371c9d4SSatish Balay PetscScalar vertexCoords[24] = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; 45459318fe57SMatthew G. Knepley 45469566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45479566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45489371c9d4SSatish Balay } break; 45499371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 45509318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 45519318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 4552f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 45539318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 45549371c9d4SSatish Balay PetscScalar vertexCoords[18] = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0}; 45559318fe57SMatthew G. Knepley 45569566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45579566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45589371c9d4SSatish Balay } break; 45599371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 45609318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 45619318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 45629318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 45639318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 45649371c9d4SSatish Balay PetscScalar vertexCoords[18] = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, 1.0, 1.0}; 45659318fe57SMatthew G. Knepley 45669566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45679566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45689371c9d4SSatish Balay } break; 45699371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 45709318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 45719318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 45729318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 45739318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 45749371c9d4SSatish Balay PetscScalar vertexCoords[24] = {-1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; 45759318fe57SMatthew G. Knepley 45769566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45779566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45789371c9d4SSatish Balay } break; 45799371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 45809318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 45819318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 4582f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 45839318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 45849371c9d4SSatish Balay PetscScalar vertexCoords[24] = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 0.0, 0.0, 1.0}; 45859318fe57SMatthew G. Knepley 45869566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45879566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45889371c9d4SSatish Balay } break; 4589d71ae5a4SJacob Faibussowitsch default: 4590d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 45919318fe57SMatthew G. Knepley } 45929318fe57SMatthew G. Knepley { 45939318fe57SMatthew G. Knepley PetscInt Nv, v; 45949318fe57SMatthew G. Knepley 45959318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 45969566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 45979566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 45989566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 45999566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 46009318fe57SMatthew G. Knepley } 46019566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 46029566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 46033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46040a6ba040SMatthew G. Knepley } 46050a6ba040SMatthew G. Knepley 46069318fe57SMatthew G. Knepley /*@ 4607a1cb98faSBarry Smith DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell 46089318fe57SMatthew G. Knepley 46099318fe57SMatthew G. Knepley Collective 46109318fe57SMatthew G. Knepley 46119318fe57SMatthew G. Knepley Input Parameters: 46129318fe57SMatthew G. Knepley + comm - The communicator 46139318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 46149318fe57SMatthew G. Knepley 46159318fe57SMatthew G. Knepley Output Parameter: 46169318fe57SMatthew G. Knepley . refdm - The reference cell 46179318fe57SMatthew G. Knepley 46189318fe57SMatthew G. Knepley Level: intermediate 46199318fe57SMatthew G. Knepley 462042747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()` 46219318fe57SMatthew G. Knepley @*/ 4622d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 4623d71ae5a4SJacob Faibussowitsch { 46240a6ba040SMatthew G. Knepley PetscFunctionBegin; 46259566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 46269566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 46279566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 46283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46299318fe57SMatthew G. Knepley } 463079a015ccSMatthew G. Knepley 4631d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 4632d71ae5a4SJacob Faibussowitsch { 46339318fe57SMatthew G. Knepley DM plex; 46349318fe57SMatthew G. Knepley DMLabel label; 46359318fe57SMatthew G. Knepley PetscBool hasLabel; 46360a6ba040SMatthew G. Knepley 4637c22d3578SMatthew G. Knepley PetscFunctionBegin; 46389566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 46393ba16761SJacob Faibussowitsch if (hasLabel) PetscFunctionReturn(PETSC_SUCCESS); 46409566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 46419566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 46429566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 46439566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 46441c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 46459566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 46463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46479318fe57SMatthew G. Knepley } 4648acdc6f61SToby Isaac 4649669647acSMatthew G. Knepley /* 4650669647acSMatthew G. Knepley We use the last coordinate as the radius, the inner radius is lower[dim-1] and the outer radius is upper[dim-1]. Then we map the first coordinate around the circle. 4651669647acSMatthew G. Knepley 4652669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 4653669647acSMatthew G. Knepley */ 4654d71ae5a4SJacob Faibussowitsch static void boxToAnnulus(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 4655d71ae5a4SJacob Faibussowitsch { 4656669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 4657669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 4658669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 4659669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 4660669647acSMatthew G. Knepley 4661669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 4662669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 4663669647acSMatthew G. Knepley } 4664669647acSMatthew G. Knepley 46655390be7dSMatthew G. Knepley // Insert vertices and their joins, marked by depth 46665390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Vertices(DM dm, DMLabel label, DMLabel vlabel, PetscInt val, PetscInt n, const PetscInt vertices[]) 46675390be7dSMatthew G. Knepley { 46685390be7dSMatthew G. Knepley PetscFunctionBegin; 46695390be7dSMatthew G. Knepley PetscCall(DMPlexMarkSubmesh_Interpolated(dm, vlabel, val, PETSC_FALSE, PETSC_FALSE, label, NULL)); 46705390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 46715390be7dSMatthew G. Knepley } 46725390be7dSMatthew G. Knepley 46735390be7dSMatthew G. Knepley // Insert faces and their closures, marked by depth 46745390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Faces(DM dm, DMLabel label, PetscInt n, const PetscInt faces[]) 46755390be7dSMatthew G. Knepley { 46765390be7dSMatthew G. Knepley PetscFunctionBegin; 46775390be7dSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) { 46785390be7dSMatthew G. Knepley const PetscInt point = faces[p]; 46795390be7dSMatthew G. Knepley PetscInt *closure = NULL; 46805390be7dSMatthew G. Knepley PetscInt clSize, pdepth; 46815390be7dSMatthew G. Knepley 46825390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, point, &pdepth)); 46835390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, point, pdepth)); 46845390be7dSMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 46855390be7dSMatthew G. Knepley for (PetscInt cl = 0; cl < clSize * 2; cl += 2) { 46865390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, closure[cl], &pdepth)); 46875390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, closure[cl], pdepth)); 46885390be7dSMatthew G. Knepley } 46895390be7dSMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 46905390be7dSMatthew G. Knepley } 46915390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 46925390be7dSMatthew G. Knepley } 46935390be7dSMatthew G. Knepley 46944e22dd4cSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *flg); 46954e22dd4cSMatthew G. Knepley 46965dca41c3SJed Brown const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "zbox", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 46979318fe57SMatthew G. Knepley 4698ce78bad3SBarry Smith static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 4699d71ae5a4SJacob Faibussowitsch { 47009318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 47019318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 47029318fe57SMatthew G. Knepley PetscInt dim = 2; 4703b9da1bb3SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, orient = PETSC_FALSE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 4704d0812dedSMatthew G. Knepley PetscBool flg, flg2, fflg, strflg, bdfflg, nameflg; 47059318fe57SMatthew G. Knepley MPI_Comm comm; 4706ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4707ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4708ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 47094e22dd4cSMatthew G. Knepley const char *option; 47109318fe57SMatthew G. Knepley 47119318fe57SMatthew G. Knepley PetscFunctionBegin; 4712708be2fdSJed Brown PetscCall(PetscLogEventBegin(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 47139566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 47149318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 47159566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 4716d0812dedSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_file_contents", "Contents of a file format in a string", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &strflg)); 47179566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 47189566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 47199566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 47209566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 47219566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 47229566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 47239566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 47249566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 4725b9da1bb3SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_orient", "Orient the constructed mesh", "DMPlexOrient", orient, &orient, &flg)); 47269566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 47279566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 47289566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 47293f3e541fSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_adj", "Debug output level all adjacency computations", "", 0, &((DM_Plex *)dm->data)->printAdj, NULL, 0)); 47309318fe57SMatthew G. Knepley 473161a622f3SMatthew G. Knepley switch (cell) { 473261a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 473361a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 473461a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 473561a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 473661a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 473761a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 4738d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 4739d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_TRUE; 4740d71ae5a4SJacob Faibussowitsch break; 4741d71ae5a4SJacob Faibussowitsch default: 4742d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_FALSE; 4743d71ae5a4SJacob Faibussowitsch break; 474461a622f3SMatthew G. Knepley } 474561a622f3SMatthew G. Knepley 47469318fe57SMatthew G. Knepley if (fflg) { 47479318fe57SMatthew G. Knepley DM dmnew; 47481e4a82c4SMatthew G. Knepley const char *name; 47499318fe57SMatthew G. Knepley 47501e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 47511e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, nameflg ? plexname : name, interpolate, &dmnew)); 47525de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 475369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 47549318fe57SMatthew G. Knepley } else if (refDomain) { 47559566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 47569318fe57SMatthew G. Knepley } else if (bdfflg) { 47579318fe57SMatthew G. Knepley DM bdm, dmnew; 47581e4a82c4SMatthew G. Knepley const char *name; 47599318fe57SMatthew G. Knepley 47601e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 47611e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, nameflg ? plexname : name, interpolate, &bdm)); 47629566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 47639566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 47649566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 47659566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 47665de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 476769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 4768d0812dedSMatthew G. Knepley } else if (strflg) { 4769d0812dedSMatthew G. Knepley DM dmnew; 4770d0812dedSMatthew G. Knepley PetscViewer viewer; 4771d0812dedSMatthew G. Knepley const char *contents; 4772d0812dedSMatthew G. Knepley char *strname; 4773d0812dedSMatthew G. Knepley char tmpdir[PETSC_MAX_PATH_LEN]; 4774d0812dedSMatthew G. Knepley char tmpfilename[PETSC_MAX_PATH_LEN]; 4775d0812dedSMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 4776d0812dedSMatthew G. Knepley MPI_Comm comm; 4777d0812dedSMatthew G. Knepley PetscMPIInt rank; 4778d0812dedSMatthew G. Knepley 4779d0812dedSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4780d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 4781d0812dedSMatthew G. Knepley PetscCall(PetscStrchr(filename, ':', &strname)); 4782d0812dedSMatthew G. Knepley PetscCheck(strname, comm, PETSC_ERR_ARG_WRONG, "File contents must have the form \"ext:string_name\", not %s", filename); 4783d0812dedSMatthew G. Knepley strname[0] = '\0'; 4784d0812dedSMatthew G. Knepley ++strname; 4785d0812dedSMatthew G. Knepley PetscCall(PetscDLSym(NULL, strname, (void **)&contents)); 4786d0812dedSMatthew G. Knepley PetscCheck(contents, comm, PETSC_ERR_ARG_WRONG, "Could not locate mesh string %s", strname); 4787d0812dedSMatthew G. Knepley PetscCall(PetscGetTmp(comm, tmpdir, PETSC_MAX_PATH_LEN)); 4788ed32af8cSMatthew G. Knepley PetscCall(PetscStrlcat(tmpdir, "/meshXXXXXX", PETSC_MAX_PATH_LEN)); 4789ed32af8cSMatthew G. Knepley PetscCall(PetscMkdtemp(tmpdir)); 4790ed32af8cSMatthew G. Knepley PetscCall(PetscSNPrintf(tmpfilename, PETSC_MAX_PATH_LEN, "%s/mesh.%s", tmpdir, filename)); 4791d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIOpen(comm, tmpfilename, &viewer)); 4792d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", contents)); 4793d0812dedSMatthew G. Knepley PetscCall(PetscViewerDestroy(&viewer)); 4794d0812dedSMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), tmpfilename, plexname, interpolate, &dmnew)); 4795ed32af8cSMatthew G. Knepley PetscCall(PetscRMTree(tmpdir)); 4796d0812dedSMatthew G. Knepley PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%s Mesh", strname)); 4797d0812dedSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, name)); 4798d0812dedSMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 4799d0812dedSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 48009318fe57SMatthew G. Knepley } else { 48019566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 48029318fe57SMatthew G. Knepley switch (shape) { 4803669647acSMatthew G. Knepley case DM_SHAPE_BOX: 48045dca41c3SJed Brown case DM_SHAPE_ZBOX: 4805669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 48069318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 48079318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 48089318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 48099318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4810669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 48119318fe57SMatthew G. Knepley PetscInt i, n; 48129318fe57SMatthew G. Knepley 48139318fe57SMatthew G. Knepley n = dim; 48149318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 48159566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 48169318fe57SMatthew G. Knepley n = 3; 48179566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 481863a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 48199318fe57SMatthew G. Knepley n = 3; 48209566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 482163a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 48229318fe57SMatthew G. Knepley n = 3; 48239566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 482463a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 4825669647acSMatthew G. Knepley 4826669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 4827669647acSMatthew G. Knepley if (isAnnular) 4828669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 4829669647acSMatthew G. Knepley 48309318fe57SMatthew G. Knepley switch (cell) { 483161a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 48329566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 4833d410b0cfSMatthew G. Knepley if (!interpolate) { 4834d410b0cfSMatthew G. Knepley DM udm; 4835d410b0cfSMatthew G. Knepley 48369566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 483769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 4838d410b0cfSMatthew G. Knepley } 48399318fe57SMatthew G. Knepley break; 4840d71ae5a4SJacob Faibussowitsch default: 48415dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(dm, shape, dim, simplex, faces, lower, upper, bdt, interpolate)); 4842d71ae5a4SJacob Faibussowitsch break; 48439318fe57SMatthew G. Knepley } 4844669647acSMatthew G. Knepley if (isAnnular) { 4845669647acSMatthew G. Knepley DM cdm; 4846669647acSMatthew G. Knepley PetscDS cds; 4847669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 4848669647acSMatthew G. Knepley 4849669647acSMatthew G. Knepley // Fix coordinates for annular region 4850669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 4851669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 4852669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 4853e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL)); 4854669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 4855669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 4856669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 4857669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 4858669647acSMatthew G. Knepley } 48599371c9d4SSatish Balay } break; 48609371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 48619318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 48629318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 48639318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 48649318fe57SMatthew G. Knepley PetscInt i, n; 48659318fe57SMatthew G. Knepley 48669318fe57SMatthew G. Knepley n = dim + 1; 48679318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 48689566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 48699318fe57SMatthew G. Knepley n = 3; 48709566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 487163a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim + 1), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim + 1); 48729318fe57SMatthew G. Knepley n = 3; 48739566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 487463a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim + 1), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim + 1); 48759566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 48769371c9d4SSatish Balay } break; 48779371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 48789318fe57SMatthew G. Knepley PetscReal R = 1.0; 48799318fe57SMatthew G. Knepley 48809566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 48819566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 48829371c9d4SSatish Balay } break; 48839371c9d4SSatish Balay case DM_SHAPE_BALL: { 48849318fe57SMatthew G. Knepley PetscReal R = 1.0; 48859318fe57SMatthew G. Knepley 48869566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 48879566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 48889371c9d4SSatish Balay } break; 48899371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 48909318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 48919318fe57SMatthew G. Knepley PetscInt Nw = 6; 489249704ca5SMatthew G. Knepley PetscInt Nr = 0; 48939318fe57SMatthew G. Knepley 48949566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 48959566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 489649704ca5SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_refine", "Number of refinements before projection", "", Nr, &Nr, NULL)); 48979318fe57SMatthew G. Knepley switch (cell) { 4898d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_TRI_PRISM_TENSOR: 4899d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 4900d71ae5a4SJacob Faibussowitsch break; 4901d71ae5a4SJacob Faibussowitsch default: 490249704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt, Nr)); 4903d71ae5a4SJacob Faibussowitsch break; 49049318fe57SMatthew G. Knepley } 49059371c9d4SSatish Balay } break; 4906b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 49079371c9d4SSatish Balay case DM_SHAPE_GYROID: { 4908b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 4909b7f5c055SJed Brown PetscReal thickness = 0.; 4910b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4911b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 49121436d7faSJed Brown PetscBool tps_distribute; 49139566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 49149566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 49159566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 49169566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 49179566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 49189566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 49199566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 49209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 49219371c9d4SSatish Balay } break; 49229371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 492305bd46c0SStefano Zampini DM dmnew; 492405bd46c0SStefano Zampini PetscReal rl = 0.0; 492505bd46c0SStefano Zampini 492605bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 492705bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 49285de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 492969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 49309371c9d4SSatish Balay } break; 4931cfb853baSMatthew G. Knepley case DM_SHAPE_HYPERCUBIC: { 49328d2ec52aSSatish Balay PetscInt *edges, overlap = 1; 4933cfb853baSMatthew G. Knepley PetscReal *lower, *upper; 4934cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 4935cfb853baSMatthew G. Knepley PetscInt n, d; 4936cfb853baSMatthew G. Knepley 4937cfb853baSMatthew G. Knepley *useCoordSpace = PETSC_FALSE; 4938cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt)); 4939cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 4940cfb853baSMatthew G. Knepley edges[d] = 1; 4941cfb853baSMatthew G. Knepley lower[d] = 0.; 4942cfb853baSMatthew G. Knepley upper[d] = 1.; 4943cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 4944cfb853baSMatthew G. Knepley } 4945cfb853baSMatthew G. Knepley n = dim; 4946cfb853baSMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg)); 4947cfb853baSMatthew G. Knepley n = dim; 4948cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 4949cfb853baSMatthew G. Knepley PetscCheck(!flg || n == dim, comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 4950cfb853baSMatthew G. Knepley n = dim; 4951cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 4952cfb853baSMatthew G. Knepley PetscCheck(!flg || n == dim, comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 4953cfb853baSMatthew G. Knepley n = dim; 4954cfb853baSMatthew G. Knepley PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 4955cfb853baSMatthew G. Knepley PetscCheck(!flg || n == dim, comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 49568d2ec52aSSatish Balay PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", overlap, &overlap, NULL, 0)); 49578d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, overlap, bdt)); 4958cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edges, lower, upper, bdt)); 4959cfb853baSMatthew G. Knepley } break; 4960d71ae5a4SJacob Faibussowitsch default: 4961d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 49629318fe57SMatthew G. Knepley } 49639318fe57SMatthew G. Knepley } 49649566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 496548a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 4966b9da1bb3SMatthew G. Knepley if (orient) PetscCall(DMPlexOrient(dm)); 49674e22dd4cSMatthew G. Knepley // Allow label creation 49684e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_label_", &option, NULL, &flg)); 49694e22dd4cSMatthew G. Knepley if (flg) { 49704e22dd4cSMatthew G. Knepley DMLabel label; 49714e22dd4cSMatthew G. Knepley PetscInt points[1024], n = 1024; 49724e22dd4cSMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 49734e22dd4cSMatthew G. Knepley const char *name = &option[14]; 49744e22dd4cSMatthew G. Knepley 49754e22dd4cSMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 49764e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 49774e22dd4cSMatthew G. Knepley fulloption[0] = '-'; 49784e22dd4cSMatthew G. Knepley fulloption[1] = 0; 49794e22dd4cSMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, option, PETSC_MAX_PATH_LEN)); 49804e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, NULL)); 49814e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) PetscCall(DMLabelSetValue(label, points[p], 1)); 49824e22dd4cSMatthew G. Knepley } 4983dd0eeac9SMatthew G. Knepley // Allow cohesive label creation 4984dd0eeac9SMatthew G. Knepley // Faces are input, completed, and all points are marked with their depth 4985dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_cohesive_label_", &option, NULL, &flg)); 4986dd0eeac9SMatthew G. Knepley if (flg) { 4987dd0eeac9SMatthew G. Knepley DMLabel label; 4988dd0eeac9SMatthew G. Knepley PetscInt points[1024], n, pStart, pEnd, Nl = 1; 49895390be7dSMatthew G. Knepley PetscBool noCreate = PETSC_FALSE; 4990dd0eeac9SMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 4991dd0eeac9SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 4992dd0eeac9SMatthew G. Knepley size_t len; 4993dd0eeac9SMatthew G. Knepley 4994dd0eeac9SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4995dd0eeac9SMatthew G. Knepley PetscCall(PetscStrncpy(name, &option[23], PETSC_MAX_PATH_LEN)); 4996dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlen(name, &len)); 4997dd0eeac9SMatthew G. Knepley if (name[len - 1] == '0') Nl = 10; 4998dd0eeac9SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 49996497c311SBarry Smith if (l > 0) name[len - 1] = (char)('0' + l); 5000dd0eeac9SMatthew G. Knepley fulloption[0] = 0; 5001dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, "-dm_plex_cohesive_label_", 32)); 5002dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, name, PETSC_MAX_PATH_LEN - 32)); 5003dd0eeac9SMatthew G. Knepley n = 1024; 5004dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, &flg)); 5005dd0eeac9SMatthew G. Knepley if (!flg) break; 50065390be7dSMatthew G. Knepley PetscCall(DMHasLabel(dm, name, &noCreate)); 50075390be7dSMatthew G. Knepley if (noCreate) { 50085390be7dSMatthew G. Knepley DMLabel inlabel; 50095390be7dSMatthew G. Knepley IS pointIS; 50105390be7dSMatthew G. Knepley const PetscInt *lpoints; 50115390be7dSMatthew G. Knepley PetscInt pdep, ln, inval = points[0]; 50125390be7dSMatthew G. Knepley char newname[PETSC_MAX_PATH_LEN]; 50135390be7dSMatthew G. Knepley 50145390be7dSMatthew G. Knepley PetscCheck(n == 1, comm, PETSC_ERR_ARG_WRONG, "Must specify a label value with this option"); 50155390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &inlabel)); 50165390be7dSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(inlabel, inval, &pointIS)); 50175390be7dSMatthew G. Knepley PetscCall(ISGetLocalSize(pointIS, &ln)); 50185390be7dSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &lpoints)); 50195390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, lpoints[0], &pdep)); 50205390be7dSMatthew G. Knepley PetscCall(PetscSNPrintf(newname, PETSC_MAX_PATH_LEN, "%s%" PetscInt_FMT, name, points[0])); 50215390be7dSMatthew G. Knepley PetscCall(DMCreateLabel(dm, newname)); 50225390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, newname, &label)); 50235390be7dSMatthew G. Knepley if (!pdep) PetscCall(ProcessCohesiveLabel_Vertices(dm, label, inlabel, inval, ln, lpoints)); 50245390be7dSMatthew G. Knepley else PetscCall(ProcessCohesiveLabel_Faces(dm, label, ln, lpoints)); 50255390be7dSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &lpoints)); 50265390be7dSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 50275390be7dSMatthew G. Knepley } else { 5028dd0eeac9SMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 5029dd0eeac9SMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 5030dd0eeac9SMatthew G. Knepley if (pStart >= pEnd) n = 0; 50315390be7dSMatthew G. Knepley PetscCall(ProcessCohesiveLabel_Faces(dm, label, n, points)); 5032dd0eeac9SMatthew G. Knepley } 5033dd0eeac9SMatthew G. Knepley PetscCall(DMPlexOrientLabel(dm, label)); 50340542aa8cSMatthew G. Knepley PetscCall(DMPlexLabelCohesiveComplete(dm, label, NULL, 1, PETSC_FALSE, PETSC_FALSE, NULL)); 5035dd0eeac9SMatthew G. Knepley } 5036dd0eeac9SMatthew G. Knepley } 50375390be7dSMatthew G. Knepley PetscCall(DMViewFromOptions(dm, NULL, "-created_dm_view")); 5038708be2fdSJed Brown PetscCall(PetscLogEventEnd(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 50393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50400a6ba040SMatthew G. Knepley } 50410a6ba040SMatthew G. Knepley 5042ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems PetscOptionsObject) 5043d71ae5a4SJacob Faibussowitsch { 50440a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 50457f9d8d6cSVaclav Hapla PetscBool flg, flg2; 50469318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 5047adc21957SMatthew G. Knepley char method[PETSC_MAX_PATH_LEN]; 50480a6ba040SMatthew G. Knepley 50490a6ba040SMatthew G. Knepley PetscFunctionBegin; 50500a6ba040SMatthew G. Knepley /* Handle viewing */ 50519566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 50525962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level for all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 50535962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fvm", "Debug output level for all fvm computations", "DMPlexSNESComputeResidualFVM", 0, &mesh->printFVM, NULL, 0)); 50549566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 50559566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 5056f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 5057a77a5016SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_project", "Debug output level all projection computations", "DMPlexProject", 0, &mesh->printProject, NULL, 0)); 50589566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 50599566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 50605e2c5519SMatthew G. Knepley // Interpolation 50615e2c5519SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_interpolate_prefer_tensor", "When different orderings exist, prefer the tensor order", "DMPlexSetInterpolationPreferTensor", mesh->interpolatePreferTensor, &mesh->interpolatePreferTensor, NULL)); 50629318fe57SMatthew G. Knepley /* Labeling */ 50639566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 50649566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 5065953fc75cSMatthew G. Knepley /* Point Location */ 50669566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 50670848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 50689566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 5069d02c7345SMatthew G. Knepley /* Reordering */ 5070adc21957SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_reorder_section", "Compute point permutation for local section", "DMReorderSectionSetDefault", PETSC_FALSE, &flg2, &flg)); 5071adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetDefault(dm, flg2 ? DM_REORDER_DEFAULT_TRUE : DM_REORDER_DEFAULT_FALSE)); 5072adc21957SMatthew G. Knepley PetscCall(PetscOptionsString("-dm_reorder_section_type", "Reordering method for local section", "DMReorderSectionSetType", method, method, PETSC_MAX_PATH_LEN, &flg)); 5073adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetType(dm, method)); 50742e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 50759566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 5076b29cfa1cSToby Isaac /* Projection behavior */ 5077d5b43468SJose E. Roman PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 50789566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 5079f12cf164SMatthew G. Knepley /* Checking structure */ 5080f12cf164SMatthew G. Knepley { 50817f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 5082f12cf164SMatthew G. Knepley 50837f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 50847f9d8d6cSVaclav Hapla if (all) { 50857f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 50867f9d8d6cSVaclav Hapla } else { 50879566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 50887f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 50899566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_skeleton", "Check that each cell has the correct number of vertices (only for homogeneous simplex or tensor meshes)", "DMPlexCheckSkeleton", PETSC_FALSE, &flg, &flg2)); 50907f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 50919566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_faces", "Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type", "DMPlexCheckFaces", PETSC_FALSE, &flg, &flg2)); 50927f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 50939566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 50947f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 50959566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 5096d7d32a9aSMatthew G. Knepley if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 50979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_interface_cones", "Check points on inter-partition interfaces have conforming order of cone points", "DMPlexCheckInterfaceCones", PETSC_FALSE, &flg, &flg2)); 50987f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 50997f9d8d6cSVaclav Hapla } 51009566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 51019566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 5102f12cf164SMatthew G. Knepley } 51039318fe57SMatthew G. Knepley { 51049318fe57SMatthew G. Knepley PetscReal scale = 1.0; 51054f3833eaSMatthew G. Knepley 51069566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 51079318fe57SMatthew G. Knepley if (flg) { 51089318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 51099318fe57SMatthew G. Knepley 51109566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 51119566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 51129566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 51139566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 51149318fe57SMatthew G. Knepley } 51159318fe57SMatthew G. Knepley } 51169566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 51173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 511868d4fef7SMatthew G. Knepley } 511968d4fef7SMatthew G. Knepley 5120ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems PetscOptionsObject, PetscInt *overlap) 5121d71ae5a4SJacob Faibussowitsch { 5122c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 5123c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 5124c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 5125c506a872SMatthew G. Knepley PetscBool flg; 5126c506a872SMatthew G. Knepley 5127c506a872SMatthew G. Knepley PetscFunctionBegin; 5128c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 5129c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 5130c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 5131c506a872SMatthew G. Knepley if (numOvLabels) { 5132c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 5133c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 5134c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 5135c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 5136c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 5137c506a872SMatthew G. Knepley } 5138c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 5139c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 5140c506a872SMatthew G. Knepley PetscCheck(numOvLabels == numOvValues, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "The number of labels %" PetscInt_FMT " must match the number of values %" PetscInt_FMT, numOvLabels, numOvValues); 5141c506a872SMatthew G. Knepley 5142c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 5143c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 5144c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 5145c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 5146c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 5147c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 5148c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 5149c506a872SMatthew G. Knepley } 5150c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 5151c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 5152c506a872SMatthew G. Knepley PetscCheck(numOvExLabels == numOvExValues, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "The number of exclude labels %" PetscInt_FMT " must match the number of values %" PetscInt_FMT, numOvExLabels, numOvExValues); 5153c506a872SMatthew G. Knepley } 51543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5155c506a872SMatthew G. Knepley } 5156c506a872SMatthew G. Knepley 5157ce78bad3SBarry Smith static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems PetscOptionsObject) 5158d71ae5a4SJacob Faibussowitsch { 5159bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 5160bdf63967SMatthew G. Knepley char oname[256]; 51614e22dd4cSMatthew G. Knepley char sublabelname[PETSC_MAX_PATH_LEN] = ""; 5162adc21957SMatthew G. Knepley DMReorderDefaultFlag reorder; 5163d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 51649318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 51651b742f01SMatthew G. Knepley PetscBool uniformOrig = PETSC_FALSE, created = PETSC_FALSE, uniform = PETSC_TRUE, distribute, saveSF = PETSC_FALSE, interpolate = PETSC_TRUE, coordSpace = PETSC_TRUE, remap = PETSC_TRUE, ghostCells = PETSC_FALSE, isHierarchy, flg; 516668d4fef7SMatthew G. Knepley 516768d4fef7SMatthew G. Knepley PetscFunctionBegin; 5168d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 5169dd4c3f67SMatthew G. Knepley if (dm->cloneOpts) goto non_refine; 51709318fe57SMatthew G. Knepley /* Handle automatic creation */ 51719566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 51726bc1bd01Sksagiyam if (dim < 0) { 51736bc1bd01Sksagiyam PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 51746bc1bd01Sksagiyam created = PETSC_TRUE; 51756bc1bd01Sksagiyam } 51766bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 5177d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 51789566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 5179d89e6e46SMatthew G. Knepley if (flg) { 5180d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 5181d89e6e46SMatthew G. Knepley 51829566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 5183d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 5184d89e6e46SMatthew G. Knepley DM udm; 5185d89e6e46SMatthew G. Knepley 51869566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 518769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 5188d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 5189d89e6e46SMatthew G. Knepley DM idm; 5190d89e6e46SMatthew G. Knepley 51919566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 519269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 5193d89e6e46SMatthew G. Knepley } 5194d89e6e46SMatthew G. Knepley } 51954e22dd4cSMatthew G. Knepley // Handle submesh selection before distribution 51964e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_submesh", "Label to use for submesh selection", "", sublabelname, sublabelname, PETSC_MAX_PATH_LEN, &flg)); 51974e22dd4cSMatthew G. Knepley if (flg) { 51984e22dd4cSMatthew G. Knepley DM subdm; 51994e22dd4cSMatthew G. Knepley DMLabel label; 52004e22dd4cSMatthew G. Knepley IS valueIS, pointIS; 52014e22dd4cSMatthew G. Knepley const PetscInt *values, *points; 52024e22dd4cSMatthew G. Knepley PetscBool markedFaces = PETSC_FALSE; 52034e22dd4cSMatthew G. Knepley PetscInt Nv, value, Np; 52044e22dd4cSMatthew G. Knepley 52054e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, sublabelname, &label)); 52064e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &Nv)); 52074e22dd4cSMatthew G. Knepley PetscCheck(Nv == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Only a single label value is currently supported for submesh selection, not %" PetscInt_FMT, Nv); 52084e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetValueIS(label, &valueIS)); 52094e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &values)); 52104e22dd4cSMatthew G. Knepley value = values[0]; 52114e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(valueIS, &values)); 52124e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 52134e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumSize(label, value, &Np)); 52144e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, value, &pointIS)); 52154e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &points)); 52164e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 52174e22dd4cSMatthew G. Knepley PetscInt pdepth; 52184e22dd4cSMatthew G. Knepley 52194e22dd4cSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, points[p], &pdepth)); 52204e22dd4cSMatthew G. Knepley if (pdepth) { 52214e22dd4cSMatthew G. Knepley markedFaces = PETSC_TRUE; 52224e22dd4cSMatthew G. Knepley break; 52234e22dd4cSMatthew G. Knepley } 52244e22dd4cSMatthew G. Knepley } 52254e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &points)); 52264e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 52274e22dd4cSMatthew G. Knepley PetscCall(DMPlexCreateSubmesh(dm, label, value, markedFaces, &subdm)); 52284e22dd4cSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &subdm)); 52294e22dd4cSMatthew G. Knepley PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 52304e22dd4cSMatthew G. Knepley } 52319b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 52329566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 52339566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 52349566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 52359566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 52369566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 52379566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 52389318fe57SMatthew G. Knepley if (flg) { 52399566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 52409566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 52419318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 52429318fe57SMatthew G. Knepley } 5243b23db253SStefano Zampini if (prerefine) PetscCall(DMLocalizeCoordinates(dm)); 52449b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 52459b44eab4SMatthew G. Knepley DM rdm; 52469b44eab4SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 52479b44eab4SMatthew G. Knepley 5248dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 52499566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 525069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 5251dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 525261a622f3SMatthew G. Knepley if (coordFunc && remap) { 52539566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 52549b44eab4SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 52559b44eab4SMatthew G. Knepley } 52569b44eab4SMatthew G. Knepley } 52579566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 52589318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 52599566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 52609318fe57SMatthew G. Knepley if (extLayers) { 52619318fe57SMatthew G. Knepley DM edm; 52629318fe57SMatthew G. Knepley 52639566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 526469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 526548d16a33SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = NULL; 5266dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5267d410b0cfSMatthew G. Knepley extLayers = 0; 52685e17fc22SAidan Hamilton PetscCall(DMGetDimension(dm, &dim)); 52699318fe57SMatthew G. Knepley } 5270bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 52716bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 52729566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 52736bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 52749566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 5275adc21957SMatthew G. Knepley if (reorder == DM_REORDER_DEFAULT_TRUE || flg) { 5276bdf63967SMatthew G. Knepley DM pdm; 5277bdf63967SMatthew G. Knepley IS perm; 5278bdf63967SMatthew G. Knepley 52799566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 52809566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 52819566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 528269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 5283dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5284bdf63967SMatthew G. Knepley } 52859b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 52869566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 5287c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 5288a286e215SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute_save_sf", "Flag to save the migration SF", "DMPlexSetMigrationSF", saveSF, &saveSF, NULL)); 5289dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 52909b44eab4SMatthew G. Knepley if (distribute) { 52919b44eab4SMatthew G. Knepley DM pdm = NULL; 52929b44eab4SMatthew G. Knepley PetscPartitioner part; 5293a286e215SMatthew G. Knepley PetscSF sfMigration; 52949b44eab4SMatthew G. Knepley 52959566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 52969566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 5297a286e215SMatthew G. Knepley PetscCall(DMPlexDistribute(dm, overlap, &sfMigration, &pdm)); 52985d2873a6SJames Wright if (pdm) { 52995d2873a6SJames Wright // Delete the local section to force the existing one to be rebuilt with the distributed DM 53005d2873a6SJames Wright PetscCall(DMSetLocalSection(dm, pdm->localSection)); 53015d2873a6SJames Wright PetscCall(DMPlexReplace_Internal(dm, &pdm)); 53025d2873a6SJames Wright } 5303a286e215SMatthew G. Knepley if (saveSF) PetscCall(DMPlexSetMigrationSF(dm, sfMigration)); 5304a286e215SMatthew G. Knepley PetscCall(PetscSFDestroy(&sfMigration)); 53059b44eab4SMatthew G. Knepley } 53064054ae39SJames Wright 53074054ae39SJames Wright { 53084054ae39SJames Wright PetscBool useBoxLabel = PETSC_FALSE; 53094054ae39SJames Wright PetscCall(PetscOptionsBool("-dm_plex_box_label", "Create 'Face Sets' assuming boundary faces align with cartesian directions", "DMCreate", useBoxLabel, &useBoxLabel, NULL)); 5310d7d2d1d2SJames Wright if (useBoxLabel) { 5311d7d2d1d2SJames Wright PetscInt n = 3; 5312d7d2d1d2SJames Wright DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 5313d7d2d1d2SJames Wright 5314d7d2d1d2SJames Wright PetscCall(PetscOptionsEnumArray("-dm_plex_box_label_bd", "Boundary type for each dimension when using -dm_plex_box_label", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 5315d7d2d1d2SJames Wright PetscCheck(!flg || !(n != dim), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 5316d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, bdt)); 5317d7d2d1d2SJames Wright } 53184054ae39SJames Wright } 5319d2b2dc1eSMatthew G. Knepley /* Must check CEED options before creating function space for coordinates */ 5320d2b2dc1eSMatthew G. Knepley { 5321d2b2dc1eSMatthew G. Knepley PetscBool useCeed = PETSC_FALSE, flg; 5322d2b2dc1eSMatthew G. Knepley 5323d2b2dc1eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_use_ceed", "Use LibCEED as the FEM backend", "DMPlexSetUseCeed", useCeed, &useCeed, &flg)); 5324d2b2dc1eSMatthew G. Knepley if (flg) PetscCall(DMPlexSetUseCeed(dm, useCeed)); 5325d2b2dc1eSMatthew G. Knepley } 53269318fe57SMatthew G. Knepley /* Create coordinate space */ 53279318fe57SMatthew G. Knepley if (created) { 532861a622f3SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5329e44f6aebSMatthew G. Knepley PetscInt degree = 1, deg; 53305515ebd3SMatthew G. Knepley PetscInt height = 0; 53315515ebd3SMatthew G. Knepley DM cdm; 5332c3db174cSMatthew G. Knepley PetscBool flg, localize = PETSC_TRUE, sparseLocalize = PETSC_TRUE; 53339318fe57SMatthew G. Knepley 53349566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, &flg)); 53359566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 5336e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDegree_Internal(dm, °)); 5337e44f6aebSMatthew G. Knepley if (coordSpace && deg <= 1) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_TRUE, mesh->coordFunc)); 53385515ebd3SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 533961a622f3SMatthew G. Knepley if (flg && !coordSpace) { 534061a622f3SMatthew G. Knepley PetscDS cds; 534161a622f3SMatthew G. Knepley PetscObject obj; 534261a622f3SMatthew G. Knepley PetscClassId id; 534361a622f3SMatthew G. Knepley 53449566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 53459566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 53469566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 534761a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 534861a622f3SMatthew G. Knepley PetscContainer dummy; 534961a622f3SMatthew G. Knepley 53509566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 53519566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 53529566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 53539566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 53549566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 535561a622f3SMatthew G. Knepley } 535661a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 535761a622f3SMatthew G. Knepley } 5358c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_localize", "Localize mesh coordinates", "", localize, &localize, NULL)); 5359c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "DMSetSparseLocalize", sparseLocalize, &sparseLocalize, &flg)); 5360c3db174cSMatthew G. Knepley if (flg) PetscCall(DMSetSparseLocalize(dm, sparseLocalize)); 53615515ebd3SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg)); 53625515ebd3SMatthew G. Knepley if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height)); 5363c3db174cSMatthew G. Knepley if (localize) PetscCall(DMLocalizeCoordinates(dm)); 53649318fe57SMatthew G. Knepley } 536568d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 536661a622f3SMatthew G. Knepley remap = PETSC_TRUE; 53679566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 53689566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 53699566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 53709566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 537168d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 5372acdc6f61SToby Isaac DM *dms, coarseDM; 537368d4fef7SMatthew G. Knepley 53749566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 53759566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 53769566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 53779566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 537868d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 53799566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 538068d4fef7SMatthew G. Knepley if (refine == 1) { 53819566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 53829566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 538368d4fef7SMatthew G. Knepley } else { 53849566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 53859566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 53869566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 53879566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 538868d4fef7SMatthew G. Knepley } 53899566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 53909566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 539168d4fef7SMatthew G. Knepley /* Free DMs */ 539268d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 5393dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 53949566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 539568d4fef7SMatthew G. Knepley } 53969566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 539768d4fef7SMatthew G. Knepley } else { 539868d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 53999318fe57SMatthew G. Knepley DM rdm; 540051a74b61SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 540168d4fef7SMatthew G. Knepley 5402dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54039566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 540468d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 540569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 5406dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 540761a622f3SMatthew G. Knepley if (coordFunc && remap) { 54089566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 540951a74b61SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 541051a74b61SMatthew G. Knepley } 541168d4fef7SMatthew G. Knepley } 541268d4fef7SMatthew G. Knepley } 54133cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 54149566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 54159566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 5416b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 5417b653a561SMatthew G. Knepley DM *dms; 5418b653a561SMatthew G. Knepley 54199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 54209566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 5421b653a561SMatthew G. Knepley /* Free DMs */ 5422b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 5423dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 54249566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 5425b653a561SMatthew G. Knepley } 54269566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 5427b653a561SMatthew G. Knepley } else { 5428b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 54299318fe57SMatthew G. Knepley DM cdm; 54309318fe57SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 54313cf6fe12SMatthew G. Knepley 5432dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54339566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 54343cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 543569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 5436dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54379318fe57SMatthew G. Knepley if (coordFunc) { 54389566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 54399318fe57SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 54409318fe57SMatthew G. Knepley } 54413cf6fe12SMatthew G. Knepley } 5442b653a561SMatthew G. Knepley } 5443be664eb1SMatthew G. Knepley // Handle coordinate remapping 5444be664eb1SMatthew G. Knepley remap = PETSC_FALSE; 5445be664eb1SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_coord_remap", "Flag to control coordinate remapping", "", remap, &remap, NULL)); 5446be664eb1SMatthew G. Knepley if (remap) { 5447be664eb1SMatthew G. Knepley DMPlexCoordMap map = DM_COORD_MAP_NONE; 5448be664eb1SMatthew G. Knepley PetscPointFunc mapFunc = NULL; 5449be664eb1SMatthew G. Knepley PetscScalar params[16]; 5450f45b553cSPierre Jolivet PetscInt Np = PETSC_STATIC_ARRAY_LENGTH(params), cdim; 5451be664eb1SMatthew G. Knepley MPI_Comm comm; 5452be664eb1SMatthew G. Knepley 5453be664eb1SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 5454be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 5455be664eb1SMatthew G. Knepley PetscCall(PetscOptionsScalarArray("-dm_coord_map_params", "Parameters for the coordinate remapping", "", params, &Np, &flg)); 5456be664eb1SMatthew G. Knepley if (!flg) Np = 0; 5457be664eb1SMatthew G. Knepley // TODO Allow user to pass a map function by name 5458be664eb1SMatthew G. Knepley PetscCall(PetscOptionsEnum("-dm_coord_map", "Coordinate mapping for built-in mesh", "", DMPlexCoordMaps, (PetscEnum)map, (PetscEnum *)&map, &flg)); 5459be664eb1SMatthew G. Knepley if (flg) { 5460be664eb1SMatthew G. Knepley switch (map) { 5461be664eb1SMatthew G. Knepley case DM_COORD_MAP_NONE: 5462be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5463be664eb1SMatthew G. Knepley break; 5464be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHEAR: 5465be664eb1SMatthew G. Knepley mapFunc = coordMap_shear; 5466be664eb1SMatthew G. Knepley if (!Np) { 5467be664eb1SMatthew G. Knepley Np = cdim + 1; 5468be664eb1SMatthew G. Knepley params[0] = 0; 5469be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5470be664eb1SMatthew G. Knepley } 5471be664eb1SMatthew G. Knepley PetscCheck(Np == cdim + 1, comm, PETSC_ERR_ARG_WRONG, "The shear coordinate map must have cdim + 1 = %" PetscInt_FMT " parameters, not %" PetscInt_FMT, cdim + 1, Np); 5472be664eb1SMatthew G. Knepley break; 5473be664eb1SMatthew G. Knepley case DM_COORD_MAP_FLARE: 5474be664eb1SMatthew G. Knepley mapFunc = coordMap_flare; 5475be664eb1SMatthew G. Knepley if (!Np) { 5476be664eb1SMatthew G. Knepley Np = cdim + 1; 5477be664eb1SMatthew G. Knepley params[0] = 0; 5478be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5479be664eb1SMatthew G. Knepley } 5480be664eb1SMatthew G. Knepley PetscCheck(Np == cdim + 1, comm, PETSC_ERR_ARG_WRONG, "The flare coordinate map must have cdim + 1 = %" PetscInt_FMT " parameters, not %" PetscInt_FMT, cdim + 1, Np); 5481be664eb1SMatthew G. Knepley break; 5482be664eb1SMatthew G. Knepley case DM_COORD_MAP_ANNULUS: 5483be664eb1SMatthew G. Knepley mapFunc = coordMap_annulus; 5484be664eb1SMatthew G. Knepley if (!Np) { 5485be664eb1SMatthew G. Knepley Np = 2; 5486be664eb1SMatthew G. Knepley params[0] = 1.; 5487be664eb1SMatthew G. Knepley params[1] = 2.; 5488be664eb1SMatthew G. Knepley } 5489be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The annulus coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5490be664eb1SMatthew G. Knepley break; 5491be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHELL: 5492be664eb1SMatthew G. Knepley mapFunc = coordMap_shell; 5493be664eb1SMatthew G. Knepley if (!Np) { 5494be664eb1SMatthew G. Knepley Np = 2; 5495be664eb1SMatthew G. Knepley params[0] = 1.; 5496be664eb1SMatthew G. Knepley params[1] = 2.; 5497be664eb1SMatthew G. Knepley } 5498be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The spherical shell coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5499be664eb1SMatthew G. Knepley break; 5500be664eb1SMatthew G. Knepley default: 5501be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5502be664eb1SMatthew G. Knepley } 5503be664eb1SMatthew G. Knepley } 5504be664eb1SMatthew G. Knepley if (Np) { 5505be664eb1SMatthew G. Knepley DM cdm; 5506be664eb1SMatthew G. Knepley PetscDS cds; 5507be664eb1SMatthew G. Knepley 5508be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5509be664eb1SMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 5510be664eb1SMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, Np, params)); 5511be664eb1SMatthew G. Knepley } 5512be664eb1SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, mapFunc)); 5513be664eb1SMatthew G. Knepley } 5514909dfd52SMatthew G. Knepley /* Handle ghost cells */ 55159566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 5516909dfd52SMatthew G. Knepley if (ghostCells) { 5517909dfd52SMatthew G. Knepley DM gdm; 5518909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 5519909dfd52SMatthew G. Knepley 5520909dfd52SMatthew G. Knepley lname[0] = '\0'; 55219566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 55229566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 552369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 5524909dfd52SMatthew G. Knepley } 55256913077dSMatthew G. Knepley /* Handle 1D order */ 5526adc21957SMatthew G. Knepley if (reorder != DM_REORDER_DEFAULT_FALSE && dim == 1) { 55276913077dSMatthew G. Knepley DM cdm, rdm; 55286913077dSMatthew G. Knepley PetscDS cds; 55296913077dSMatthew G. Knepley PetscObject obj; 55306913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 55316913077dSMatthew G. Knepley IS perm; 55326bc1bd01Sksagiyam PetscInt Nf; 55336913077dSMatthew G. Knepley PetscBool distributed; 55346913077dSMatthew G. Knepley 55359566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 55369566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 55379566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 55389566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 55396913077dSMatthew G. Knepley if (Nf) { 55409566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 55419566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 55426913077dSMatthew G. Knepley } 55436bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 55449566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 55459566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 554669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 55479566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 55486913077dSMatthew G. Knepley } 55496913077dSMatthew G. Knepley } 55503cf6fe12SMatthew G. Knepley /* Handle */ 5551dd4c3f67SMatthew G. Knepley non_refine: 5552dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 555322d6dc08SStefano Zampini char *phases[16]; 555422d6dc08SStefano Zampini PetscInt Nphases = 16; 555522d6dc08SStefano Zampini PetscCall(PetscOptionsStringArray("-dm_plex_option_phases", "Option phase prefixes", "DMSetFromOptions", phases, &Nphases, &flg)); 5556d0609cedSBarry Smith PetscOptionsHeadEnd(); 555722d6dc08SStefano Zampini 555822d6dc08SStefano Zampini // Phases 555922d6dc08SStefano Zampini if (flg) { 556022d6dc08SStefano Zampini const char *oldPrefix; 556122d6dc08SStefano Zampini 556222d6dc08SStefano Zampini PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &oldPrefix)); 556322d6dc08SStefano Zampini for (PetscInt ph = 0; ph < Nphases; ++ph) { 556422d6dc08SStefano Zampini PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, phases[ph])); 556522d6dc08SStefano Zampini PetscCall(PetscInfo(dm, "Options phase %s for DM %s\n", phases[ph], dm->hdr.name)); 556622d6dc08SStefano Zampini PetscCall(DMSetFromOptions(dm)); 556722d6dc08SStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix)); 556822d6dc08SStefano Zampini PetscCall(PetscFree(phases[ph])); 556922d6dc08SStefano Zampini } 557022d6dc08SStefano Zampini } 55713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 55720a6ba040SMatthew G. Knepley } 55730a6ba040SMatthew G. Knepley 5574d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) 5575d71ae5a4SJacob Faibussowitsch { 5576552f7358SJed Brown PetscFunctionBegin; 55779566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 55789566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 55799566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 55809566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 55819566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 55829566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 55833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5584552f7358SJed Brown } 5585552f7358SJed Brown 5586d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) 5587d71ae5a4SJacob Faibussowitsch { 5588552f7358SJed Brown PetscFunctionBegin; 55899566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 55909566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 55919566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 55923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5593552f7358SJed Brown } 5594552f7358SJed Brown 5595d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 5596d71ae5a4SJacob Faibussowitsch { 5597793f3fe5SMatthew G. Knepley PetscInt depth, d; 5598793f3fe5SMatthew G. Knepley 5599793f3fe5SMatthew G. Knepley PetscFunctionBegin; 56009566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 5601793f3fe5SMatthew G. Knepley if (depth == 1) { 56029566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 56039566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 56049566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 56059371c9d4SSatish Balay else { 56069371c9d4SSatish Balay *pStart = 0; 56079371c9d4SSatish Balay *pEnd = 0; 56089371c9d4SSatish Balay } 5609793f3fe5SMatthew G. Knepley } else { 56109566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 5611793f3fe5SMatthew G. Knepley } 56123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5613793f3fe5SMatthew G. Knepley } 5614793f3fe5SMatthew G. Knepley 5615d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 5616d71ae5a4SJacob Faibussowitsch { 5617502a2867SDave May PetscSF sf; 56186497c311SBarry Smith PetscMPIInt niranks, njranks; 56196497c311SBarry Smith PetscInt n; 56200a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 56210a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 5622502a2867SDave May 56232f356facSMatthew G. Knepley PetscFunctionBegin; 56249566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 56250a19bb7dSprj- if (!data->neighbors) { 56269566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 56279566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 56289566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 56299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 56309566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 56319566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 56320a19bb7dSprj- n = njranks + niranks; 56339566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 56340a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 56359566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 56360a19bb7dSprj- } 56370a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 56380a19bb7dSprj- if (ranks) { 56390a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 56400a19bb7dSprj- else *ranks = NULL; 56410a19bb7dSprj- } 56423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5643502a2867SDave May } 5644502a2867SDave May 56451eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 56461eb70e55SToby Isaac 5647d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm) 5648d71ae5a4SJacob Faibussowitsch { 5649552f7358SJed Brown PetscFunctionBegin; 5650552f7358SJed Brown dm->ops->view = DMView_Plex; 56512c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 5652552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 565338221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 5654552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 56551bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 5656adc21957SMatthew G. Knepley dm->ops->createsectionpermutation = DMCreateSectionPermutation_Plex; 565766ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 5658552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 5659552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 5660184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 56610298fd71SBarry Smith dm->ops->createfieldis = NULL; 5662552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 5663f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 56640a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 5665552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 5666bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 5667bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 5668b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 56695a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 5670552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 56710a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 56720a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 5673b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 5674d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 56750298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 56760298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 56770298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 56780298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 5679552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 5680552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 56812adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 5682793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 5683552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 56840709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 56850709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 5686bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 56878c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 5688ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 56890709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 5690b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 56912a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 569228d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 56936c6a6b79SMatthew G. Knepley dm->ops->getlocalboundingbox = DMGetLocalBoundingBox_Coordinates; 5694907a3e9cSStefano Zampini dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_Plex; 5695907a3e9cSStefano Zampini dm->ops->createddscatters = DMCreateDomainDecompositionScatters_Plex; 56969566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 56976c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 56989566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 56999566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 57009566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 57019566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 57026bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 57036bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 5704adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", DMReorderSectionGetDefault_Plex)); 5705adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", DMReorderSectionSetDefault_Plex)); 5706adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", DMReorderSectionGetType_Plex)); 5707adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", DMReorderSectionSetType_Plex)); 57089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 5709c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 5710c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 5711d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", DMPlexGetUseCeed_Plex)); 5712d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", DMPlexSetUseCeed_Plex)); 57133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5714552f7358SJed Brown } 5715552f7358SJed Brown 5716d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 5717d71ae5a4SJacob Faibussowitsch { 571863a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 57191fca310dSJames Wright const PetscSF *face_sfs; 57201fca310dSJames Wright PetscInt num_face_sfs; 572163a16f15SMatthew G. Knepley 572263a16f15SMatthew G. Knepley PetscFunctionBegin; 572363a16f15SMatthew G. Knepley mesh->refct++; 572463a16f15SMatthew G. Knepley (*newdm)->data = mesh; 57251fca310dSJames Wright PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &face_sfs)); 57261fca310dSJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, num_face_sfs, (PetscSF *)face_sfs)); 57279566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 57289566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 57293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 573063a16f15SMatthew G. Knepley } 573163a16f15SMatthew G. Knepley 57328818961aSMatthew G Knepley /*MC 57330b4b7b1cSBarry Smith DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh (or grid), or CW Complex {cite}`cwcomplex`, 57340b4b7b1cSBarry Smith which can be expressed using a Hasse Diagram {cite}`hassediagram`. 573520f4b53cSBarry Smith In the local representation, `Vec`s contain all unknowns in the interior and shared boundary. This is 57360b4b7b1cSBarry Smith specified by a `PetscSection` object. Ownership in the global representation is determined by 5737a1cb98faSBarry Smith ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object. 57388818961aSMatthew G Knepley 5739e5893cccSMatthew G. Knepley Options Database Keys: 5740250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 5741250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 5742250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 5743250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 5744250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 5745250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 5746c3db174cSMatthew G. Knepley . -dm_localize <bool> - Whether to localize coordinates for periodic meshes 5747c3db174cSMatthew G. Knepley . -dm_sparse_localize <bool> - Whether to only localize cells on the periodic boundary 5748250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 5749ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 5750f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 5751f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 5752d5b43468SJose E. Roman . -dm_plex_max_projection_height - Maximum mesh point height used to project locally 5753f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 5754d02c7345SMatthew G. Knepley . -dm_plex_reorder_section - Use specialized blocking if available 5755aaa8cc7dSPierre Jolivet . -dm_plex_check_all - Perform all checks below 5756f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 5757f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 5758f12cf164SMatthew G. Knepley . -dm_plex_check_faces <celltype> - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 5759f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 5760f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 5761e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 57625962854dSMatthew G. Knepley . -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 57635962854dSMatthew G. Knepley - -dm_plex_print_fvm <num> - View FVM assembly information, such as flux updates 5764e5893cccSMatthew G. Knepley 57658818961aSMatthew G Knepley Level: intermediate 57668818961aSMatthew G Knepley 57671cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection` 57688818961aSMatthew G Knepley M*/ 57698818961aSMatthew G Knepley 5770d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 5771d71ae5a4SJacob Faibussowitsch { 5772552f7358SJed Brown DM_Plex *mesh; 5773412e9a14SMatthew G. Knepley PetscInt unit; 5774552f7358SJed Brown 5775552f7358SJed Brown PetscFunctionBegin; 5776f39ec787SMatthew G. Knepley PetscCall(PetscCitationsRegister(PlexCitation, &Plexcite)); 5777552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 57784dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mesh)); 5779adc21957SMatthew G. Knepley dm->reorderSection = DM_REORDER_DEFAULT_NOTSET; 5780552f7358SJed Brown dm->data = mesh; 5781552f7358SJed Brown 5782552f7358SJed Brown mesh->refct = 1; 57839566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 57849566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 5785552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 5786552f7358SJed Brown mesh->refinementLimit = -1.0; 5787e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 5788adc21957SMatthew G. Knepley mesh->reorderDefault = DM_REORDER_DEFAULT_NOTSET; 57891d1f2f2aSksagiyam mesh->distributionName = NULL; 57907d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 57917d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 57925e2c5519SMatthew G. Knepley mesh->interpolatePreferTensor = PETSC_TRUE; 5793552f7358SJed Brown 57949566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 57952e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 5796d9deefdfSMatthew G. Knepley 57978865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 5798552f7358SJed Brown 5799df0420ecSMatthew G. Knepley mesh->depthState = -1; 5800ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 58016113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 5802c29ce622SStefano Zampini mesh->nonempty_comm = MPI_COMM_SELF; 5803552f7358SJed Brown 58049566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 58053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5806552f7358SJed Brown } 5807552f7358SJed Brown 5808552f7358SJed Brown /*@ 5809a1cb98faSBarry Smith DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 5810552f7358SJed Brown 5811d083f849SBarry Smith Collective 5812552f7358SJed Brown 5813552f7358SJed Brown Input Parameter: 5814a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object 5815552f7358SJed Brown 5816552f7358SJed Brown Output Parameter: 5817a1cb98faSBarry Smith . mesh - The `DMPLEX` object 5818552f7358SJed Brown 5819552f7358SJed Brown Level: beginner 5820552f7358SJed Brown 582142747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMCreate()`, `DMSetType()` 5822552f7358SJed Brown @*/ 5823d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 5824d71ae5a4SJacob Faibussowitsch { 5825552f7358SJed Brown PetscFunctionBegin; 58264f572ea9SToby Isaac PetscAssertPointer(mesh, 2); 58279566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 58289566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 58293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5830552f7358SJed Brown } 5831552f7358SJed Brown 5832b09969d6SVaclav Hapla /*@C 5833b0fe842aSMatthew G. Knepley DMPlexBuildFromCellListParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) where all cells have the same celltype 5834a1cb98faSBarry Smith 583520f4b53cSBarry Smith Collective; No Fortran Support 5836b09969d6SVaclav Hapla 5837b09969d6SVaclav Hapla Input Parameters: 5838a1cb98faSBarry Smith + dm - The `DM` 5839b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 5840a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 5841a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DETERMINE` 5842b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 58435e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 5844b09969d6SVaclav Hapla 5845be8c289dSNicolas Barral Output Parameters: 5846a1cb98faSBarry Smith + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 5847be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 5848b09969d6SVaclav Hapla 5849b09969d6SVaclav Hapla Level: advanced 5850b09969d6SVaclav Hapla 5851a1cb98faSBarry Smith Notes: 5852a1cb98faSBarry Smith Two triangles sharing a face 5853a1cb98faSBarry Smith .vb 5854a1cb98faSBarry Smith 5855a1cb98faSBarry Smith 2 5856a1cb98faSBarry Smith / | \ 5857a1cb98faSBarry Smith / | \ 5858a1cb98faSBarry Smith / | \ 5859a1cb98faSBarry Smith 0 0 | 1 3 5860a1cb98faSBarry Smith \ | / 5861a1cb98faSBarry Smith \ | / 5862a1cb98faSBarry Smith \ | / 5863a1cb98faSBarry Smith 1 5864a1cb98faSBarry Smith .ve 5865a1cb98faSBarry Smith would have input 5866a1cb98faSBarry Smith .vb 5867a1cb98faSBarry Smith numCells = 2, numVertices = 4 5868a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 5869a1cb98faSBarry Smith .ve 5870a1cb98faSBarry Smith which would result in the `DMPLEX` 5871a1cb98faSBarry Smith .vb 5872a1cb98faSBarry Smith 5873a1cb98faSBarry Smith 4 5874a1cb98faSBarry Smith / | \ 5875a1cb98faSBarry Smith / | \ 5876a1cb98faSBarry Smith / | \ 5877a1cb98faSBarry Smith 2 0 | 1 5 5878a1cb98faSBarry Smith \ | / 5879a1cb98faSBarry Smith \ | / 5880a1cb98faSBarry Smith \ | / 5881a1cb98faSBarry Smith 3 5882a1cb98faSBarry Smith .ve 5883a1cb98faSBarry Smith 5884a1cb98faSBarry Smith Vertices are implicitly numbered consecutively 0,...,NVertices. 5885a1cb98faSBarry Smith Each rank owns a chunk of numVertices consecutive vertices. 5886a1cb98faSBarry Smith If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 5887a1cb98faSBarry Smith If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 5888a1cb98faSBarry Smith If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 5889a1cb98faSBarry Smith 5890a1cb98faSBarry Smith The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 5891a1cb98faSBarry Smith 58921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 5893a1cb98faSBarry Smith `PetscSF` 5894b09969d6SVaclav Hapla @*/ 5895ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[]) 5896d71ae5a4SJacob Faibussowitsch { 58972464107aSksagiyam PetscSF sfPoint; 58982464107aSksagiyam PetscLayout layout; 589982fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 5900a47d0d45SMatthew G. Knepley 5901a47d0d45SMatthew G. Knepley PetscFunctionBegin; 590225b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 59039566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 590425b6865aSVaclav Hapla /* Get/check global number of vertices */ 590525b6865aSVaclav Hapla { 590625b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 590725b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 590825b6865aSVaclav Hapla 590925b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 59101690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 59119371c9d4SSatish Balay for (i = 0; i < len; i++) 59129371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 591325b6865aSVaclav Hapla ++NVerticesInCells; 5914462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 591525b6865aSVaclav Hapla 591625b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 59179371c9d4SSatish Balay else 59189371c9d4SSatish Balay PetscCheck(NVertices == PETSC_DECIDE || NVertices >= NVerticesInCells, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Specified global number of vertices %" PetscInt_FMT " must be greater than or equal to the number of vertices in cells %" PetscInt_FMT, NVertices, NVerticesInCells); 591925b6865aSVaclav Hapla } 59209079aca8SVaclav Hapla /* Count locally unique vertices */ 59219079aca8SVaclav Hapla { 59229079aca8SVaclav Hapla PetscHSetI vhash; 59239079aca8SVaclav Hapla PetscInt off = 0; 59249079aca8SVaclav Hapla 59259566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 5926a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 592748a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 5928a47d0d45SMatthew G. Knepley } 59299566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 59309566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 5931ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 59329566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 59339566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 593463a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 5935a47d0d45SMatthew G. Knepley } 59369566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 5937a47d0d45SMatthew G. Knepley /* Create cones */ 59389566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 59399566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 59409566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 59419566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 5942a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 5943a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 5944a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 5945a47d0d45SMatthew G. Knepley PetscInt lv; 5946a47d0d45SMatthew G. Knepley 59479079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 59489079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 59499566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 595063a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 5951961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 5952a47d0d45SMatthew G. Knepley } 5953a47d0d45SMatthew G. Knepley } 59542464107aSksagiyam /* Build point sf */ 59559566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 59569566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 59579566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 59589566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 59599566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 59609566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 59619566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 59629566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 59632464107aSksagiyam if (dm->sf) { 59642464107aSksagiyam const char *prefix; 59652464107aSksagiyam 59669566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 59679566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 59682464107aSksagiyam } 59699566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 59709566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 5971f4f49eeaSPierre Jolivet if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 5972a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 59739566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 59749566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 59759566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 59763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5977a47d0d45SMatthew G. Knepley } 5978a47d0d45SMatthew G. Knepley 5979b0fe842aSMatthew G. Knepley /*@C 5980b0fe842aSMatthew G. Knepley DMPlexBuildFromCellSectionParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) allowing multiple celltypes 5981b0fe842aSMatthew G. Knepley 5982b0fe842aSMatthew G. Knepley Collective; No Fortran Support 5983b0fe842aSMatthew G. Knepley 5984b0fe842aSMatthew G. Knepley Input Parameters: 5985b0fe842aSMatthew G. Knepley + dm - The `DM` 5986b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 5987b0fe842aSMatthew G. Knepley . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 5988b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DETERMINE` 5989b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 5990b0fe842aSMatthew G. Knepley - cells - An array of the global vertex numbers for each cell 5991b0fe842aSMatthew G. Knepley 5992b0fe842aSMatthew G. Knepley Output Parameters: 5993b0fe842aSMatthew G. Knepley + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 5994b0fe842aSMatthew G. Knepley - verticesAdjSaved - (Optional) vertex adjacency array 5995b0fe842aSMatthew G. Knepley 5996b0fe842aSMatthew G. Knepley Level: advanced 5997b0fe842aSMatthew G. Knepley 5998b0fe842aSMatthew G. Knepley Notes: 5999b0fe842aSMatthew G. Knepley A triangle and quadrilateral sharing a face 6000b0fe842aSMatthew G. Knepley .vb 6001b0fe842aSMatthew G. Knepley 2----------3 6002b0fe842aSMatthew G. Knepley / | | 6003b0fe842aSMatthew G. Knepley / | | 6004b0fe842aSMatthew G. Knepley / | | 6005b0fe842aSMatthew G. Knepley 0 0 | 1 | 6006b0fe842aSMatthew G. Knepley \ | | 6007b0fe842aSMatthew G. Knepley \ | | 6008b0fe842aSMatthew G. Knepley \ | | 6009b0fe842aSMatthew G. Knepley 1----------4 6010b0fe842aSMatthew G. Knepley .ve 6011b0fe842aSMatthew G. Knepley would have input 6012b0fe842aSMatthew G. Knepley .vb 6013b0fe842aSMatthew G. Knepley numCells = 2, numVertices = 5 6014b0fe842aSMatthew G. Knepley cells = [0 1 2 1 4 3 2] 6015b0fe842aSMatthew G. Knepley .ve 6016b0fe842aSMatthew G. Knepley which would result in the `DMPLEX` 6017b0fe842aSMatthew G. Knepley .vb 6018b0fe842aSMatthew G. Knepley 4----------5 6019b0fe842aSMatthew G. Knepley / | | 6020b0fe842aSMatthew G. Knepley / | | 6021b0fe842aSMatthew G. Knepley / | | 6022b0fe842aSMatthew G. Knepley 2 0 | 1 | 6023b0fe842aSMatthew G. Knepley \ | | 6024b0fe842aSMatthew G. Knepley \ | | 6025b0fe842aSMatthew G. Knepley \ | | 6026b0fe842aSMatthew G. Knepley 3----------6 6027b0fe842aSMatthew G. Knepley .ve 6028b0fe842aSMatthew G. Knepley 6029b0fe842aSMatthew G. Knepley Vertices are implicitly numbered consecutively 0,...,NVertices. 6030b0fe842aSMatthew G. Knepley Each rank owns a chunk of numVertices consecutive vertices. 6031b0fe842aSMatthew G. Knepley If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 6032b0fe842aSMatthew G. Knepley If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 6033b0fe842aSMatthew G. Knepley If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 6034b0fe842aSMatthew G. Knepley 6035b0fe842aSMatthew G. Knepley The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 6036b0fe842aSMatthew G. Knepley 6037b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexCreateFromCellSectionParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 6038b0fe842aSMatthew G. Knepley `PetscSF` 6039b0fe842aSMatthew G. Knepley @*/ 6040ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellSectionParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[]) 6041b0fe842aSMatthew G. Knepley { 6042b0fe842aSMatthew G. Knepley PetscSF sfPoint; 6043b0fe842aSMatthew G. Knepley PetscLayout layout; 6044b0fe842aSMatthew G. Knepley PetscInt numVerticesAdj, *verticesAdj, *cones, cStart, cEnd, len; 6045b0fe842aSMatthew G. Knepley 6046b0fe842aSMatthew G. Knepley PetscFunctionBegin; 6047b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, NVertices, 4); 6048b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 6049b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetChart(cellSection, &cStart, &cEnd)); 6050b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(cellSection, &len)); 6051b0fe842aSMatthew G. Knepley PetscCheck(cStart == 0 && cEnd == numCells, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Section chart [%" PetscInt_FMT ", %" PetscInt_FMT ") should be [0, %" PetscInt_FMT ")", cStart, cEnd, numCells); 6052b0fe842aSMatthew G. Knepley /* Get/check global number of vertices */ 6053b0fe842aSMatthew G. Knepley { 6054b0fe842aSMatthew G. Knepley PetscInt NVerticesInCells; 6055b0fe842aSMatthew G. Knepley 6056b0fe842aSMatthew G. Knepley /* NVerticesInCells = max(cells) + 1 */ 6057b0fe842aSMatthew G. Knepley NVerticesInCells = PETSC_MIN_INT; 6058b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) 6059b0fe842aSMatthew G. Knepley if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 6060b0fe842aSMatthew G. Knepley ++NVerticesInCells; 6061b0fe842aSMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 6062b0fe842aSMatthew G. Knepley 6063b0fe842aSMatthew G. Knepley if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 6064b0fe842aSMatthew G. Knepley else 6065b0fe842aSMatthew G. Knepley PetscCheck(NVertices == PETSC_DECIDE || NVertices >= NVerticesInCells, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Specified global number of vertices %" PetscInt_FMT " must be greater than or equal to the number of vertices in cells %" PetscInt_FMT, NVertices, NVerticesInCells); 6066b0fe842aSMatthew G. Knepley } 6067b0fe842aSMatthew G. Knepley /* Count locally unique vertices */ 6068b0fe842aSMatthew G. Knepley { 6069b0fe842aSMatthew G. Knepley PetscHSetI vhash; 6070b0fe842aSMatthew G. Knepley PetscInt off = 0; 6071b0fe842aSMatthew G. Knepley 6072b0fe842aSMatthew G. Knepley PetscCall(PetscHSetICreate(&vhash)); 6073b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) PetscCall(PetscHSetIAdd(vhash, cells[i])); 6074b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 6075b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 6076b0fe842aSMatthew G. Knepley else verticesAdj = *verticesAdjSaved; 6077b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 6078b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIDestroy(&vhash)); 6079b0fe842aSMatthew G. Knepley PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 6080b0fe842aSMatthew G. Knepley } 6081b0fe842aSMatthew G. Knepley PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 6082b0fe842aSMatthew G. Knepley /* Create cones */ 6083b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 6084b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 6085b0fe842aSMatthew G. Knepley PetscInt dof; 6086b0fe842aSMatthew G. Knepley 6087b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 6088b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetConeSize(dm, c, dof)); 6089b0fe842aSMatthew G. Knepley } 6090b0fe842aSMatthew G. Knepley PetscCall(DMSetUp(dm)); 6091b0fe842aSMatthew G. Knepley PetscCall(DMPlexGetCones(dm, &cones)); 6092b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 6093b0fe842aSMatthew G. Knepley PetscInt dof, off; 6094b0fe842aSMatthew G. Knepley 6095b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 6096b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cellSection, c, &off)); 6097b0fe842aSMatthew G. Knepley for (PetscInt p = off; p < off + dof; ++p) { 6098b0fe842aSMatthew G. Knepley const PetscInt gv = cells[p]; 6099b0fe842aSMatthew G. Knepley PetscInt lv; 6100b0fe842aSMatthew G. Knepley 6101b0fe842aSMatthew G. Knepley /* Positions within verticesAdj form 0-based local vertex numbering; 6102b0fe842aSMatthew G. Knepley we need to shift it by numCells to get correct DAG points (cells go first) */ 6103b0fe842aSMatthew G. Knepley PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 6104b0fe842aSMatthew G. Knepley PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 6105b0fe842aSMatthew G. Knepley cones[p] = lv + numCells; 6106b0fe842aSMatthew G. Knepley } 6107b0fe842aSMatthew G. Knepley } 6108b0fe842aSMatthew G. Knepley /* Build point sf */ 6109b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 6110b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetSize(layout, NVertices)); 6111b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 6112b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetBlockSize(layout, 1)); 6113b0fe842aSMatthew G. Knepley PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 6114b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutDestroy(&layout)); 6115b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 6116b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 6117b0fe842aSMatthew G. Knepley if (dm->sf) { 6118b0fe842aSMatthew G. Knepley const char *prefix; 6119b0fe842aSMatthew G. Knepley 6120b0fe842aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 6121b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 6122b0fe842aSMatthew G. Knepley } 6123b0fe842aSMatthew G. Knepley PetscCall(DMSetPointSF(dm, sfPoint)); 6124b0fe842aSMatthew G. Knepley PetscCall(PetscSFDestroy(&sfPoint)); 6125b0fe842aSMatthew G. Knepley if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 6126b0fe842aSMatthew G. Knepley /* Fill in the rest of the topology structure */ 6127b0fe842aSMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 6128b0fe842aSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 6129b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 6130b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 6131b0fe842aSMatthew G. Knepley } 6132b0fe842aSMatthew G. Knepley 6133cc4c1da9SBarry Smith /*@ 6134a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 6135a1cb98faSBarry Smith 613620f4b53cSBarry Smith Collective; No Fortran Support 6137b09969d6SVaclav Hapla 6138b09969d6SVaclav Hapla Input Parameters: 6139a1cb98faSBarry Smith + dm - The `DM` 6140b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6141a1cb98faSBarry Smith . sfVert - `PetscSF` describing complete vertex ownership 6142b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6143b09969d6SVaclav Hapla 6144b09969d6SVaclav Hapla Level: advanced 6145b09969d6SVaclav Hapla 61461cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 6147b09969d6SVaclav Hapla @*/ 6148d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 6149d71ae5a4SJacob Faibussowitsch { 6150a47d0d45SMatthew G. Knepley PetscSection coordSection; 6151a47d0d45SMatthew G. Knepley Vec coordinates; 6152a47d0d45SMatthew G. Knepley PetscScalar *coords; 61531edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 6154835f2295SStefano Zampini PetscMPIInt spaceDimi; 6155a47d0d45SMatthew G. Knepley 6156a47d0d45SMatthew G. Knepley PetscFunctionBegin; 61579566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 61589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 61591dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 61609566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 61619566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 61621dca8a05SBarry Smith PetscCheck(vEnd - vStart == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Supplied sfVert has wrong number of leaves = %" PetscInt_FMT " != %" PetscInt_FMT " = vEnd - vStart", numVerticesAdj, vEnd - vStart); 61639566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 61649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 61659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 61669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 61671edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 61689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 61699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 6170a47d0d45SMatthew G. Knepley } 61719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 61729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 61739566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 61749566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 61759566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 61769566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 61779566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 61789566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6179a47d0d45SMatthew G. Knepley { 6180a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 6181a47d0d45SMatthew G. Knepley 6182a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 6183835f2295SStefano Zampini PetscCall(PetscMPIIntCast(spaceDim, &spaceDimi)); 6184835f2295SStefano Zampini PetscCallMPI(MPI_Type_contiguous(spaceDimi, MPIU_SCALAR, &coordtype)); 61859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 618621016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 618721016a8bSBarry Smith { 618821016a8bSBarry Smith PetscScalar *svertexCoords; 618921016a8bSBarry Smith PetscInt i; 61909566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 61913612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 61929566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 61939566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 61949566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 619521016a8bSBarry Smith } 619621016a8bSBarry Smith #else 61979566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 61989566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 619921016a8bSBarry Smith #endif 62009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 6201a47d0d45SMatthew G. Knepley } 62029566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 62039566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 62049566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 62059566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 62063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6207a47d0d45SMatthew G. Knepley } 6208a47d0d45SMatthew G. Knepley 6209c3edce3dSSatish Balay /*@ 6210b0fe842aSMatthew G. Knepley DMPlexCreateFromCellListParallelPetsc - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) where all cells have the same celltype 6211a1cb98faSBarry Smith 6212a1cb98faSBarry Smith Collective 6213a47d0d45SMatthew G. Knepley 6214a47d0d45SMatthew G. Knepley Input Parameters: 6215a47d0d45SMatthew G. Knepley + comm - The communicator 6216a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 6217a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 6218a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 6219a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DECIDE` 6220a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 6221a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6222a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 6223a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 6224a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6225a47d0d45SMatthew G. Knepley 6226d8d19677SJose E. Roman Output Parameters: 6227a1cb98faSBarry Smith + dm - The `DM` 6228a1cb98faSBarry Smith . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 622960225df5SJacob Faibussowitsch - verticesAdj - (Optional) vertex adjacency array 6230a47d0d45SMatthew G. Knepley 6231b09969d6SVaclav Hapla Level: intermediate 6232a47d0d45SMatthew G. Knepley 6233a1cb98faSBarry Smith Notes: 6234a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 6235a1cb98faSBarry Smith `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 6236a1cb98faSBarry Smith 6237a1cb98faSBarry Smith See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters. 6238a1cb98faSBarry Smith 6239a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 6240a1cb98faSBarry Smith 62411cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 6242a47d0d45SMatthew G. Knepley @*/ 6243ce78bad3SBarry Smith PetscErrorCode DMPlexCreateFromCellListParallelPetsc(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdj[], DM *dm) 6244d71ae5a4SJacob Faibussowitsch { 6245a47d0d45SMatthew G. Knepley PetscSF sfVert; 6246a47d0d45SMatthew G. Knepley 6247a47d0d45SMatthew G. Knepley PetscFunctionBegin; 62489566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 62499566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 6250a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 6251064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 62529566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 62539566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 6254a47d0d45SMatthew G. Knepley if (interpolate) { 62555fd9971aSMatthew G. Knepley DM idm; 6256a47d0d45SMatthew G. Knepley 62579566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 62589566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 6259a47d0d45SMatthew G. Knepley *dm = idm; 6260a47d0d45SMatthew G. Knepley } 62619566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 626218d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 62639566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 62643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6265a47d0d45SMatthew G. Knepley } 6266a47d0d45SMatthew G. Knepley 6267cc4c1da9SBarry Smith /*@ 6268b0fe842aSMatthew G. Knepley DMPlexCreateFromCellSectionParallel - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) and supports multiple celltypes 6269b0fe842aSMatthew G. Knepley 6270b0fe842aSMatthew G. Knepley Collective 6271b0fe842aSMatthew G. Knepley 6272b0fe842aSMatthew G. Knepley Input Parameters: 6273b0fe842aSMatthew G. Knepley + comm - The communicator 6274b0fe842aSMatthew G. Knepley . dim - The topological dimension of the mesh 6275b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 6276b0fe842aSMatthew G. Knepley . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 6277b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DECIDE` 6278b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 6279b0fe842aSMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6280b0fe842aSMatthew G. Knepley . cells - An array of the global vertex numbers for each cell 6281b0fe842aSMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 6282b0fe842aSMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6283b0fe842aSMatthew G. Knepley 6284b0fe842aSMatthew G. Knepley Output Parameters: 6285b0fe842aSMatthew G. Knepley + dm - The `DM` 6286b0fe842aSMatthew G. Knepley . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 6287b0fe842aSMatthew G. Knepley - verticesAdj - (Optional) vertex adjacency array 6288b0fe842aSMatthew G. Knepley 6289b0fe842aSMatthew G. Knepley Level: intermediate 6290b0fe842aSMatthew G. Knepley 6291b0fe842aSMatthew G. Knepley Notes: 6292b0fe842aSMatthew G. Knepley This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 6293b0fe842aSMatthew G. Knepley `DMPlexBuildFromCellSectionParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 6294b0fe842aSMatthew G. Knepley 6295b0fe842aSMatthew G. Knepley See `DMPlexBuildFromCellSectionParallel()` for an example and details about the topology-related parameters. 6296b0fe842aSMatthew G. Knepley 6297b0fe842aSMatthew G. Knepley See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 6298b0fe842aSMatthew G. Knepley 6299b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 6300b0fe842aSMatthew G. Knepley @*/ 6301ce78bad3SBarry Smith PetscErrorCode DMPlexCreateFromCellSectionParallel(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdj[], DM *dm) 6302b0fe842aSMatthew G. Knepley { 6303b0fe842aSMatthew G. Knepley PetscSF sfVert; 6304b0fe842aSMatthew G. Knepley 6305b0fe842aSMatthew G. Knepley PetscFunctionBegin; 6306b0fe842aSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 6307b0fe842aSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 6308b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 6309b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 6310b0fe842aSMatthew G. Knepley PetscCall(DMSetDimension(*dm, dim)); 6311b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildFromCellSectionParallel(*dm, numCells, numVertices, NVertices, cellSection, cells, &sfVert, verticesAdj)); 6312b0fe842aSMatthew G. Knepley if (interpolate) { 6313b0fe842aSMatthew G. Knepley DM idm; 6314b0fe842aSMatthew G. Knepley 6315b0fe842aSMatthew G. Knepley PetscCall(DMPlexInterpolate(*dm, &idm)); 6316b0fe842aSMatthew G. Knepley PetscCall(DMDestroy(dm)); 6317b0fe842aSMatthew G. Knepley *dm = idm; 6318b0fe842aSMatthew G. Knepley } 6319b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 6320b0fe842aSMatthew G. Knepley if (vertexSF) *vertexSF = sfVert; 6321b0fe842aSMatthew G. Knepley else PetscCall(PetscSFDestroy(&sfVert)); 6322b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 6323b0fe842aSMatthew G. Knepley } 6324b0fe842aSMatthew G. Knepley 6325b0fe842aSMatthew G. Knepley /*@ 6326a1cb98faSBarry Smith DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) 6327a1cb98faSBarry Smith 632820f4b53cSBarry Smith Collective; No Fortran Support 63299298eaa6SMatthew G Knepley 63309298eaa6SMatthew G Knepley Input Parameters: 6331a1cb98faSBarry Smith + dm - The `DM` 6332b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 6333a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE` 63349298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 6335a3b724e8SBarry Smith - cells - An array of `numCells` x `numCorners` numbers, the global vertex numbers for each cell 63369298eaa6SMatthew G Knepley 6337b09969d6SVaclav Hapla Level: advanced 63389298eaa6SMatthew G Knepley 6339b09969d6SVaclav Hapla Notes: 6340b09969d6SVaclav Hapla Two triangles sharing a face 6341a1cb98faSBarry Smith .vb 63429298eaa6SMatthew G Knepley 6343a1cb98faSBarry Smith 2 6344a1cb98faSBarry Smith / | \ 6345a1cb98faSBarry Smith / | \ 6346a1cb98faSBarry Smith / | \ 6347a1cb98faSBarry Smith 0 0 | 1 3 6348a1cb98faSBarry Smith \ | / 6349a1cb98faSBarry Smith \ | / 6350a1cb98faSBarry Smith \ | / 6351a1cb98faSBarry Smith 1 6352a1cb98faSBarry Smith .ve 6353a1cb98faSBarry Smith would have input 6354a1cb98faSBarry Smith .vb 6355a1cb98faSBarry Smith numCells = 2, numVertices = 4 6356a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 6357a1cb98faSBarry Smith .ve 6358a1cb98faSBarry Smith which would result in the `DMPLEX` 6359a1cb98faSBarry Smith .vb 6360a1cb98faSBarry Smith 6361a1cb98faSBarry Smith 4 6362a1cb98faSBarry Smith / | \ 6363a1cb98faSBarry Smith / | \ 6364a1cb98faSBarry Smith / | \ 6365a1cb98faSBarry Smith 2 0 | 1 5 6366a1cb98faSBarry Smith \ | / 6367a1cb98faSBarry Smith \ | / 6368a1cb98faSBarry Smith \ | / 6369a1cb98faSBarry Smith 3 6370a1cb98faSBarry Smith .ve 6371a1cb98faSBarry Smith 6372a1cb98faSBarry Smith If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1. 637325b6865aSVaclav Hapla 63741cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 6375b09969d6SVaclav Hapla @*/ 6376d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 6377d71ae5a4SJacob Faibussowitsch { 6378961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 6379b09969d6SVaclav Hapla 6380b09969d6SVaclav Hapla PetscFunctionBegin; 63819566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 63829566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 638325b6865aSVaclav Hapla /* Get/check global number of vertices */ 638425b6865aSVaclav Hapla { 638525b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 638625b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 638725b6865aSVaclav Hapla 638825b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 63891690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 63909371c9d4SSatish Balay for (i = 0; i < len; i++) 63919371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 639225b6865aSVaclav Hapla ++NVerticesInCells; 639325b6865aSVaclav Hapla 639425b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 63959371c9d4SSatish Balay else 63969371c9d4SSatish Balay PetscCheck(numVertices >= NVerticesInCells, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Specified number of vertices %" PetscInt_FMT " must be greater than or equal to the number of vertices in cells %" PetscInt_FMT, numVertices, NVerticesInCells); 639725b6865aSVaclav Hapla } 63989566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 639948a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 64009566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 64019566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 6402b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 6403ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 6404b09969d6SVaclav Hapla } 64059566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 64069566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 64079566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 64083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6409b09969d6SVaclav Hapla } 6410b09969d6SVaclav Hapla 6411cc4c1da9SBarry Smith /*@ 6412a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 6413a1cb98faSBarry Smith 6414cc4c1da9SBarry Smith Collective 6415b09969d6SVaclav Hapla 6416b09969d6SVaclav Hapla Input Parameters: 6417a1cb98faSBarry Smith + dm - The `DM` 6418b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6419b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6420b09969d6SVaclav Hapla 6421b09969d6SVaclav Hapla Level: advanced 6422b09969d6SVaclav Hapla 64231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 6424b09969d6SVaclav Hapla @*/ 6425d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 6426d71ae5a4SJacob Faibussowitsch { 6427b09969d6SVaclav Hapla PetscSection coordSection; 6428b09969d6SVaclav Hapla Vec coordinates; 6429b09969d6SVaclav Hapla DM cdm; 6430b09969d6SVaclav Hapla PetscScalar *coords; 64311edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 6432b09969d6SVaclav Hapla 6433b09969d6SVaclav Hapla PetscFunctionBegin; 64349566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 64359566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 64361dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 64379566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 64389566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 64399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 64409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 64419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 64421edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 64439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 64449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 6445b09969d6SVaclav Hapla } 64469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6447b09969d6SVaclav Hapla 64489566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 64499566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 64509566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 64519566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 64529566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 64531edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 6454ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 6455b09969d6SVaclav Hapla } 64569566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 64579566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 64589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 64599566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 64603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6461b09969d6SVaclav Hapla } 6462b09969d6SVaclav Hapla 6463b09969d6SVaclav Hapla /*@ 6464a1cb98faSBarry Smith DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 64653df08285SMatthew G. Knepley 6466a1cb98faSBarry Smith Collective 6467b09969d6SVaclav Hapla 6468b09969d6SVaclav Hapla Input Parameters: 6469b09969d6SVaclav Hapla + comm - The communicator 6470b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 64713df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 6472a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0 64733df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 6474b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6475ce78bad3SBarry Smith . cells - An array of $ numCells \times numCorners$ numbers, the vertices for each cell, only on process 0 6476b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6477ce78bad3SBarry Smith - vertexCoords - An array of $ numVertices \times spaceDim$ numbers, the coordinates of each vertex, only on process 0 6478b09969d6SVaclav Hapla 6479b09969d6SVaclav Hapla Output Parameter: 6480a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0 648125b6865aSVaclav Hapla 6482b09969d6SVaclav Hapla Level: intermediate 6483b09969d6SVaclav Hapla 6484a1cb98faSBarry Smith Notes: 6485a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`, 6486a1cb98faSBarry Smith `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()` 6487a1cb98faSBarry Smith 6488a1cb98faSBarry Smith See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters. 6489a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters. 6490a1cb98faSBarry Smith See `DMPlexCreateFromCellListParallelPetsc()` for parallel input 6491a1cb98faSBarry Smith 64921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 64939298eaa6SMatthew G Knepley @*/ 6494d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromCellListPetsc(MPI_Comm comm, PetscInt dim, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, PetscBool interpolate, const PetscInt cells[], PetscInt spaceDim, const PetscReal vertexCoords[], DM *dm) 6495d71ae5a4SJacob Faibussowitsch { 64963df08285SMatthew G. Knepley PetscMPIInt rank; 64979298eaa6SMatthew G Knepley 64989298eaa6SMatthew G Knepley PetscFunctionBegin; 649928b400f6SJacob Faibussowitsch PetscCheck(dim, comm, PETSC_ERR_ARG_OUTOFRANGE, "This is not appropriate for 0-dimensional meshes. Consider either creating the DM using DMPlexCreateFromDAG(), by hand, or using DMSwarm."); 65009566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 65019566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 65029566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 65039566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 6504c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 65059566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 65069298eaa6SMatthew G Knepley if (interpolate) { 65075fd9971aSMatthew G. Knepley DM idm; 65089298eaa6SMatthew G Knepley 65099566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 65109566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 65119298eaa6SMatthew G Knepley *dm = idm; 65129298eaa6SMatthew G Knepley } 6513c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 65149566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 65153ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 65169298eaa6SMatthew G Knepley } 65179298eaa6SMatthew G Knepley 6518939f6067SMatthew G. Knepley /*@ 651920f4b53cSBarry Smith DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a `DM` 6520939f6067SMatthew G. Knepley 6521939f6067SMatthew G. Knepley Input Parameters: 652220f4b53cSBarry Smith + dm - The empty `DM` object, usually from `DMCreate()` and `DMSetDimension()` 6523939f6067SMatthew G. Knepley . depth - The depth of the DAG 6524ce78bad3SBarry Smith . numPoints - Array of size $ depth + 1 $ containing the number of points at each `depth` 6525939f6067SMatthew G. Knepley . coneSize - The cone size of each point 6526939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 6527939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 6528ce78bad3SBarry Smith - vertexCoords - An array of $ numPoints[0] \times spacedim $ numbers representing the coordinates of each vertex, with `spacedim` the value set via `DMSetCoordinateDim()` 6529939f6067SMatthew G. Knepley 6530939f6067SMatthew G. Knepley Output Parameter: 653120f4b53cSBarry Smith . dm - The `DM` 653220f4b53cSBarry Smith 653320f4b53cSBarry Smith Level: advanced 6534939f6067SMatthew G. Knepley 6535a1cb98faSBarry Smith Note: 6536a1cb98faSBarry Smith Two triangles sharing a face would have input 6537a1cb98faSBarry Smith .vb 6538a1cb98faSBarry Smith depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 6539a1cb98faSBarry Smith cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 6540a1cb98faSBarry Smith vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 6541a1cb98faSBarry Smith .ve 6542939f6067SMatthew G. Knepley which would result in the DMPlex 6543a1cb98faSBarry Smith .vb 6544a1cb98faSBarry Smith 4 6545a1cb98faSBarry Smith / | \ 6546a1cb98faSBarry Smith / | \ 6547a1cb98faSBarry Smith / | \ 6548a1cb98faSBarry Smith 2 0 | 1 5 6549a1cb98faSBarry Smith \ | / 6550a1cb98faSBarry Smith \ | / 6551a1cb98faSBarry Smith \ | / 6552a1cb98faSBarry Smith 3 6553a1cb98faSBarry Smith .ve 6554a1cb98faSBarry Smith Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()` 6555939f6067SMatthew G. Knepley 6556ce78bad3SBarry Smith Developer Note: 6557ce78bad3SBarry Smith This does not create anything so should not have create in the name. 6558ce78bad3SBarry Smith 65591cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 6560939f6067SMatthew G. Knepley @*/ 6561d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 6562d71ae5a4SJacob Faibussowitsch { 65639298eaa6SMatthew G Knepley Vec coordinates; 65649298eaa6SMatthew G Knepley PetscSection coordSection; 65659298eaa6SMatthew G Knepley PetscScalar *coords; 6566811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 65679298eaa6SMatthew G Knepley 65689298eaa6SMatthew G Knepley PetscFunctionBegin; 65699566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 65709566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 657163a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 65729298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 65739566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 65749298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 65759566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 6576ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 657797e052ccSToby Isaac } 65781dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 65799566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 65809298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 65819566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 65829566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 65839298eaa6SMatthew G Knepley } 65849566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 65859566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 65869298eaa6SMatthew G Knepley /* Build coordinates */ 65879566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 65889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 65899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 65909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 65919298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 65929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 65939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 65949298eaa6SMatthew G Knepley } 65959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 65969566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 65979566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 65989566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 65999566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 66009566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dimEmbed)); 66019566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 66029318fe57SMatthew G. Knepley if (vertexCoords) { 66039566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 66049298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 66059298eaa6SMatthew G Knepley PetscInt off; 66069298eaa6SMatthew G Knepley 66079566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 6608ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 66099298eaa6SMatthew G Knepley } 66109318fe57SMatthew G. Knepley } 66119566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 66129566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 66139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 66143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 66159298eaa6SMatthew G Knepley } 66168415267dSToby Isaac 6617a4e35b19SJacob Faibussowitsch /* 6618a1cb98faSBarry Smith DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file. 6619a1cb98faSBarry Smith 6620a1cb98faSBarry Smith Collective 66218ca92349SMatthew G. Knepley 66228ca92349SMatthew G. Knepley + comm - The MPI communicator 66238ca92349SMatthew G. Knepley . filename - Name of the .dat file 66248ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 66258ca92349SMatthew G. Knepley 66268ca92349SMatthew G. Knepley Output Parameter: 6627a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 66288ca92349SMatthew G. Knepley 66298ca92349SMatthew G. Knepley Level: beginner 66308ca92349SMatthew G. Knepley 6631a1cb98faSBarry Smith Note: 6632a1cb98faSBarry Smith The format is the simplest possible: 6633a1cb98faSBarry Smith .vb 6634d0812dedSMatthew G. Knepley dim Ne Nv Nc Nl 6635d0812dedSMatthew G. Knepley v_1 v_2 ... v_Nc 6636d0812dedSMatthew G. Knepley ... 6637d0812dedSMatthew G. Knepley x y z marker_1 ... marker_Nl 6638a1cb98faSBarry Smith .ve 6639a1cb98faSBarry Smith 6640a1cb98faSBarry Smith Developer Note: 6641a1cb98faSBarry Smith Should use a `PetscViewer` not a filename 6642a1cb98faSBarry Smith 66436afe31f6SMartin Diehl .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 6644a4e35b19SJacob Faibussowitsch */ 6645ff6a9541SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 6646d71ae5a4SJacob Faibussowitsch { 66478ca92349SMatthew G. Knepley DMLabel marker; 66488ca92349SMatthew G. Knepley PetscViewer viewer; 66498ca92349SMatthew G. Knepley Vec coordinates; 66508ca92349SMatthew G. Knepley PetscSection coordSection; 66518ca92349SMatthew G. Knepley PetscScalar *coords; 66528ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 6653d0812dedSMatthew G. Knepley PetscInt cdim, coordSize, v, c, d; 66548ca92349SMatthew G. Knepley PetscMPIInt rank; 6655d0812dedSMatthew G. Knepley int snum, dim, Nv, Nc, Ncn, Nl; 66568ca92349SMatthew G. Knepley 66578ca92349SMatthew G. Knepley PetscFunctionBegin; 66589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 66599566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 66609566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 66619566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 66629566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 6663dd400576SPatrick Sanan if (rank == 0) { 6664d0812dedSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING)); 6665d0812dedSMatthew G. Knepley snum = sscanf(line, "%d %d %d %d %d", &dim, &Nc, &Nv, &Ncn, &Nl); 6666d0812dedSMatthew G. Knepley PetscCheck(snum == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 666725ce1634SJed Brown } else { 6668f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 66698ca92349SMatthew G. Knepley } 6670d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm)); 6671835f2295SStefano Zampini cdim = dim; 66729566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 66739566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 66749566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 6675835f2295SStefano Zampini PetscCall(DMSetDimension(*dm, dim)); 66769566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 66778ca92349SMatthew G. Knepley /* Read topology */ 6678dd400576SPatrick Sanan if (rank == 0) { 6679f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 6680f8d5e320SMatthew G. Knepley PetscInt cone[8]; 66818ca92349SMatthew G. Knepley int vbuf[8], v; 66828ca92349SMatthew G. Knepley 66839371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 66849371c9d4SSatish Balay format[c * 3 + 0] = '%'; 66859371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 66869371c9d4SSatish Balay format[c * 3 + 2] = ' '; 66879371c9d4SSatish Balay } 6688f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 66899566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 66909566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 66918ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 66929566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 6693f8d5e320SMatthew G. Knepley switch (Ncn) { 6694d71ae5a4SJacob Faibussowitsch case 2: 6695d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1]); 6696d71ae5a4SJacob Faibussowitsch break; 6697d71ae5a4SJacob Faibussowitsch case 3: 6698d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); 6699d71ae5a4SJacob Faibussowitsch break; 6700d71ae5a4SJacob Faibussowitsch case 4: 6701d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); 6702d71ae5a4SJacob Faibussowitsch break; 6703d71ae5a4SJacob Faibussowitsch case 6: 6704d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); 6705d71ae5a4SJacob Faibussowitsch break; 6706d71ae5a4SJacob Faibussowitsch case 8: 6707d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 6708d71ae5a4SJacob Faibussowitsch break; 6709d71ae5a4SJacob Faibussowitsch default: 6710d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 6711f8d5e320SMatthew G. Knepley } 671208401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6713f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 67148ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 6715f8d5e320SMatthew G. Knepley if (Ncn == 8) { 67168ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 67178ca92349SMatthew G. Knepley cone[1] = cone[3]; 67188ca92349SMatthew G. Knepley cone[3] = tmp; 67198ca92349SMatthew G. Knepley } 67209566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 67218ca92349SMatthew G. Knepley } 67228ca92349SMatthew G. Knepley } 67239566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 67249566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 67258ca92349SMatthew G. Knepley /* Read coordinates */ 67269566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 67279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 67289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 67299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 67308ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 67319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 67329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 67338ca92349SMatthew G. Knepley } 67349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 67359566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 67369566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 67379566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 67389566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 67399566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 67409566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 67419566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6742dd400576SPatrick Sanan if (rank == 0) { 6743f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 67448ca92349SMatthew G. Knepley double x[3]; 6745f8d5e320SMatthew G. Knepley int l, val[3]; 67468ca92349SMatthew G. Knepley 6747f8d5e320SMatthew G. Knepley if (Nl) { 67489371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 67499371c9d4SSatish Balay format[l * 3 + 0] = '%'; 67509371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 67519371c9d4SSatish Balay format[l * 3 + 2] = ' '; 67529371c9d4SSatish Balay } 6753f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 67549566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 67559566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 6756f8d5e320SMatthew G. Knepley } 67578ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 67589566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 6759f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 676008401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6761f8d5e320SMatthew G. Knepley switch (Nl) { 6762d71ae5a4SJacob Faibussowitsch case 0: 6763d71ae5a4SJacob Faibussowitsch snum = 0; 6764d71ae5a4SJacob Faibussowitsch break; 6765d71ae5a4SJacob Faibussowitsch case 1: 6766d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0]); 6767d71ae5a4SJacob Faibussowitsch break; 6768d71ae5a4SJacob Faibussowitsch case 2: 6769d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1]); 6770d71ae5a4SJacob Faibussowitsch break; 6771d71ae5a4SJacob Faibussowitsch case 3: 6772d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1], &val[2]); 6773d71ae5a4SJacob Faibussowitsch break; 6774d71ae5a4SJacob Faibussowitsch default: 6775d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 6776f8d5e320SMatthew G. Knepley } 677708401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 67788ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 67799566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 67808ca92349SMatthew G. Knepley } 67818ca92349SMatthew G. Knepley } 67829566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 67839566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 67849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 67859566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 67868ca92349SMatthew G. Knepley if (interpolate) { 67878ca92349SMatthew G. Knepley DM idm; 67888ca92349SMatthew G. Knepley DMLabel bdlabel; 67898ca92349SMatthew G. Knepley 67909566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 67919566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 67928ca92349SMatthew G. Knepley *dm = idm; 67938ca92349SMatthew G. Knepley 6794f8d5e320SMatthew G. Knepley if (!Nl) { 67959566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 67969566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 67979566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 67989566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 67998ca92349SMatthew G. Knepley } 6800f8d5e320SMatthew G. Knepley } 68013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68028ca92349SMatthew G. Knepley } 68038ca92349SMatthew G. Knepley 6804cc4c1da9SBarry Smith /*@ 6805a1cb98faSBarry Smith DMPlexCreateFromFile - This takes a filename and produces a `DM` 6806a1cb98faSBarry Smith 6807a1cb98faSBarry Smith Collective 6808ca522641SMatthew G. Knepley 6809ca522641SMatthew G. Knepley Input Parameters: 6810ca522641SMatthew G. Knepley + comm - The communicator 6811ca522641SMatthew G. Knepley . filename - A file name 6812a1cb98faSBarry Smith . plexname - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats 6813ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 6814ca522641SMatthew G. Knepley 6815ca522641SMatthew G. Knepley Output Parameter: 6816a1cb98faSBarry Smith . dm - The `DM` 6817ca522641SMatthew G. Knepley 6818a1cb98faSBarry Smith Options Database Key: 6819a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5 682002ef0d99SVaclav Hapla 682137fdd005SBarry Smith Use `-dm_plex_create_ prefix` to pass options to the internal `PetscViewer`, e.g. 6822bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective 6823bca97951SVaclav Hapla 6824ca522641SMatthew G. Knepley Level: beginner 6825ca522641SMatthew G. Knepley 6826a1cb98faSBarry Smith Notes: 6827a1cb98faSBarry Smith Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX` 6828a1cb98faSBarry Smith meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()` 6829a1cb98faSBarry Smith before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object. 6830a1cb98faSBarry Smith The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally 6831a1cb98faSBarry Smith calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats. 6832a1cb98faSBarry Smith 68331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 6834ca522641SMatthew G. Knepley @*/ 6835d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 6836d71ae5a4SJacob Faibussowitsch { 6837ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 6838ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 6839ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 6840ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 6841ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 6842ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 6843ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 6844ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 6845ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 68466f2c871aSStefano Zampini const char extXDMFHDF5[] = ".xdmf.h5"; 6847ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 68485552b385SBrandon const char extEGADSlite[] = ".egadslite"; 6849ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 6850ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 68515552b385SBrandon const char extIGES2[] = ".iges"; 6852ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 68535552b385SBrandon const char extSTEP2[] = ".step"; 68545552b385SBrandon const char extBREP[] = ".brep"; 6855ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 6856ca522641SMatthew G. Knepley size_t len; 68575552b385SBrandon PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isPLY, isEGADSlite, isEGADS, isIGES, isIGES2, isSTEP, isSTEP2, isBREP, isCV, isXDMFHDF5; 6858ca522641SMatthew G. Knepley PetscMPIInt rank; 6859ca522641SMatthew G. Knepley 6860ca522641SMatthew G. Knepley PetscFunctionBegin; 68614f572ea9SToby Isaac PetscAssertPointer(filename, 2); 68624f572ea9SToby Isaac if (plexname) PetscAssertPointer(plexname, 3); 68634f572ea9SToby Isaac PetscAssertPointer(dm, 5); 68649566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 68659566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 68669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 68679566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 686828b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 6869ef3a5affSJacob Faibussowitsch 68709371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 68719371c9d4SSatish Balay do { \ 6872274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 6873274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 6874274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 6875274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 6876ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 6877ef3a5affSJacob Faibussowitsch } else { \ 6878274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 6879ef3a5affSJacob Faibussowitsch } \ 6880ef3a5affSJacob Faibussowitsch } while (0) 6881ef3a5affSJacob Faibussowitsch 6882ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 6883ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 6884ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 6885ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 6886ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 6887ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 6888ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 6889ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 6890ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 6891ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 68925552b385SBrandon CheckExtension(extEGADSlite, isEGADSlite); 6893ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 6894ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 68955552b385SBrandon CheckExtension(extIGES2, isIGES2); 6896ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 68975552b385SBrandon CheckExtension(extSTEP2, isSTEP2); 68985552b385SBrandon CheckExtension(extBREP, isBREP); 6899ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 69006f2c871aSStefano Zampini CheckExtension(extXDMFHDF5, isXDMFHDF5); 6901ef3a5affSJacob Faibussowitsch 6902ef3a5affSJacob Faibussowitsch #undef CheckExtension 6903ef3a5affSJacob Faibussowitsch 6904de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 69059566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 6906ca522641SMatthew G. Knepley } else if (isCGNS) { 69079566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 690890c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 69099566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 69102f0bd6dcSMichael Lange } else if (isFluent) { 69119566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 6912cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 6913cc2f8f65SMatthew G. Knepley PetscViewer viewer; 6914cc2f8f65SMatthew G. Knepley 691543b242b4SVaclav Hapla /* PETSC_VIEWER_HDF5_XDMF is used if the filename ends with .xdmf.h5, or if -dm_plex_create_from_hdf5_xdmf option is present */ 69166f2c871aSStefano Zampini PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &isXDMFHDF5, NULL)); 69179566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 69189566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 69199566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 69209566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 69219566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 69229566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 6923cd7e8a5eSksagiyam 69249566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 6925f4f49eeaSPierre Jolivet PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 69269566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 69276f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 69289566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 69296f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPopFormat(viewer)); 69309566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 69315fd9971aSMatthew G. Knepley 69325fd9971aSMatthew G. Knepley if (interpolate) { 69335fd9971aSMatthew G. Knepley DM idm; 69345fd9971aSMatthew G. Knepley 69359566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 69369566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 69375fd9971aSMatthew G. Knepley *dm = idm; 69385fd9971aSMatthew G. Knepley } 6939f2801cd6SMatthew G. Knepley } else if (isPLY) { 69409566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 69415552b385SBrandon } else if (isEGADSlite || isEGADS || isIGES || isIGES2 || isSTEP || isSTEP2 || isBREP) { 69425552b385SBrandon PetscCall(DMPlexCreateGeomFromFile(comm, filename, dm, isEGADSlite)); 69435552b385SBrandon 69447bee2925SMatthew Knepley if (!interpolate) { 69457bee2925SMatthew Knepley DM udm; 69467bee2925SMatthew Knepley 69479566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 69489566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 69497bee2925SMatthew Knepley *dm = udm; 69507bee2925SMatthew Knepley } 69518ca92349SMatthew G. Knepley } else if (isCV) { 69529566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 695398921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 69549566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 6955f4f49eeaSPierre Jolivet if (len) PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 69569566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 69573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6958ca522641SMatthew G. Knepley } 695912b8a6daSStefano Zampini 6960cc4c1da9SBarry Smith /*@ 69619f6c5813SMatthew G. Knepley DMPlexCreateEphemeral - This takes a `DMPlexTransform` and a base `DMPlex` and produces an ephemeral `DM`, meaning one that is created on the fly in response to queries. 69629f6c5813SMatthew G. Knepley 69630528010dSStefano Zampini Input Parameters: 69640528010dSStefano Zampini + tr - The `DMPlexTransform` 69650528010dSStefano Zampini - prefix - An options prefix, or NULL 69669f6c5813SMatthew G. Knepley 69679f6c5813SMatthew G. Knepley Output Parameter: 69689f6c5813SMatthew G. Knepley . dm - The `DM` 69699f6c5813SMatthew G. Knepley 69709f6c5813SMatthew G. Knepley Level: beginner 69719f6c5813SMatthew G. Knepley 697220f4b53cSBarry Smith Notes: 697320f4b53cSBarry Smith An emphemeral mesh is one that is not stored concretely, as in the default `DMPLEX` implementation, but rather is produced on the fly in response to queries, using information from the transform and the base mesh. 697420f4b53cSBarry Smith 69759f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 69769f6c5813SMatthew G. Knepley @*/ 69770528010dSStefano Zampini PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, const char prefix[], DM *dm) 69789f6c5813SMatthew G. Knepley { 69790528010dSStefano Zampini DM bdm, bcdm, cdm; 69800528010dSStefano Zampini Vec coordinates, coordinatesNew; 69810528010dSStefano Zampini PetscSection cs; 6982817b2c36SMatthew G. Knepley PetscInt cdim, Nl; 69839f6c5813SMatthew G. Knepley 69849f6c5813SMatthew G. Knepley PetscFunctionBegin; 69859f6c5813SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm)); 69869f6c5813SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 69870528010dSStefano Zampini ((DM_Plex *)(*dm)->data)->interpolated = DMPLEX_INTERPOLATED_FULL; 69880528010dSStefano Zampini // Handle coordinates 69890528010dSStefano Zampini PetscCall(DMPlexTransformGetDM(tr, &bdm)); 6990817b2c36SMatthew G. Knepley PetscCall(DMPlexTransformSetDimensions(tr, bdm, *dm)); 6991817b2c36SMatthew G. Knepley PetscCall(DMGetCoordinateDim(*dm, &cdim)); 69920528010dSStefano Zampini PetscCall(DMGetCoordinateDM(bdm, &bcdm)); 69930528010dSStefano Zampini PetscCall(DMGetCoordinateDM(*dm, &cdm)); 69940528010dSStefano Zampini PetscCall(DMCopyDisc(bcdm, cdm)); 69950528010dSStefano Zampini PetscCall(DMGetLocalSection(cdm, &cs)); 69960528010dSStefano Zampini PetscCall(PetscSectionSetNumFields(cs, 1)); 69970528010dSStefano Zampini PetscCall(PetscSectionSetFieldComponents(cs, 0, cdim)); 69980528010dSStefano Zampini PetscCall(DMGetCoordinatesLocal(bdm, &coordinates)); 69990528010dSStefano Zampini PetscCall(VecDuplicate(coordinates, &coordinatesNew)); 70000528010dSStefano Zampini PetscCall(VecCopy(coordinates, coordinatesNew)); 70010528010dSStefano Zampini PetscCall(DMSetCoordinatesLocal(*dm, coordinatesNew)); 70020528010dSStefano Zampini PetscCall(VecDestroy(&coordinatesNew)); 70039f6c5813SMatthew G. Knepley 70049f6c5813SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)tr)); 70059f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr)); 70069f6c5813SMatthew G. Knepley ((DM_Plex *)(*dm)->data)->tr = tr; 70070528010dSStefano Zampini PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE)); 70080528010dSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix)); 70090528010dSStefano Zampini PetscCall(DMSetFromOptions(*dm)); 70109f6c5813SMatthew G. Knepley 70119f6c5813SMatthew G. Knepley PetscCall(DMGetNumLabels(bdm, &Nl)); 70129f6c5813SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 70139f6c5813SMatthew G. Knepley DMLabel label, labelNew; 70149f6c5813SMatthew G. Knepley const char *lname; 70159f6c5813SMatthew G. Knepley PetscBool isDepth, isCellType; 70169f6c5813SMatthew G. Knepley 70179f6c5813SMatthew G. Knepley PetscCall(DMGetLabelName(bdm, l, &lname)); 70189f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 70199f6c5813SMatthew G. Knepley if (isDepth) continue; 70209f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "celltype", &isCellType)); 70219f6c5813SMatthew G. Knepley if (isCellType) continue; 70229f6c5813SMatthew G. Knepley PetscCall(DMCreateLabel(*dm, lname)); 70239f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(bdm, lname, &label)); 70249f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(*dm, lname, &labelNew)); 70259f6c5813SMatthew G. Knepley PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL)); 70269f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetLabel(labelNew, label)); 70279f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetTransform(labelNew, tr)); 70289f6c5813SMatthew G. Knepley PetscCall(DMLabelSetUp(labelNew)); 70299f6c5813SMatthew G. Knepley } 70303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70319f6c5813SMatthew G. Knepley } 7032