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) { 338*530e699aSMatthew G. Knepley PetscInt dof; 339*530e699aSMatthew G. Knepley 340*530e699aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cs, p, &dof)); 341*530e699aSMatthew G. Knepley if (dof) { 342ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetDof(csNew, p, cdim)); 343ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csNew, p, 0, cdim)); 344ac9d17c7SMatthew G. Knepley } 345*530e699aSMatthew G. Knepley } 346ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetUp(csNew)); 347ac9d17c7SMatthew G. Knepley } 348ac9d17c7SMatthew G. Knepley PetscCall(DMSetLocalSection(cdm, csNew)); 349ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionDestroy(&csNew)); 350*530e699aSMatthew G. Knepley // Reset coordinate dimension for coordinate DM 351*530e699aSMatthew G. Knepley PetscCall(DMSetCoordinateDim(cdm, cdim)); 352*530e699aSMatthew G. Knepley PetscCall(DMSetCoordinateField(cdm, NULL)); 353ac9d17c7SMatthew G. Knepley // Inject coordinates into higher dimension 354ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 355ac9d17c7SMatthew G. Knepley PetscCall(VecGetBlockSize(coordinates, &bs)); 356ac9d17c7SMatthew G. Knepley PetscCheck(bs == dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension"); 357ac9d17c7SMatthew G. Knepley PetscCall(VecCreate(PetscObjectComm((PetscObject)coordinates), &coordinatesNew)); 358ac9d17c7SMatthew G. Knepley PetscCall(VecGetType(coordinates, &vectype)); 359ac9d17c7SMatthew G. Knepley PetscCall(VecSetType(coordinatesNew, vectype)); 360ac9d17c7SMatthew G. Knepley PetscCall(VecGetLocalSize(coordinates, &n)); 361ac9d17c7SMatthew G. Knepley PetscCheck(!(n % bs), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension"); 362ac9d17c7SMatthew G. Knepley n /= bs; 363ac9d17c7SMatthew G. Knepley PetscCall(VecSetSizes(coordinatesNew, n * cdim, PETSC_DETERMINE)); 364ac9d17c7SMatthew G. Knepley PetscCall(VecSetUp(coordinatesNew)); 365ac9d17c7SMatthew G. Knepley PetscCall(PetscMalloc1(n * bs, &indices)); 366ac9d17c7SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) 367ac9d17c7SMatthew G. Knepley for (PetscInt b = 0; b < bs; ++b) indices[i * bs + b] = i * cdim + b; 368ac9d17c7SMatthew G. Knepley PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n * bs, indices, PETSC_OWN_POINTER, &idx)); 369ac9d17c7SMatthew G. Knepley PetscCall(VecISCopy(coordinatesNew, idx, SCATTER_FORWARD, coordinates)); 370ac9d17c7SMatthew G. Knepley PetscCall(ISDestroy(&idx)); 371ac9d17c7SMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinatesNew)); 372ac9d17c7SMatthew G. Knepley PetscCall(VecDestroy(&coordinatesNew)); 373ac9d17c7SMatthew G. Knepley PetscCall(DMSetCoordinateDim(dm, cdim)); 374ac9d17c7SMatthew G. Knepley { 375ac9d17c7SMatthew G. Knepley PetscInt gn; 376ac9d17c7SMatthew G. Knepley 377ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinates(dm, &coordinatesNew)); 378ac9d17c7SMatthew G. Knepley PetscCall(VecGetLocalSize(coordinatesNew, &gn)); 379ac9d17c7SMatthew G. Knepley PetscCheck(gn == n * cdim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Global coordinate size %" PetscInt_FMT " != %" PetscInt_FMT "local coordinate size", gn, n * cdim); 380ac9d17c7SMatthew G. Knepley } 381ac9d17c7SMatthew G. Knepley dE = cdim; 382*530e699aSMatthew G. Knepley project = PETSC_FALSE; 383ac9d17c7SMatthew G. Knepley } 384e44f6aebSMatthew G. Knepley if (degree >= 0) { 385e44f6aebSMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 386e44f6aebSMatthew G. Knepley PetscInt cStart, cEnd, gct; 387dc431b0cSMatthew G. Knepley 3881df12153SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd)); 389dc431b0cSMatthew G. Knepley if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 390e44f6aebSMatthew G. Knepley gct = (PetscInt)ct; 391462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &gct, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm))); 392e44f6aebSMatthew G. Knepley ct = (DMPolytopeType)gct; 393e44f6aebSMatthew G. Knepley // Work around current bug in PetscDualSpaceSetUp_Lagrange() 394e44f6aebSMatthew G. Knepley // Can be seen in plex_tutorials-ex10_1 395e44f6aebSMatthew G. Knepley if (ct != DM_POLYTOPE_SEG_PRISM_TENSOR && ct != DM_POLYTOPE_TRI_PRISM_TENSOR && ct != DM_POLYTOPE_QUAD_PRISM_TENSOR) PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe)); 3964f9ab2b4SJed Brown } 397e44f6aebSMatthew G. Knepley PetscCall(DMSetCoordinateDisc(dm, fe, project)); 3989566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 3999318fe57SMatthew G. Knepley mesh->coordFunc = coordFunc; 4003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4019318fe57SMatthew G. Knepley } 4029318fe57SMatthew G. Knepley 4031df5d5c5SMatthew G. Knepley /*@ 4041df5d5c5SMatthew G. Knepley DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 4051df5d5c5SMatthew G. Knepley 406d083f849SBarry Smith Collective 4071df5d5c5SMatthew G. Knepley 4081df5d5c5SMatthew G. Knepley Input Parameters: 409a1cb98faSBarry Smith + comm - The communicator for the `DM` object 4101df5d5c5SMatthew G. Knepley . dim - The spatial dimension 4111df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells 4121df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces) 4131df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 4141df5d5c5SMatthew G. Knepley 4151df5d5c5SMatthew G. Knepley Output Parameter: 41660225df5SJacob Faibussowitsch . newdm - The `DM` object 4171df5d5c5SMatthew G. Knepley 4181df5d5c5SMatthew G. Knepley Level: beginner 4191df5d5c5SMatthew G. Knepley 4201cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()` 4211df5d5c5SMatthew G. Knepley @*/ 422d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) 423d71ae5a4SJacob Faibussowitsch { 4241df5d5c5SMatthew G. Knepley DM dm; 4251df5d5c5SMatthew G. Knepley PetscMPIInt rank; 4261df5d5c5SMatthew G. Knepley 4271df5d5c5SMatthew G. Knepley PetscFunctionBegin; 4289566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &dm)); 4299566063dSJacob Faibussowitsch PetscCall(DMSetType(dm, DMPLEX)); 4309566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 43146139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 4329566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 433ce78fa2fSMatthew G. Knepley switch (dim) { 434ce78fa2fSMatthew G. Knepley case 2: 4359566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular")); 4369566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral")); 437ce78fa2fSMatthew G. Knepley break; 438ce78fa2fSMatthew G. Knepley case 3: 4399566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral")); 4409566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral")); 441ce78fa2fSMatthew G. Knepley break; 442d71ae5a4SJacob Faibussowitsch default: 443d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 444ce78fa2fSMatthew G. Knepley } 4451df5d5c5SMatthew G. Knepley if (rank) { 4461df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {0, 0}; 4479566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL)); 4481df5d5c5SMatthew G. Knepley } else { 4491df5d5c5SMatthew G. Knepley switch (dim) { 4501df5d5c5SMatthew G. Knepley case 2: 4511df5d5c5SMatthew G. Knepley if (simplex) { 4521df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {4, 2}; 4531df5d5c5SMatthew G. Knepley PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 4541df5d5c5SMatthew G. Knepley PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 4551df5d5c5SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 4561df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 4571df5d5c5SMatthew G. Knepley 4589566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4591df5d5c5SMatthew G. Knepley } else { 4601df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {6, 2}; 4611df5d5c5SMatthew G. Knepley PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 4621df5d5c5SMatthew G. Knepley PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 4631df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 4641df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[12] = {-1.0, -0.5, 0.0, -0.5, 0.0, 0.5, -1.0, 0.5, 1.0, -0.5, 1.0, 0.5}; 4651df5d5c5SMatthew G. Knepley 4669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4671df5d5c5SMatthew G. Knepley } 4681df5d5c5SMatthew G. Knepley break; 4691df5d5c5SMatthew G. Knepley case 3: 4701df5d5c5SMatthew G. Knepley if (simplex) { 4711df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {5, 2}; 4721df5d5c5SMatthew G. Knepley PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 4731df5d5c5SMatthew G. Knepley PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 4741df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 4751df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[15] = {-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0}; 4761df5d5c5SMatthew G. Knepley 4779566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4781df5d5c5SMatthew G. Knepley } else { 4791df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {12, 2}; 4801df5d5c5SMatthew G. Knepley PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 4811df5d5c5SMatthew G. Knepley PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 4821df5d5c5SMatthew G. Knepley PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 4839371c9d4SSatish Balay PetscScalar vertexCoords[36] = {-1.0, -0.5, -0.5, -1.0, 0.5, -0.5, 0.0, 0.5, -0.5, 0.0, -0.5, -0.5, -1.0, -0.5, 0.5, 0.0, -0.5, 0.5, 0.0, 0.5, 0.5, -1.0, 0.5, 0.5, 1.0, 0.5, -0.5, 1.0, -0.5, -0.5, 1.0, -0.5, 0.5, 1.0, 0.5, 0.5}; 4841df5d5c5SMatthew G. Knepley 4859566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4861df5d5c5SMatthew G. Knepley } 4871df5d5c5SMatthew G. Knepley break; 488d71ae5a4SJacob Faibussowitsch default: 489d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 4901df5d5c5SMatthew G. Knepley } 4911df5d5c5SMatthew G. Knepley } 49246139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 4931df5d5c5SMatthew G. Knepley *newdm = dm; 4941df5d5c5SMatthew G. Knepley if (refinementLimit > 0.0) { 4951df5d5c5SMatthew G. Knepley DM rdm; 4961df5d5c5SMatthew G. Knepley const char *name; 4971df5d5c5SMatthew G. Knepley 4989566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 4999566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 5009566063dSJacob Faibussowitsch PetscCall(DMRefine(*newdm, comm, &rdm)); 5019566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)*newdm, &name)); 5029566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, name)); 5039566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 5041df5d5c5SMatthew G. Knepley *newdm = rdm; 5051df5d5c5SMatthew G. Knepley } 5061df5d5c5SMatthew G. Knepley if (interpolate) { 5075fd9971aSMatthew G. Knepley DM idm; 5081df5d5c5SMatthew G. Knepley 5099566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*newdm, &idm)); 5109566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 5111df5d5c5SMatthew G. Knepley *newdm = idm; 5121df5d5c5SMatthew G. Knepley } 5133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5141df5d5c5SMatthew G. Knepley } 5151df5d5c5SMatthew G. Knepley 516d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 517d71ae5a4SJacob Faibussowitsch { 5189318fe57SMatthew G. Knepley const PetscInt numVertices = 2; 5199318fe57SMatthew G. Knepley PetscInt markerRight = 1; 5209318fe57SMatthew G. Knepley PetscInt markerLeft = 1; 5219318fe57SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 5229318fe57SMatthew G. Knepley Vec coordinates; 5239318fe57SMatthew G. Knepley PetscSection coordSection; 5249318fe57SMatthew G. Knepley PetscScalar *coords; 5259318fe57SMatthew G. Knepley PetscInt coordSize; 5269318fe57SMatthew G. Knepley PetscMPIInt rank; 5279318fe57SMatthew G. Knepley PetscInt cdim = 1, v; 528552f7358SJed Brown 5299318fe57SMatthew G. Knepley PetscFunctionBegin; 5309566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 5319318fe57SMatthew G. Knepley if (markerSeparate) { 5329318fe57SMatthew G. Knepley markerRight = 2; 5339318fe57SMatthew G. Knepley markerLeft = 1; 5349318fe57SMatthew G. Knepley } 5359566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 536c5853193SPierre Jolivet if (rank == 0) { 5379566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numVertices)); 5389566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 5399566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft)); 5409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight)); 5419318fe57SMatthew G. Knepley } 5429566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 5439566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 5449318fe57SMatthew G. Knepley /* Build coordinates */ 5459566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 5469566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 5479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 5489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, 0, numVertices)); 5499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 5509318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 5519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 5529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 5539318fe57SMatthew G. Knepley } 5549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 5559566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 5569566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 5579566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 5589566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 5599566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 5609566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 5619566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5629318fe57SMatthew G. Knepley coords[0] = lower[0]; 5639318fe57SMatthew G. Knepley coords[1] = upper[0]; 5649566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 5659566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 5669566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 5673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5689318fe57SMatthew G. Knepley } 56926492d91SMatthew G. Knepley 570d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 571d71ae5a4SJacob Faibussowitsch { 5721df21d24SMatthew G. Knepley const PetscInt numVertices = (edges[0] + 1) * (edges[1] + 1); 5731df21d24SMatthew G. Knepley const PetscInt numEdges = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1]; 574552f7358SJed Brown PetscInt markerTop = 1; 575552f7358SJed Brown PetscInt markerBottom = 1; 576552f7358SJed Brown PetscInt markerRight = 1; 577552f7358SJed Brown PetscInt markerLeft = 1; 578552f7358SJed Brown PetscBool markerSeparate = PETSC_FALSE; 579552f7358SJed Brown Vec coordinates; 580552f7358SJed Brown PetscSection coordSection; 581552f7358SJed Brown PetscScalar *coords; 582552f7358SJed Brown PetscInt coordSize; 583552f7358SJed Brown PetscMPIInt rank; 584552f7358SJed Brown PetscInt v, vx, vy; 585552f7358SJed Brown 586552f7358SJed Brown PetscFunctionBegin; 5879566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 588552f7358SJed Brown if (markerSeparate) { 5891df21d24SMatthew G. Knepley markerTop = 3; 5901df21d24SMatthew G. Knepley markerBottom = 1; 5911df21d24SMatthew G. Knepley markerRight = 2; 5921df21d24SMatthew G. Knepley markerLeft = 4; 593552f7358SJed Brown } 5949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 595dd400576SPatrick Sanan if (rank == 0) { 596552f7358SJed Brown PetscInt e, ex, ey; 597552f7358SJed Brown 5989566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices)); 59948a46eb9SPierre Jolivet for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 6009566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 601552f7358SJed Brown for (vx = 0; vx <= edges[0]; vx++) { 602552f7358SJed Brown for (ey = 0; ey < edges[1]; ey++) { 603552f7358SJed Brown PetscInt edge = vx * edges[1] + ey + edges[0] * (edges[1] + 1); 604552f7358SJed Brown PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges; 605da80777bSKarl Rupp PetscInt cone[2]; 606552f7358SJed Brown 6079371c9d4SSatish Balay cone[0] = vertex; 6089371c9d4SSatish Balay cone[1] = vertex + edges[0] + 1; 6099566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 610552f7358SJed Brown if (vx == edges[0]) { 6119566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 6129566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 613552f7358SJed Brown if (ey == edges[1] - 1) { 6149566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 6159566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 616552f7358SJed Brown } 617552f7358SJed Brown } else if (vx == 0) { 6189566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 6199566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 620552f7358SJed Brown if (ey == edges[1] - 1) { 6219566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 6229566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft)); 623552f7358SJed Brown } 624552f7358SJed Brown } 625552f7358SJed Brown } 626552f7358SJed Brown } 627552f7358SJed Brown for (vy = 0; vy <= edges[1]; vy++) { 628552f7358SJed Brown for (ex = 0; ex < edges[0]; ex++) { 629552f7358SJed Brown PetscInt edge = vy * edges[0] + ex; 630552f7358SJed Brown PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges; 631da80777bSKarl Rupp PetscInt cone[2]; 632552f7358SJed Brown 6339371c9d4SSatish Balay cone[0] = vertex; 6349371c9d4SSatish Balay cone[1] = vertex + 1; 6359566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 636552f7358SJed Brown if (vy == edges[1]) { 6379566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 6389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 639552f7358SJed Brown if (ex == edges[0] - 1) { 6409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 6419566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 642552f7358SJed Brown } 643552f7358SJed Brown } else if (vy == 0) { 6449566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 6459566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 646552f7358SJed Brown if (ex == edges[0] - 1) { 6479566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 6489566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 649552f7358SJed Brown } 650552f7358SJed Brown } 651552f7358SJed Brown } 652552f7358SJed Brown } 653552f7358SJed Brown } 6549566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 6559566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 656552f7358SJed Brown /* Build coordinates */ 6579566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 2)); 6589566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 6599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 6609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 6619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 662552f7358SJed Brown for (v = numEdges; v < numEdges + numVertices; ++v) { 6639566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 2)); 6649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 665552f7358SJed Brown } 6669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 6689566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 6699566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 6709566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 6719566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 2)); 6729566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 6739566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 674552f7358SJed Brown for (vy = 0; vy <= edges[1]; ++vy) { 675552f7358SJed Brown for (vx = 0; vx <= edges[0]; ++vx) { 676552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx; 677552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy; 678552f7358SJed Brown } 679552f7358SJed Brown } 6809566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 6819566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 6829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 6833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 684552f7358SJed Brown } 685552f7358SJed Brown 686d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 687d71ae5a4SJacob Faibussowitsch { 6889e8abbc3SMichael Lange PetscInt vertices[3], numVertices; 6897b59f5a9SMichael Lange PetscInt numFaces = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2]; 690c2df9bbfSMatthew G. Knepley PetscInt markerTop = 1; 691c2df9bbfSMatthew G. Knepley PetscInt markerBottom = 1; 692c2df9bbfSMatthew G. Knepley PetscInt markerFront = 1; 693c2df9bbfSMatthew G. Knepley PetscInt markerBack = 1; 694c2df9bbfSMatthew G. Knepley PetscInt markerRight = 1; 695c2df9bbfSMatthew G. Knepley PetscInt markerLeft = 1; 696c2df9bbfSMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 697552f7358SJed Brown Vec coordinates; 698552f7358SJed Brown PetscSection coordSection; 699552f7358SJed Brown PetscScalar *coords; 700552f7358SJed Brown PetscInt coordSize; 701552f7358SJed Brown PetscMPIInt rank; 702552f7358SJed Brown PetscInt v, vx, vy, vz; 7037b59f5a9SMichael Lange PetscInt voffset, iface = 0, cone[4]; 704552f7358SJed Brown 705552f7358SJed Brown PetscFunctionBegin; 7061dca8a05SBarry Smith PetscCheck(faces[0] >= 1 && faces[1] >= 1 && faces[2] >= 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Must have at least 1 face per side"); 7079566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 708c2df9bbfSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 709c2df9bbfSMatthew G. Knepley if (markerSeparate) { 710c2df9bbfSMatthew G. Knepley markerBottom = 1; 711c2df9bbfSMatthew G. Knepley markerTop = 2; 712c2df9bbfSMatthew G. Knepley markerFront = 3; 713c2df9bbfSMatthew G. Knepley markerBack = 4; 714c2df9bbfSMatthew G. Knepley markerRight = 5; 715c2df9bbfSMatthew G. Knepley markerLeft = 6; 716c2df9bbfSMatthew G. Knepley } 7179371c9d4SSatish Balay vertices[0] = faces[0] + 1; 7189371c9d4SSatish Balay vertices[1] = faces[1] + 1; 7199371c9d4SSatish Balay vertices[2] = faces[2] + 1; 7209e8abbc3SMichael Lange numVertices = vertices[0] * vertices[1] * vertices[2]; 721dd400576SPatrick Sanan if (rank == 0) { 722552f7358SJed Brown PetscInt f; 723552f7358SJed Brown 7249566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices)); 72548a46eb9SPierre Jolivet for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 7269566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 7277b59f5a9SMichael Lange 7287b59f5a9SMichael Lange /* Side 0 (Top) */ 7297b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7307b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7317b59f5a9SMichael Lange voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx; 7329371c9d4SSatish Balay cone[0] = voffset; 7339371c9d4SSatish Balay cone[1] = voffset + 1; 7349371c9d4SSatish Balay cone[2] = voffset + vertices[0] + 1; 7359371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 7369566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 737c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop)); 738c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop)); 739c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop)); 740c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop)); 741c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop)); 7427b59f5a9SMichael Lange iface++; 743552f7358SJed Brown } 744552f7358SJed Brown } 7457b59f5a9SMichael Lange 7467b59f5a9SMichael Lange /* Side 1 (Bottom) */ 7477b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7487b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7497b59f5a9SMichael Lange voffset = numFaces + vy * (faces[0] + 1) + vx; 7509371c9d4SSatish Balay cone[0] = voffset + 1; 7519371c9d4SSatish Balay cone[1] = voffset; 7529371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 7539371c9d4SSatish Balay cone[3] = voffset + vertices[0] + 1; 7549566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 755c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom)); 756c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom)); 757c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom)); 758c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom)); 759c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom)); 7607b59f5a9SMichael Lange iface++; 761552f7358SJed Brown } 762552f7358SJed Brown } 7637b59f5a9SMichael Lange 7647b59f5a9SMichael Lange /* Side 2 (Front) */ 7657b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 7667b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7677b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vx; 7689371c9d4SSatish Balay cone[0] = voffset; 7699371c9d4SSatish Balay cone[1] = voffset + 1; 7709371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + 1; 7719371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1]; 7729566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 773c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront)); 774c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront)); 775c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront)); 776c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront)); 777c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront)); 7787b59f5a9SMichael Lange iface++; 779552f7358SJed Brown } 7807b59f5a9SMichael Lange } 7817b59f5a9SMichael Lange 7827b59f5a9SMichael Lange /* Side 3 (Back) */ 7837b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 7847b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7857b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx; 7869371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 7879371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1] + 1; 7889371c9d4SSatish Balay cone[2] = voffset + 1; 7899371c9d4SSatish Balay cone[3] = voffset; 7909566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 791c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack)); 792c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack)); 793c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack)); 794c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack)); 795c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack)); 7967b59f5a9SMichael Lange iface++; 7977b59f5a9SMichael Lange } 7987b59f5a9SMichael Lange } 7997b59f5a9SMichael Lange 8007b59f5a9SMichael Lange /* Side 4 (Left) */ 8017b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8027b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 8037b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0]; 8049371c9d4SSatish Balay cone[0] = voffset; 8059371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1]; 8069371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + vertices[0]; 8079371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 8089566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 809c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft)); 810c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft)); 811c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft)); 812c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft)); 813c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft)); 8147b59f5a9SMichael Lange iface++; 8157b59f5a9SMichael Lange } 8167b59f5a9SMichael Lange } 8177b59f5a9SMichael Lange 8187b59f5a9SMichael Lange /* Side 5 (Right) */ 8197b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8207b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 821aab5bcd8SJed Brown voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0]; 8229371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 8239371c9d4SSatish Balay cone[1] = voffset; 8249371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 8259371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1] + vertices[0]; 8269566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 827c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight)); 828c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight)); 829c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight)); 830c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight)); 831c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight)); 8327b59f5a9SMichael Lange iface++; 8337b59f5a9SMichael Lange } 834552f7358SJed Brown } 835552f7358SJed Brown } 8369566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 8379566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 838552f7358SJed Brown /* Build coordinates */ 8399566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 3)); 8409566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 8429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 8439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 844552f7358SJed Brown for (v = numFaces; v < numFaces + numVertices; ++v) { 8459566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 3)); 8469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 847552f7358SJed Brown } 8489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 8499566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 8509566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 8519566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 8529566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 8539566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 3)); 8549566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 8559566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 856552f7358SJed Brown for (vz = 0; vz <= faces[2]; ++vz) { 857552f7358SJed Brown for (vy = 0; vy <= faces[1]; ++vy) { 858552f7358SJed Brown for (vx = 0; vx <= faces[0]; ++vx) { 859552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx; 860552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy; 861552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz; 862552f7358SJed Brown } 863552f7358SJed Brown } 864552f7358SJed Brown } 8659566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 8669566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 8679566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 8683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 869552f7358SJed Brown } 870552f7358SJed Brown 871d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) 872d71ae5a4SJacob Faibussowitsch { 8739318fe57SMatthew G. Knepley PetscFunctionBegin; 8749318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 87546139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 8769566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim - 1)); 8779566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim)); 8789318fe57SMatthew G. Knepley switch (dim) { 879d71ae5a4SJacob Faibussowitsch case 1: 880d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces)); 881d71ae5a4SJacob Faibussowitsch break; 882d71ae5a4SJacob Faibussowitsch case 2: 883d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces)); 884d71ae5a4SJacob Faibussowitsch break; 885d71ae5a4SJacob Faibussowitsch case 3: 886d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces)); 887d71ae5a4SJacob Faibussowitsch break; 888d71ae5a4SJacob Faibussowitsch default: 889d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim); 8909318fe57SMatthew G. Knepley } 89146139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 8929566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 8933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8949318fe57SMatthew G. Knepley } 8959318fe57SMatthew G. Knepley 8969318fe57SMatthew G. Knepley /*@C 8979318fe57SMatthew G. Knepley DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra). 8989318fe57SMatthew G. Knepley 8999318fe57SMatthew G. Knepley Collective 9009318fe57SMatthew G. Knepley 9019318fe57SMatthew G. Knepley Input Parameters: 902a1cb98faSBarry Smith + comm - The communicator for the `DM` object 90320f4b53cSBarry Smith . dim - The spatial dimension of the box, so the resulting mesh is has dimension `dim`-1 90420f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 90520f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 90620f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 9079318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 9089318fe57SMatthew G. Knepley 9099318fe57SMatthew G. Knepley Output Parameter: 910a1cb98faSBarry Smith . dm - The `DM` object 9119318fe57SMatthew G. Knepley 9129318fe57SMatthew G. Knepley Level: beginner 9139318fe57SMatthew G. Knepley 9141cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()` 9159318fe57SMatthew G. Knepley @*/ 916d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) 917d71ae5a4SJacob Faibussowitsch { 9189318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 9199318fe57SMatthew G. Knepley PetscReal low[3] = {0, 0, 0}; 9209318fe57SMatthew G. Knepley PetscReal upp[3] = {1, 1, 1}; 9219318fe57SMatthew G. Knepley 9229318fe57SMatthew G. Knepley PetscFunctionBegin; 9239566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 9249566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 9259566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate)); 9263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9279318fe57SMatthew G. Knepley } 9289318fe57SMatthew G. Knepley 929d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd) 930d71ae5a4SJacob Faibussowitsch { 931fdbf62faSLisandro Dalcin PetscInt i, fStart, fEnd, numCells = 0, numVerts = 0; 932fdbf62faSLisandro Dalcin PetscInt numPoints[2], *coneSize, *cones, *coneOrientations; 933fdbf62faSLisandro Dalcin PetscScalar *vertexCoords; 934fdbf62faSLisandro Dalcin PetscReal L, maxCell; 935fdbf62faSLisandro Dalcin PetscBool markerSeparate = PETSC_FALSE; 936fdbf62faSLisandro Dalcin PetscInt markerLeft = 1, faceMarkerLeft = 1; 937fdbf62faSLisandro Dalcin PetscInt markerRight = 1, faceMarkerRight = 2; 938fdbf62faSLisandro Dalcin PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 939fdbf62faSLisandro Dalcin PetscMPIInt rank; 940fdbf62faSLisandro Dalcin 941fdbf62faSLisandro Dalcin PetscFunctionBegin; 9424f572ea9SToby Isaac PetscAssertPointer(dm, 1); 943fdbf62faSLisandro Dalcin 9449566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, 1)); 9459566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 9469566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 947fdbf62faSLisandro Dalcin 9489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 949dd400576SPatrick Sanan if (rank == 0) numCells = segments; 950dd400576SPatrick Sanan if (rank == 0) numVerts = segments + (wrap ? 0 : 1); 951fdbf62faSLisandro Dalcin 9529371c9d4SSatish Balay numPoints[0] = numVerts; 9539371c9d4SSatish Balay numPoints[1] = numCells; 9549566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords)); 9559566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts)); 956ad540459SPierre Jolivet for (i = 0; i < numCells; ++i) coneSize[i] = 2; 957ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0; 9589371c9d4SSatish Balay for (i = 0; i < numCells; ++i) { 9599371c9d4SSatish Balay cones[2 * i] = numCells + i % numVerts; 9609371c9d4SSatish Balay cones[2 * i + 1] = numCells + (i + 1) % numVerts; 9619371c9d4SSatish Balay } 962ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells); 9639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 9649566063dSJacob Faibussowitsch PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords)); 965fdbf62faSLisandro Dalcin 9669566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 9679371c9d4SSatish Balay if (markerSeparate) { 9689371c9d4SSatish Balay markerLeft = faceMarkerLeft; 9699371c9d4SSatish Balay markerRight = faceMarkerRight; 9709371c9d4SSatish Balay } 971dd400576SPatrick Sanan if (!wrap && rank == 0) { 9729566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 9739566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft)); 9749566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight)); 9759566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft)); 9769566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight)); 977fdbf62faSLisandro Dalcin } 978fdbf62faSLisandro Dalcin if (wrap) { 979fdbf62faSLisandro Dalcin L = upper - lower; 980fdbf62faSLisandro Dalcin maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments)); 9814fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L)); 982fdbf62faSLisandro Dalcin } 9839566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 9843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 985fdbf62faSLisandro Dalcin } 986fdbf62faSLisandro Dalcin 9874054ae39SJames Wright // Creates "Face Sets" label based on the standard box labeling conventions 988d7d2d1d2SJames Wright static PetscErrorCode DMPlexSetBoxLabel_Internal(DM dm, const DMBoundaryType periodicity[]) 9894054ae39SJames Wright { 9906ff49feeSJames Wright DM cdm; 9916ff49feeSJames Wright PetscSection csection; 9926ff49feeSJames Wright Vec coordinates; 9934054ae39SJames Wright DMLabel label; 9946ff49feeSJames Wright IS faces_is; 9952b4f33d9SJames Wright PetscInt dim, num_face = 0; 9964054ae39SJames Wright const PetscInt *faces; 9974054ae39SJames Wright PetscInt faceMarkerBottom, faceMarkerTop, faceMarkerFront, faceMarkerBack, faceMarkerRight, faceMarkerLeft; 9984054ae39SJames Wright 9994054ae39SJames Wright PetscFunctionBeginUser; 10004054ae39SJames Wright PetscCall(DMGetDimension(dm, &dim)); 1001d7c1f440SPierre Jolivet PetscCheck((dim == 2) || (dim == 3), PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "DMPlex box labeling only supports 2D and 3D meshes, received DM of dimension %" PetscInt_FMT, dim); 10024054ae39SJames Wright // Get Face Sets label 10034054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 10044054ae39SJames Wright if (label) { 10054054ae39SJames Wright PetscCall(DMLabelReset(label)); 10064054ae39SJames Wright } else { 10074054ae39SJames Wright PetscCall(DMCreateLabel(dm, "Face Sets")); 10084054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 10094054ae39SJames Wright } 10104054ae39SJames Wright PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label)); 10116ff49feeSJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", 1, &faces_is)); 10124054ae39SJames Wright 10134054ae39SJames Wright switch (dim) { 10144054ae39SJames Wright case 2: 10154054ae39SJames Wright faceMarkerTop = 3; 10164054ae39SJames Wright faceMarkerBottom = 1; 10174054ae39SJames Wright faceMarkerRight = 2; 10184054ae39SJames Wright faceMarkerLeft = 4; 10194054ae39SJames Wright break; 10204054ae39SJames Wright case 3: 10214054ae39SJames Wright faceMarkerBottom = 1; 10224054ae39SJames Wright faceMarkerTop = 2; 10234054ae39SJames Wright faceMarkerFront = 3; 10244054ae39SJames Wright faceMarkerBack = 4; 10254054ae39SJames Wright faceMarkerRight = 5; 10264054ae39SJames Wright faceMarkerLeft = 6; 10274054ae39SJames Wright break; 10284054ae39SJames Wright default: 10294054ae39SJames Wright SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 10304054ae39SJames Wright } 10314054ae39SJames Wright 10322b4f33d9SJames Wright if (faces_is) PetscCall(ISGetLocalSize(faces_is, &num_face)); 10332b4f33d9SJames Wright if (faces_is) PetscCall(ISGetIndices(faces_is, &faces)); 10346ff49feeSJames Wright PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 10356ff49feeSJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 10366ff49feeSJames Wright PetscCall(DMGetLocalSection(cdm, &csection)); 10374054ae39SJames Wright for (PetscInt f = 0; f < num_face; ++f) { 10386ff49feeSJames Wright PetscScalar *coords = NULL; 10396ff49feeSJames Wright PetscInt face = faces[f], flip = 1, label_value = -1, coords_size; 10404054ae39SJames Wright 10414054ae39SJames Wright { // Determine if orientation of face is flipped 10424054ae39SJames Wright PetscInt num_cells_support, num_faces, start = -1; 10434054ae39SJames Wright const PetscInt *orients, *cell_faces, *cells; 10444054ae39SJames Wright 10454054ae39SJames Wright PetscCall(DMPlexGetSupport(dm, face, &cells)); 10464054ae39SJames Wright PetscCall(DMPlexGetSupportSize(dm, face, &num_cells_support)); 10474054ae39SJames Wright PetscCheck(num_cells_support == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Expected one cell in support of exterior face, but got %" PetscInt_FMT " cells", num_cells_support); 10484054ae39SJames Wright PetscCall(DMPlexGetCone(dm, cells[0], &cell_faces)); 10494054ae39SJames Wright PetscCall(DMPlexGetConeSize(dm, cells[0], &num_faces)); 10504054ae39SJames Wright for (PetscInt i = 0; i < num_faces; i++) { 10514054ae39SJames Wright if (cell_faces[i] == face) start = i; 10524054ae39SJames Wright } 10534054ae39SJames Wright PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Could not find face %" PetscInt_FMT " in cone of its support", face); 10544054ae39SJames Wright PetscCall(DMPlexGetConeOrientation(dm, cells[0], &orients)); 10554054ae39SJames Wright if (orients[start] < 0) flip = -1; 10564054ae39SJames Wright } 10574054ae39SJames Wright 10586ff49feeSJames Wright // Cannot use DMPlexComputeCellGeometryFVM() for high-order geometry, so must calculate normal vectors manually 10596ff49feeSJames Wright // Use the vertices (depth 0) of coordinate DM to calculate normal vector 10606ff49feeSJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 10614054ae39SJames Wright switch (dim) { 10624054ae39SJames Wright case 2: { 10636ff49feeSJames Wright PetscScalar vec[2]; 10646ff49feeSJames Wright 10656ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) vec[d] = flip * (PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d])); 10666ff49feeSJames Wright PetscScalar normal[] = {vec[1], -vec[0]}; 10676ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 10686ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 10694054ae39SJames Wright } else { 10706ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerTop : faceMarkerBottom; 10714054ae39SJames Wright } 10724054ae39SJames Wright } break; 10734054ae39SJames Wright case 3: { 10746ff49feeSJames Wright PetscScalar vec1[3], vec2[3], normal[3]; 10756ff49feeSJames Wright 10766ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) { 10776ff49feeSJames Wright vec1[d] = PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]); 10786ff49feeSJames Wright vec2[d] = PetscRealPart(coords[2 * dim + d]) - PetscRealPart(coords[1 * dim + d]); 10796ff49feeSJames Wright } 10806ff49feeSJames Wright 10816ff49feeSJames Wright // Calculate normal vector via cross-product 10826ff49feeSJames Wright normal[0] = flip * ((vec1[1] * vec2[2]) - (vec1[2] * vec2[1])); 10836ff49feeSJames Wright normal[1] = flip * ((vec1[2] * vec2[0]) - (vec1[0] * vec2[2])); 10846ff49feeSJames Wright normal[2] = flip * ((vec1[0] * vec2[1]) - (vec1[1] * vec2[0])); 10856ff49feeSJames Wright 10866ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 10876ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[2])) { 10886ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 10894054ae39SJames Wright } else { 10906ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 10914054ae39SJames Wright } 10924054ae39SJames Wright } else { 10936ff49feeSJames Wright if (PetscAbsScalar(normal[1]) > PetscAbsScalar(normal[2])) { 10946ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerBack : faceMarkerFront; 10954054ae39SJames Wright } else { 10966ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 10974054ae39SJames Wright } 10984054ae39SJames Wright } 10994054ae39SJames Wright } break; 11004054ae39SJames Wright } 11014054ae39SJames Wright 11024054ae39SJames Wright PetscInt previous_label_value; // always 1 due to DMPlexMarkBoundaryFaces call above 11034054ae39SJames Wright PetscCall(DMGetLabelValue(dm, "Face Sets", face, &previous_label_value)); 11044054ae39SJames Wright PetscCall(DMClearLabelValue(dm, "Face Sets", face, previous_label_value)); 11054054ae39SJames Wright PetscCall(DMSetLabelValue(dm, "Face Sets", face, label_value)); 11066ff49feeSJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 11074054ae39SJames Wright } 11082b4f33d9SJames Wright if (faces_is) PetscCall(ISRestoreIndices(faces_is, &faces)); 11096ff49feeSJames Wright PetscCall(ISDestroy(&faces_is)); 1110d7d2d1d2SJames Wright 1111d7d2d1d2SJames Wright // Create Isoperiodic SF from newly-created face labels 1112d7d2d1d2SJames Wright PetscSF periodicsfs[3]; 1113d7d2d1d2SJames Wright PetscInt periodic_sf_index = 0; 1114d7d2d1d2SJames Wright PetscScalar transform[3][4][4] = {{{0.}}}; 1115d7d2d1d2SJames Wright for (PetscInt d = 0; d < dim; d++) { 1116d7d2d1d2SJames Wright IS donor_is, periodic_is; 1117d7d2d1d2SJames Wright const PetscInt *donor_faces = NULL, *periodic_faces = NULL; 1118d7d2d1d2SJames Wright PetscInt num_donor = 0, num_periodic = 0; 1119d7d2d1d2SJames Wright PetscSF centroidsf; 1120d7d2d1d2SJames Wright PetscReal donor_to_periodic_distance; 1121d7d2d1d2SJames Wright const PetscInt face_pairings[2][3][2] = { 1122d7d2d1d2SJames Wright // 2D face pairings, {donor, periodic} 1123d7d2d1d2SJames Wright {{4, 2}, {1, 3}}, 1124d7d2d1d2SJames Wright // 3D face pairings 1125d7d2d1d2SJames Wright {{5, 6}, {3, 4}, {1, 2}} 1126d7d2d1d2SJames Wright }; 1127d7d2d1d2SJames Wright 1128d7d2d1d2SJames Wright if (periodicity[d] != DM_BOUNDARY_PERIODIC) continue; 1129d7d2d1d2SJames Wright { 1130d7d2d1d2SJames Wright // Compute centroidsf, which is the mapping from donor faces to periodic faces 1131d7d2d1d2SJames Wright // Matches the centroid of the faces together, ignoring the periodic direction component (which should not match between donor and periodic face) 1132d7d2d1d2SJames Wright PetscInt coords_size, centroid_comps = dim - 1; 1133d7d2d1d2SJames Wright PetscScalar *coords = NULL; 1134d7d2d1d2SJames Wright PetscReal *donor_centroids, *periodic_centroids; 1135d7d2d1d2SJames Wright PetscReal loc_periodic[2] = {PETSC_MIN_REAL, PETSC_MIN_REAL}, loc_periodic_global[2]; // Location of donor (0) and periodic (1) faces in periodic direction 1136d7d2d1d2SJames Wright 1137d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][0], &donor_is)); 1138d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][1], &periodic_is)); 1139d7d2d1d2SJames Wright if (donor_is) { 1140d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(donor_is, &num_donor)); 1141d7d2d1d2SJames Wright PetscCall(ISGetIndices(donor_is, &donor_faces)); 1142d7d2d1d2SJames Wright } 1143d7d2d1d2SJames Wright if (periodic_is) { 1144d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(periodic_is, &num_periodic)); 1145d7d2d1d2SJames Wright PetscCall(ISGetIndices(periodic_is, &periodic_faces)); 1146d7d2d1d2SJames Wright } 1147d7d2d1d2SJames Wright PetscCall(PetscCalloc2(num_donor * centroid_comps, &donor_centroids, num_periodic * centroid_comps, &periodic_centroids)); 1148d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_donor; f++) { 1149d7d2d1d2SJames Wright PetscInt face = donor_faces[f], num_coords; 1150d7d2d1d2SJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 1151d7d2d1d2SJames Wright num_coords = coords_size / dim; 1152d7d2d1d2SJames Wright for (PetscInt c = 0; c < num_coords; c++) { 1153d7d2d1d2SJames Wright PetscInt comp_index = 0; 1154d7d2d1d2SJames Wright loc_periodic[0] = PetscRealPart(coords[c * dim + d]); 1155d7d2d1d2SJames Wright for (PetscInt i = 0; i < dim; i++) { 1156d7d2d1d2SJames Wright if (i == d) continue; // Periodic direction not used for centroid calculation 1157d7d2d1d2SJames Wright donor_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords; 1158d7d2d1d2SJames Wright comp_index++; 1159d7d2d1d2SJames Wright } 1160d7d2d1d2SJames Wright } 1161d7d2d1d2SJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 1162d7d2d1d2SJames Wright } 1163d7d2d1d2SJames Wright 1164d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_periodic; f++) { 1165d7d2d1d2SJames Wright PetscInt face = periodic_faces[f], num_coords; 1166d7d2d1d2SJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 1167d7d2d1d2SJames Wright num_coords = coords_size / dim; 1168d7d2d1d2SJames Wright for (PetscInt c = 0; c < num_coords; c++) { 1169d7d2d1d2SJames Wright PetscInt comp_index = 0; 1170d7d2d1d2SJames Wright loc_periodic[1] = PetscRealPart(coords[c * dim + d]); 1171d7d2d1d2SJames Wright for (PetscInt i = 0; i < dim; i++) { 1172d7d2d1d2SJames Wright if (i == d) continue; // Periodic direction not used for centroid calculation 1173d7d2d1d2SJames Wright periodic_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords; 1174d7d2d1d2SJames Wright comp_index++; 1175d7d2d1d2SJames Wright } 1176d7d2d1d2SJames Wright } 1177d7d2d1d2SJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 1178d7d2d1d2SJames Wright } 1179d7d2d1d2SJames Wright PetscCallMPI(MPIU_Allreduce(loc_periodic, loc_periodic_global, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm))); 1180d7d2d1d2SJames Wright donor_to_periodic_distance = loc_periodic_global[1] - loc_periodic_global[0]; 1181d7d2d1d2SJames Wright 1182d7d2d1d2SJames Wright PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), ¢roidsf)); 1183d7d2d1d2SJames Wright PetscCall(PetscSFSetGraphFromCoordinates(centroidsf, num_donor, num_periodic, centroid_comps, 1e-10, donor_centroids, periodic_centroids)); 1184d7d2d1d2SJames Wright PetscCall(PetscSFViewFromOptions(centroidsf, NULL, "-dm_plex_box_label_centroid_sf_view")); 1185d7d2d1d2SJames Wright PetscCall(PetscFree2(donor_centroids, periodic_centroids)); 1186d7d2d1d2SJames Wright } 1187d7d2d1d2SJames Wright 1188d7d2d1d2SJames Wright { // Create Isoperiodic SF using centroidsSF 1189d7d2d1d2SJames Wright PetscInt pStart, pEnd; 1190d7d2d1d2SJames Wright PetscInt *leaf_faces; 1191d7d2d1d2SJames Wright const PetscSFNode *firemote; 1192d7d2d1d2SJames Wright PetscSFNode *isoperiodic_leaves; 1193d7d2d1d2SJames Wright 1194d7d2d1d2SJames Wright PetscCall(PetscMalloc1(num_periodic, &leaf_faces)); 1195d7d2d1d2SJames Wright PetscCall(PetscSFBcastBegin(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE)); 1196d7d2d1d2SJames Wright PetscCall(PetscSFBcastEnd(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE)); 1197d7d2d1d2SJames Wright 1198d7d2d1d2SJames Wright PetscCall(PetscMalloc1(num_periodic, &isoperiodic_leaves)); 1199d7d2d1d2SJames Wright PetscCall(PetscSFGetGraph(centroidsf, NULL, NULL, NULL, &firemote)); 1200d7d2d1d2SJames Wright for (PetscInt l = 0; l < num_periodic; ++l) { 1201d7d2d1d2SJames Wright isoperiodic_leaves[l].index = leaf_faces[l]; 1202d7d2d1d2SJames Wright isoperiodic_leaves[l].rank = firemote[l].rank; 1203d7d2d1d2SJames Wright } 1204d7d2d1d2SJames Wright 1205d7d2d1d2SJames Wright PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 1206d7d2d1d2SJames Wright PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &periodicsfs[periodic_sf_index])); 1207d7d2d1d2SJames Wright PetscCall(PetscSFSetGraph(periodicsfs[periodic_sf_index], pEnd - pStart, num_periodic, (PetscInt *)periodic_faces, PETSC_COPY_VALUES, isoperiodic_leaves, PETSC_OWN_POINTER)); 1208d7d2d1d2SJames Wright PetscCall(PetscSFViewFromOptions(periodicsfs[periodic_sf_index], NULL, "-dm_plex_box_label_periodic_sf_view")); 1209d7d2d1d2SJames Wright PetscCall(PetscFree(leaf_faces)); 1210d7d2d1d2SJames Wright } 1211d7d2d1d2SJames Wright 1212d7d2d1d2SJames Wright transform[periodic_sf_index][0][0] = 1; 1213d7d2d1d2SJames Wright transform[periodic_sf_index][1][1] = 1; 1214d7d2d1d2SJames Wright transform[periodic_sf_index][2][2] = 1; 1215d7d2d1d2SJames Wright transform[periodic_sf_index][3][3] = 1; 1216d7d2d1d2SJames Wright transform[periodic_sf_index][d][3] = donor_to_periodic_distance; 1217d7d2d1d2SJames Wright 1218d7d2d1d2SJames Wright periodic_sf_index++; 1219d7d2d1d2SJames Wright PetscCall(PetscSFDestroy(¢roidsf)); 1220d7d2d1d2SJames Wright if (donor_is) { 1221d7d2d1d2SJames Wright PetscCall(ISRestoreIndices(donor_is, &donor_faces)); 1222d7d2d1d2SJames Wright PetscCall(ISDestroy(&donor_is)); 1223d7d2d1d2SJames Wright } 1224d7d2d1d2SJames Wright if (periodic_is) { 1225d7d2d1d2SJames Wright PetscCall(ISRestoreIndices(periodic_is, &periodic_faces)); 1226d7d2d1d2SJames Wright PetscCall(ISDestroy(&periodic_is)); 1227d7d2d1d2SJames Wright } 1228d7d2d1d2SJames Wright PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][0])); 1229d7d2d1d2SJames Wright PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][1])); 1230d7d2d1d2SJames Wright } 1231d7d2d1d2SJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(dm, periodic_sf_index, periodicsfs)); 1232d7d2d1d2SJames Wright PetscCall(DMPlexSetIsoperiodicFaceTransform(dm, periodic_sf_index, (const PetscScalar *)transform)); 1233d7d2d1d2SJames Wright for (PetscInt p = 0; p < periodic_sf_index; p++) PetscCall(PetscSFDestroy(&periodicsfs[p])); 1234d7d2d1d2SJames Wright 1235d7d2d1d2SJames Wright { // Update coordinate DM with new Face Sets label 1236d7d2d1d2SJames Wright DM cdm; 1237d7d2d1d2SJames Wright DMLabel oldFaceSets, newFaceSets; 1238d7d2d1d2SJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 1239d7d2d1d2SJames Wright PetscCall(DMGetLabel(cdm, "Face Sets", &oldFaceSets)); 1240d7d2d1d2SJames Wright if (oldFaceSets) PetscCall(DMRemoveLabelBySelf(cdm, &oldFaceSets, PETSC_FALSE)); 1241d7d2d1d2SJames Wright PetscCall(DMLabelDuplicate(label, &newFaceSets)); 1242d7d2d1d2SJames Wright PetscCall(DMAddLabel(cdm, newFaceSets)); 1243d7d2d1d2SJames Wright PetscCall(DMLabelDestroy(&newFaceSets)); 1244d7d2d1d2SJames Wright } 12454054ae39SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 12464054ae39SJames Wright } 12474054ae39SJames Wright 1248d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 1249d71ae5a4SJacob Faibussowitsch { 12509318fe57SMatthew G. Knepley DM boundary, vol; 1251c22d3578SMatthew G. Knepley DMLabel bdlabel; 1252d6218766SMatthew G. Knepley 1253d6218766SMatthew G. Knepley PetscFunctionBegin; 12544f572ea9SToby Isaac PetscAssertPointer(dm, 1); 1255c22d3578SMatthew 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"); 12569566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary)); 12579566063dSJacob Faibussowitsch PetscCall(DMSetType(boundary, DMPLEX)); 12589566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 12599566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 1260c22d3578SMatthew G. Knepley PetscCall(DMGetLabel(vol, "marker", &bdlabel)); 1261c22d3578SMatthew G. Knepley if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel)); 12625de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol)); 126369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 12644054ae39SJames Wright if (interpolate) { 12654054ae39SJames Wright PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 1266d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, periodicity)); 12674054ae39SJames Wright } 12689566063dSJacob Faibussowitsch PetscCall(DMDestroy(&boundary)); 12693ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1270d6218766SMatthew G. Knepley } 1271d6218766SMatthew G. Knepley 1272d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 1273d71ae5a4SJacob Faibussowitsch { 1274ed0e4b50SMatthew G. Knepley DMLabel cutLabel = NULL; 1275f4eb4c5dSMatthew G. Knepley PetscInt markerTop = 1, faceMarkerTop = 1; 1276f4eb4c5dSMatthew G. Knepley PetscInt markerBottom = 1, faceMarkerBottom = 1; 1277f4eb4c5dSMatthew G. Knepley PetscInt markerFront = 1, faceMarkerFront = 1; 1278f4eb4c5dSMatthew G. Knepley PetscInt markerBack = 1, faceMarkerBack = 1; 1279f4eb4c5dSMatthew G. Knepley PetscInt markerRight = 1, faceMarkerRight = 1; 1280f4eb4c5dSMatthew G. Knepley PetscInt markerLeft = 1, faceMarkerLeft = 1; 12813dfda0b1SToby Isaac PetscInt dim; 1282d8211ee3SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 12833dfda0b1SToby Isaac PetscMPIInt rank; 12843dfda0b1SToby Isaac 12853dfda0b1SToby Isaac PetscFunctionBegin; 12869566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 12879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 12889566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 12899566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 12909566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 12919371c9d4SSatish 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) { 12929371c9d4SSatish Balay if (cutMarker) { 12939371c9d4SSatish Balay PetscCall(DMCreateLabel(dm, "periodic_cut")); 12949371c9d4SSatish Balay PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 12959371c9d4SSatish Balay } 1296d8211ee3SMatthew G. Knepley } 12973dfda0b1SToby Isaac switch (dim) { 12983dfda0b1SToby Isaac case 2: 1299f4eb4c5dSMatthew G. Knepley faceMarkerTop = 3; 1300f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1301f4eb4c5dSMatthew G. Knepley faceMarkerRight = 2; 1302f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 4; 13033dfda0b1SToby Isaac break; 13043dfda0b1SToby Isaac case 3: 1305f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1306f4eb4c5dSMatthew G. Knepley faceMarkerTop = 2; 1307f4eb4c5dSMatthew G. Knepley faceMarkerFront = 3; 1308f4eb4c5dSMatthew G. Knepley faceMarkerBack = 4; 1309f4eb4c5dSMatthew G. Knepley faceMarkerRight = 5; 1310f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 6; 13113dfda0b1SToby Isaac break; 1312d71ae5a4SJacob Faibussowitsch default: 1313d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 13143dfda0b1SToby Isaac } 13159566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 1316f4eb4c5dSMatthew G. Knepley if (markerSeparate) { 1317f4eb4c5dSMatthew G. Knepley markerBottom = faceMarkerBottom; 1318f4eb4c5dSMatthew G. Knepley markerTop = faceMarkerTop; 1319f4eb4c5dSMatthew G. Knepley markerFront = faceMarkerFront; 1320f4eb4c5dSMatthew G. Knepley markerBack = faceMarkerBack; 1321f4eb4c5dSMatthew G. Knepley markerRight = faceMarkerRight; 1322f4eb4c5dSMatthew G. Knepley markerLeft = faceMarkerLeft; 13233dfda0b1SToby Isaac } 13243dfda0b1SToby Isaac { 1325dd400576SPatrick Sanan const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 1326dd400576SPatrick Sanan const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 1327dd400576SPatrick Sanan const PetscInt numZEdges = rank == 0 ? edges[2] : 0; 1328dd400576SPatrick Sanan const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0; 1329dd400576SPatrick Sanan const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0; 1330dd400576SPatrick Sanan const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0; 13313dfda0b1SToby Isaac const PetscInt numCells = numXEdges * numYEdges * numZEdges; 13323dfda0b1SToby Isaac const PetscInt numXFaces = numYEdges * numZEdges; 13333dfda0b1SToby Isaac const PetscInt numYFaces = numXEdges * numZEdges; 13343dfda0b1SToby Isaac const PetscInt numZFaces = numXEdges * numYEdges; 13353dfda0b1SToby Isaac const PetscInt numTotXFaces = numXVertices * numXFaces; 13363dfda0b1SToby Isaac const PetscInt numTotYFaces = numYVertices * numYFaces; 13373dfda0b1SToby Isaac const PetscInt numTotZFaces = numZVertices * numZFaces; 13383dfda0b1SToby Isaac const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 13393dfda0b1SToby Isaac const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices; 13403dfda0b1SToby Isaac const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices; 13413dfda0b1SToby Isaac const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices; 13423dfda0b1SToby Isaac const PetscInt numVertices = numXVertices * numYVertices * numZVertices; 13433dfda0b1SToby Isaac const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 13443dfda0b1SToby Isaac const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 13453dfda0b1SToby Isaac const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 13463dfda0b1SToby Isaac const PetscInt firstYFace = firstXFace + numTotXFaces; 13473dfda0b1SToby Isaac const PetscInt firstZFace = firstYFace + numTotYFaces; 13483dfda0b1SToby Isaac const PetscInt firstXEdge = numCells + numFaces + numVertices; 13493dfda0b1SToby Isaac const PetscInt firstYEdge = firstXEdge + numTotXEdges; 13503dfda0b1SToby Isaac const PetscInt firstZEdge = firstYEdge + numTotYEdges; 13513dfda0b1SToby Isaac Vec coordinates; 13523dfda0b1SToby Isaac PetscSection coordSection; 13533dfda0b1SToby Isaac PetscScalar *coords; 13543dfda0b1SToby Isaac PetscInt coordSize; 13553dfda0b1SToby Isaac PetscInt v, vx, vy, vz; 13563dfda0b1SToby Isaac PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 13573dfda0b1SToby Isaac 13589566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices)); 135948a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 136048a46eb9SPierre Jolivet for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 136148a46eb9SPierre Jolivet for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 13629566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 13633dfda0b1SToby Isaac /* Build cells */ 13643dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 13653dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 13663dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 13673dfda0b1SToby Isaac PetscInt cell = (fz * numYEdges + fy) * numXEdges + fx; 13683dfda0b1SToby Isaac PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 13693dfda0b1SToby Isaac PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices); 13703dfda0b1SToby Isaac PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 13713dfda0b1SToby Isaac PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices); 13723dfda0b1SToby Isaac PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 13733dfda0b1SToby Isaac PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices); 13743dfda0b1SToby Isaac /* B, T, F, K, R, L */ 1375b5a892a1SMatthew G. Knepley PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */ 137642206facSLisandro Dalcin PetscInt cone[6]; 13773dfda0b1SToby Isaac 13783dfda0b1SToby Isaac /* no boundary twisting in 3D */ 13799371c9d4SSatish Balay cone[0] = faceB; 13809371c9d4SSatish Balay cone[1] = faceT; 13819371c9d4SSatish Balay cone[2] = faceF; 13829371c9d4SSatish Balay cone[3] = faceK; 13839371c9d4SSatish Balay cone[4] = faceR; 13849371c9d4SSatish Balay cone[5] = faceL; 13859566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, cell, cone)); 13869566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, cell, ornt)); 13879566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 13889566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 13899566063dSJacob Faibussowitsch if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 13903dfda0b1SToby Isaac } 13913dfda0b1SToby Isaac } 13923dfda0b1SToby Isaac } 13933dfda0b1SToby Isaac /* Build x faces */ 13943dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 13953dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 13963dfda0b1SToby Isaac for (fx = 0; fx < numXVertices; ++fx) { 13973dfda0b1SToby Isaac PetscInt face = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 13983dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 13993dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz; 14003dfda0b1SToby Isaac PetscInt edgeB = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 14013dfda0b1SToby Isaac PetscInt edgeT = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy; 1402b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 14033dfda0b1SToby Isaac PetscInt cone[4]; 14043dfda0b1SToby Isaac 14053dfda0b1SToby Isaac if (dim == 3) { 14063dfda0b1SToby Isaac /* markers */ 14073dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 14083dfda0b1SToby Isaac if (fx == numXVertices - 1) { 14099566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 14109566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerRight)); 14119371c9d4SSatish Balay } else if (fx == 0) { 14129566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 14139566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft)); 14143dfda0b1SToby Isaac } 14153dfda0b1SToby Isaac } 14163dfda0b1SToby Isaac } 14179371c9d4SSatish Balay cone[0] = edgeB; 14189371c9d4SSatish Balay cone[1] = edgeR; 14199371c9d4SSatish Balay cone[2] = edgeT; 14209371c9d4SSatish Balay cone[3] = edgeL; 14219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 14229566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 14233dfda0b1SToby Isaac } 14243dfda0b1SToby Isaac } 14253dfda0b1SToby Isaac } 14263dfda0b1SToby Isaac /* Build y faces */ 14273dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 142842206facSLisandro Dalcin for (fx = 0; fx < numXEdges; ++fx) { 14293dfda0b1SToby Isaac for (fy = 0; fy < numYVertices; ++fy) { 14303dfda0b1SToby Isaac PetscInt face = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 14313dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 14323dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz; 14333dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 14343dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx; 1435b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 14363dfda0b1SToby Isaac PetscInt cone[4]; 14373dfda0b1SToby Isaac 14383dfda0b1SToby Isaac if (dim == 3) { 14393dfda0b1SToby Isaac /* markers */ 14403dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 14413dfda0b1SToby Isaac if (fy == numYVertices - 1) { 14429566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 14439566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBack)); 14449371c9d4SSatish Balay } else if (fy == 0) { 14459566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 14469566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerFront)); 14473dfda0b1SToby Isaac } 14483dfda0b1SToby Isaac } 14493dfda0b1SToby Isaac } 14509371c9d4SSatish Balay cone[0] = edgeB; 14519371c9d4SSatish Balay cone[1] = edgeR; 14529371c9d4SSatish Balay cone[2] = edgeT; 14539371c9d4SSatish Balay cone[3] = edgeL; 14549566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 14559566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 14563dfda0b1SToby Isaac } 14573dfda0b1SToby Isaac } 14583dfda0b1SToby Isaac } 14593dfda0b1SToby Isaac /* Build z faces */ 14603dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 14613dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 14623dfda0b1SToby Isaac for (fz = 0; fz < numZVertices; fz++) { 14633dfda0b1SToby Isaac PetscInt face = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 14643dfda0b1SToby Isaac PetscInt edgeL = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 14653dfda0b1SToby Isaac PetscInt edgeR = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy; 14663dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 14673dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx; 1468b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 14693dfda0b1SToby Isaac PetscInt cone[4]; 14703dfda0b1SToby Isaac 14713dfda0b1SToby Isaac if (dim == 2) { 14729371c9d4SSatish Balay if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) { 14739371c9d4SSatish Balay edgeR += numYEdges - 1 - 2 * fy; 14749371c9d4SSatish Balay ornt[1] = -1; 14759371c9d4SSatish Balay } 14769371c9d4SSatish Balay if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) { 14779371c9d4SSatish Balay edgeT += numXEdges - 1 - 2 * fx; 14789371c9d4SSatish Balay ornt[2] = 0; 14799371c9d4SSatish Balay } 14809566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 14819566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 1482d1c88043SMatthew G. Knepley } else { 14833dfda0b1SToby Isaac /* markers */ 14843dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 14853dfda0b1SToby Isaac if (fz == numZVertices - 1) { 14869566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 14879566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerTop)); 14889371c9d4SSatish Balay } else if (fz == 0) { 14899566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 14909566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom)); 14913dfda0b1SToby Isaac } 14923dfda0b1SToby Isaac } 14933dfda0b1SToby Isaac } 14949371c9d4SSatish Balay cone[0] = edgeB; 14959371c9d4SSatish Balay cone[1] = edgeR; 14969371c9d4SSatish Balay cone[2] = edgeT; 14979371c9d4SSatish Balay cone[3] = edgeL; 14989566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 14999566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 15003dfda0b1SToby Isaac } 15013dfda0b1SToby Isaac } 15023dfda0b1SToby Isaac } 15033dfda0b1SToby Isaac /* Build Z edges*/ 15043dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 15053dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 15063dfda0b1SToby Isaac for (ez = 0; ez < numZEdges; ez++) { 15073dfda0b1SToby Isaac const PetscInt edge = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez; 15083dfda0b1SToby Isaac const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx; 15093dfda0b1SToby Isaac const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx; 15103dfda0b1SToby Isaac PetscInt cone[2]; 15113dfda0b1SToby Isaac 15129371c9d4SSatish Balay cone[0] = vertexB; 15139371c9d4SSatish Balay cone[1] = vertexT; 1514c2df9bbfSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, edge, cone)); 15153dfda0b1SToby Isaac if (dim == 3) { 15163dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 15173dfda0b1SToby Isaac if (vx == numXVertices - 1) { 15189566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1519c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1520c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1521c2df9bbfSMatthew G. Knepley } else if (vx == 0) { 15229566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1523c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1524c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 15253dfda0b1SToby Isaac } 15263dfda0b1SToby Isaac } 15273dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 15283dfda0b1SToby Isaac if (vy == numYVertices - 1) { 15299566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1530c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1531c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1532c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 15339566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1534c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1535c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 15363dfda0b1SToby Isaac } 15373dfda0b1SToby Isaac } 15383dfda0b1SToby Isaac } 15393dfda0b1SToby Isaac } 15403dfda0b1SToby Isaac } 15413dfda0b1SToby Isaac } 15423dfda0b1SToby Isaac /* Build Y edges*/ 15433dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 15443dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 15453dfda0b1SToby Isaac for (ey = 0; ey < numYEdges; ey++) { 15463dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx; 15473dfda0b1SToby Isaac const PetscInt edge = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey; 15483dfda0b1SToby Isaac const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx; 15493dfda0b1SToby Isaac const PetscInt vertexK = firstVertex + nextv; 15503dfda0b1SToby Isaac PetscInt cone[2]; 15513dfda0b1SToby Isaac 15529371c9d4SSatish Balay cone[0] = vertexF; 15539371c9d4SSatish Balay cone[1] = vertexK; 15549566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 15553dfda0b1SToby Isaac if (dim == 2) { 15563dfda0b1SToby Isaac if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 15573dfda0b1SToby Isaac if (vx == numXVertices - 1) { 15589566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 15599566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 15609566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1561c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1562d8211ee3SMatthew G. Knepley } else if (vx == 0) { 15639566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 15649566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 15659566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1566c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 15673dfda0b1SToby Isaac } 1568d8211ee3SMatthew G. Knepley } else { 15694c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 15709566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 15719566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1572c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 15733dfda0b1SToby Isaac } 1574d8211ee3SMatthew G. Knepley } 1575d8211ee3SMatthew G. Knepley } else { 15763dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 15773dfda0b1SToby Isaac if (vx == numXVertices - 1) { 15789566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1579c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1580c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1581d8211ee3SMatthew G. Knepley } else if (vx == 0) { 15829566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1583c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1584c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 15853dfda0b1SToby Isaac } 15863dfda0b1SToby Isaac } 15873dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 15883dfda0b1SToby Isaac if (vz == numZVertices - 1) { 15899566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1590c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1591c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1592d8211ee3SMatthew G. Knepley } else if (vz == 0) { 15939566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1594c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1595c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 15963dfda0b1SToby Isaac } 15973dfda0b1SToby Isaac } 15983dfda0b1SToby Isaac } 15993dfda0b1SToby Isaac } 16003dfda0b1SToby Isaac } 16013dfda0b1SToby Isaac } 16023dfda0b1SToby Isaac /* Build X edges*/ 16033dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 16043dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 16053dfda0b1SToby Isaac for (ex = 0; ex < numXEdges; ex++) { 16063dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices; 16073dfda0b1SToby Isaac const PetscInt edge = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex; 16083dfda0b1SToby Isaac const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex; 16093dfda0b1SToby Isaac const PetscInt vertexR = firstVertex + nextv; 16103dfda0b1SToby Isaac PetscInt cone[2]; 16113dfda0b1SToby Isaac 16129371c9d4SSatish Balay cone[0] = vertexL; 16139371c9d4SSatish Balay cone[1] = vertexR; 16149566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 16153dfda0b1SToby Isaac if (dim == 2) { 16163dfda0b1SToby Isaac if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 16173dfda0b1SToby Isaac if (vy == numYVertices - 1) { 16189566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 16199566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 16209566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1621c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1622d8211ee3SMatthew G. Knepley } else if (vy == 0) { 16239566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 16249566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 16259566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1626c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 16273dfda0b1SToby Isaac } 1628d8211ee3SMatthew G. Knepley } else { 16294c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 16309566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 16319566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1632c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 16333dfda0b1SToby Isaac } 1634d8211ee3SMatthew G. Knepley } 1635d8211ee3SMatthew G. Knepley } else { 16363dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 16373dfda0b1SToby Isaac if (vy == numYVertices - 1) { 16389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1639c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1640c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1641c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 16429566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1643c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1644c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 16453dfda0b1SToby Isaac } 16463dfda0b1SToby Isaac } 16473dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 16483dfda0b1SToby Isaac if (vz == numZVertices - 1) { 16499566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1650c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1651c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1652c2df9bbfSMatthew G. Knepley } else if (vz == 0) { 16539566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1654c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1655c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 16563dfda0b1SToby Isaac } 16573dfda0b1SToby Isaac } 16583dfda0b1SToby Isaac } 16593dfda0b1SToby Isaac } 16603dfda0b1SToby Isaac } 16613dfda0b1SToby Isaac } 16629566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 16639566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 16643dfda0b1SToby Isaac /* Build coordinates */ 16659566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 16669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 16679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 16689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 16693dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex + numVertices; ++v) { 16709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 16719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 16723dfda0b1SToby Isaac } 16739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 16749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 16759566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 16769566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 16779566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 16789566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 16799566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 16809566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 16813dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; ++vz) { 16823dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; ++vy) { 16833dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; ++vx) { 16843dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 16853dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1686ad540459SPierre Jolivet if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz; 16873dfda0b1SToby Isaac } 16883dfda0b1SToby Isaac } 16893dfda0b1SToby Isaac } 16909566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 16919566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 16929566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 16933dfda0b1SToby Isaac } 16943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 16953dfda0b1SToby Isaac } 16963dfda0b1SToby Isaac 1697d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1698d71ae5a4SJacob Faibussowitsch { 16999318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 17009318fe57SMatthew G. Knepley PetscInt fac[3] = {0, 0, 0}, d; 1701552f7358SJed Brown 1702552f7358SJed Brown PetscFunctionBegin; 17034f572ea9SToby Isaac PetscAssertPointer(dm, 1); 17049318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 17059566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 17069371c9d4SSatish Balay for (d = 0; d < dim; ++d) { 17079371c9d4SSatish Balay fac[d] = faces[d]; 17089371c9d4SSatish Balay bdt[d] = periodicity[d]; 17099371c9d4SSatish Balay } 17109566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2])); 17119371c9d4SSatish 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))) { 17126858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 17136858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1714552f7358SJed Brown 17159318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 17166858538eSMatthew G. Knepley if (periodicity[d] != DM_BOUNDARY_NONE) { 17179318fe57SMatthew G. Knepley L[d] = upper[d] - lower[d]; 17189318fe57SMatthew G. Knepley maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d])); 1719768d5fceSMatthew G. Knepley } 17206858538eSMatthew G. Knepley } 17214fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1722768d5fceSMatthew G. Knepley } 17239566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 17243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 17259318fe57SMatthew G. Knepley } 17269318fe57SMatthew G. Knepley 17275dca41c3SJed 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) 1728d71ae5a4SJacob Faibussowitsch { 17299318fe57SMatthew G. Knepley PetscFunctionBegin; 173046139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 17315dca41c3SJed Brown if (shape == DM_SHAPE_ZBOX) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 17326725e60dSJed Brown else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 17339566063dSJacob Faibussowitsch else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 17349566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity)); 17359318fe57SMatthew G. Knepley if (!interpolate && dim > 1 && !simplex) { 1736768d5fceSMatthew G. Knepley DM udm; 1737768d5fceSMatthew G. Knepley 17389566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 17399566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, udm)); 174069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 1741768d5fceSMatthew G. Knepley } 174246139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 17433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1744c8c68bd8SToby Isaac } 1745c8c68bd8SToby Isaac 17465d83a8b1SBarry Smith /*@ 1747768d5fceSMatthew G. Knepley DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 1748768d5fceSMatthew G. Knepley 1749d083f849SBarry Smith Collective 1750768d5fceSMatthew G. Knepley 1751768d5fceSMatthew G. Knepley Input Parameters: 1752a1cb98faSBarry Smith + comm - The communicator for the `DM` object 1753768d5fceSMatthew G. Knepley . dim - The spatial dimension 1754a1cb98faSBarry Smith . simplex - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells 175520f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 175620f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 175720f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 175820f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 175942108689Sksagiyam . interpolate - Flag to create intermediate mesh pieces (edges, faces) 176042108689Sksagiyam . localizationHeight - Flag to localize edges and faces in addition to cells; only significant for periodic meshes 176142108689Sksagiyam - sparseLocalize - Flag to localize coordinates only for cells near the periodic boundary; only significant for periodic meshes 1762768d5fceSMatthew G. Knepley 1763768d5fceSMatthew G. Knepley Output Parameter: 1764a1cb98faSBarry Smith . dm - The `DM` object 1765768d5fceSMatthew G. Knepley 1766768d5fceSMatthew G. Knepley Level: beginner 1767768d5fceSMatthew G. Knepley 1768a1cb98faSBarry Smith Note: 1769a1cb98faSBarry Smith To customize this mesh using options, use 1770a1cb98faSBarry Smith .vb 1771a1cb98faSBarry Smith DMCreate(comm, &dm); 1772a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 1773a1cb98faSBarry Smith DMSetFromOptions(dm); 1774a1cb98faSBarry Smith .ve 1775a1cb98faSBarry Smith and use the options in `DMSetFromOptions()`. 1776a1cb98faSBarry Smith 1777a4e35b19SJacob Faibussowitsch Here is the numbering returned for 2 faces in each direction for tensor cells\: 1778a1cb98faSBarry Smith .vb 1779a1cb98faSBarry Smith 10---17---11---18----12 1780a1cb98faSBarry Smith | | | 1781a1cb98faSBarry Smith | | | 1782a1cb98faSBarry Smith 20 2 22 3 24 1783a1cb98faSBarry Smith | | | 1784a1cb98faSBarry Smith | | | 1785a1cb98faSBarry Smith 7---15----8---16----9 1786a1cb98faSBarry Smith | | | 1787a1cb98faSBarry Smith | | | 1788a1cb98faSBarry Smith 19 0 21 1 23 1789a1cb98faSBarry Smith | | | 1790a1cb98faSBarry Smith | | | 1791a1cb98faSBarry Smith 4---13----5---14----6 1792a1cb98faSBarry Smith .ve 1793a1cb98faSBarry Smith and for simplicial cells 1794a1cb98faSBarry Smith .vb 1795a1cb98faSBarry Smith 14----8---15----9----16 1796a1cb98faSBarry Smith |\ 5 |\ 7 | 1797a1cb98faSBarry Smith | \ | \ | 1798a1cb98faSBarry Smith 13 2 14 3 15 1799a1cb98faSBarry Smith | 4 \ | 6 \ | 1800a1cb98faSBarry Smith | \ | \ | 1801a1cb98faSBarry Smith 11----6---12----7----13 1802a1cb98faSBarry Smith |\ |\ | 1803a1cb98faSBarry Smith | \ 1 | \ 3 | 1804a1cb98faSBarry Smith 10 0 11 1 12 1805a1cb98faSBarry Smith | 0 \ | 2 \ | 1806a1cb98faSBarry Smith | \ | \ | 1807a1cb98faSBarry Smith 8----4----9----5----10 1808a1cb98faSBarry Smith .ve 1809a1cb98faSBarry Smith 18101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 1811768d5fceSMatthew G. Knepley @*/ 181242108689Sksagiyam 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) 1813d71ae5a4SJacob Faibussowitsch { 18149318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 1815fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 1816fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 1817fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 1818552f7358SJed Brown 1819768d5fceSMatthew G. Knepley PetscFunctionBegin; 18209566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 18219566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 18225dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(*dm, DM_SHAPE_BOX, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 182342108689Sksagiyam if (periodicity) { 182442108689Sksagiyam DM cdm; 182542108689Sksagiyam 182642108689Sksagiyam PetscCall(DMGetCoordinateDM(*dm, &cdm)); 182742108689Sksagiyam PetscCall(DMPlexSetMaxProjectionHeight(cdm, localizationHeight)); 182842108689Sksagiyam PetscCall(DMSetSparseLocalize(*dm, sparseLocalize)); 182942108689Sksagiyam PetscCall(DMLocalizeCoordinates(*dm)); 183042108689Sksagiyam } 18313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 18329318fe57SMatthew G. Knepley } 1833fdbf62faSLisandro Dalcin 1834d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1835d71ae5a4SJacob Faibussowitsch { 18369318fe57SMatthew G. Knepley DM bdm, vol; 18379318fe57SMatthew G. Knepley PetscInt i; 18389318fe57SMatthew G. Knepley 18399318fe57SMatthew G. Knepley PetscFunctionBegin; 18401fcf445aSMatthew G. Knepley // TODO Now we can support periodicity 184108401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 18429566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 18439566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 18449566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 184546139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, bdm, 0, 0, 0)); 18469566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 18471fcf445aSMatthew G. Knepley PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, NULL, NULL, &vol)); 184846139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, bdm, 0, 0, 0)); 18499566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 185069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 18519318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 18529318fe57SMatthew G. Knepley Vec v; 18539318fe57SMatthew G. Knepley PetscScalar *x; 18549318fe57SMatthew G. Knepley PetscInt cDim, n; 18559318fe57SMatthew G. Knepley 18569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 18579566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 18589566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 18599566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 18609318fe57SMatthew G. Knepley x += cDim; 18619318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 18629566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 18639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 18649318fe57SMatthew G. Knepley } 18653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1866552f7358SJed Brown } 1867552f7358SJed Brown 186800dabe28SStefano Zampini /*@ 186939f4f5dbSPierre Jolivet DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tessellating the (x,y) plane and extruding in the third direction using wedge cells. 187000dabe28SStefano Zampini 1871d083f849SBarry Smith Collective 187200dabe28SStefano Zampini 187300dabe28SStefano Zampini Input Parameters: 1874a1cb98faSBarry Smith + comm - The communicator for the `DM` object 187520f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1, 1, 1) 187620f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 187720f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 187820f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 1879a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 188000dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 188100dabe28SStefano Zampini 188200dabe28SStefano Zampini Output Parameter: 1883a1cb98faSBarry Smith . dm - The `DM` object 188400dabe28SStefano Zampini 188500dabe28SStefano Zampini Level: beginner 188600dabe28SStefano Zampini 18871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 188800dabe28SStefano Zampini @*/ 1889d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 1890d71ae5a4SJacob Faibussowitsch { 18919318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 189200dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 189300dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 189400dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 189500dabe28SStefano Zampini 189600dabe28SStefano Zampini PetscFunctionBegin; 18979566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 18989566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 18999566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 1900d410b0cfSMatthew G. Knepley if (!interpolate) { 1901d410b0cfSMatthew G. Knepley DM udm; 190200dabe28SStefano Zampini 19039566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 190469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 190500dabe28SStefano Zampini } 19067ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 19073ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 190800dabe28SStefano Zampini } 190900dabe28SStefano Zampini 1910cfb853baSMatthew G. Knepley /* 1911cfb853baSMatthew 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. 1912cfb853baSMatthew G. Knepley 1913cfb853baSMatthew G. Knepley Input Parameters: 1914cfb853baSMatthew G. Knepley + len - The length of the tuple 1915cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max) 1916cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition 1917cfb853baSMatthew G. Knepley 1918cfb853baSMatthew G. Knepley Output Parameter: 191920f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max` 1920cfb853baSMatthew G. Knepley 1921cfb853baSMatthew G. Knepley Level: developer 1922cfb853baSMatthew G. Knepley 192320f4b53cSBarry Smith Note: 192420f4b53cSBarry Smith Ordering is lexicographic with lowest index as least significant in ordering. 192520f4b53cSBarry 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}. 192620f4b53cSBarry Smith 1927cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal() 1928cfb853baSMatthew G. Knepley */ 1929cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[]) 1930cfb853baSMatthew G. Knepley { 1931cfb853baSMatthew G. Knepley PetscInt i; 1932cfb853baSMatthew G. Knepley 1933cfb853baSMatthew G. Knepley PetscFunctionBegin; 1934cfb853baSMatthew G. Knepley for (i = 0; i < len; ++i) { 1935cfb853baSMatthew G. Knepley if (tup[i] < max[i] - 1) { 1936cfb853baSMatthew G. Knepley break; 1937cfb853baSMatthew G. Knepley } else { 1938cfb853baSMatthew G. Knepley tup[i] = 0; 1939cfb853baSMatthew G. Knepley } 1940cfb853baSMatthew G. Knepley } 1941cfb853baSMatthew G. Knepley if (i == len) tup[i - 1] = max[i - 1]; 1942cfb853baSMatthew G. Knepley else ++tup[i]; 19433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1944cfb853baSMatthew G. Knepley } 1945cfb853baSMatthew G. Knepley 1946cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[]) 1947cfb853baSMatthew G. Knepley { 19488d2ec52aSSatish Balay PetscInt idx = tup[len - 1]; 1949cfb853baSMatthew G. Knepley 19508d2ec52aSSatish Balay for (PetscInt i = len - 2; i >= 0; --i) { 1951cfb853baSMatthew G. Knepley idx *= max[i]; 1952cfb853baSMatthew G. Knepley idx += tup[i]; 1953cfb853baSMatthew G. Knepley } 1954cfb853baSMatthew G. Knepley return idx; 1955cfb853baSMatthew G. Knepley } 1956cfb853baSMatthew G. Knepley 19578d2ec52aSSatish Balay static void IndexToTuple_Private(PetscInt len, const PetscInt max[], PetscInt idx, PetscInt tup[]) 1958cfb853baSMatthew G. Knepley { 19598d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 19608d2ec52aSSatish Balay tup[i] = idx % max[i]; 19618d2ec52aSSatish Balay idx = (idx - tup[i]) / max[i]; 19628d2ec52aSSatish Balay } 19638d2ec52aSSatish Balay } 19648d2ec52aSSatish Balay 19658d2ec52aSSatish Balay static void TupleToRanks_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt tup[], PetscInt ranks[]) 19668d2ec52aSSatish Balay { 19678d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 19688d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 19698d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 19708d2ec52aSSatish Balay const PetscInt idx = (tup[i] < 0 ? max[i] + tup[i] : tup[i]) % max[i]; 19718d2ec52aSSatish Balay 19728d2ec52aSSatish Balay if (idx < rem * (div + 1)) ranks[i] = idx / (div + 1); 19738d2ec52aSSatish Balay else ranks[i] = rem + (idx - rem * (div + 1)) / div; 19748d2ec52aSSatish Balay } 19758d2ec52aSSatish Balay } 19768d2ec52aSSatish Balay 19778d2ec52aSSatish Balay static void RanksToSizes_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt ranks[], PetscInt sizes[]) 19788d2ec52aSSatish Balay { 19798d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 19808d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 19818d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 19828d2ec52aSSatish Balay 19838d2ec52aSSatish Balay sizes[i] = ranks[i] < rem ? div + 1 : div; 19848d2ec52aSSatish Balay } 19858d2ec52aSSatish Balay } 19868d2ec52aSSatish Balay 19878d2ec52aSSatish Balay /* 19888d2ec52aSSatish 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. 19898d2ec52aSSatish Balay 19908d2ec52aSSatish 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. 19918d2ec52aSSatish Balay 19928d2ec52aSSatish 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. 1993dfe9cfe5SMatthew Knepley 1994dfe9cfe5SMatthew Knepley Parallel Layout: 1995dfe9cfe5SMatthew Knepley 1996dfe9cfe5SMatthew 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. 19978d2ec52aSSatish Balay */ 19988d2ec52aSSatish Balay static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], PetscInt overlap, const DMBoundaryType bd[]) 19998d2ec52aSSatish Balay { 20008d2ec52aSSatish Balay const PetscInt debug = ((DM_Plex *)dm->data)->printAdj; 20018d2ec52aSSatish Balay PetscSF sf; 2002cfb853baSMatthew G. Knepley Vec coordinates; 2003cfb853baSMatthew G. Knepley PetscSection coordSection; 2004cfb853baSMatthew G. Knepley DMLabel cutLabel = NULL; 2005cfb853baSMatthew G. Knepley PetscBool cutMarker = PETSC_FALSE; 2006cfb853baSMatthew G. Knepley PetscBool periodic = PETSC_FALSE; 20078d2ec52aSSatish Balay PetscInt numCells = 1; 20088d2ec52aSSatish Balay PetscInt numVertices = 1; 20098d2ec52aSSatish Balay PetscSFNode *remotes; 2010cfb853baSMatthew G. Knepley PetscScalar *coords; 20118d2ec52aSSatish Balay PetscInt *procs; // The number of processes along each dimension 20128d2ec52aSSatish Balay PetscInt *lrank; // Rank in each dimension, lrank[d] \in [0, procs[d]) 20138d2ec52aSSatish Balay PetscInt *ledges; // The number of edges along each dimension for this process 20148d2ec52aSSatish Balay PetscInt *vstart; // The first vertex along each dimension on this processes 20158d2ec52aSSatish Balay PetscInt *vertices; // The number of vertices along each dimension on this process 20168d2ec52aSSatish Balay PetscInt *rvert; // The global (not local) vertex number along each dimension 20178d2ec52aSSatish Balay PetscInt *rrank; // The rank along each dimension for the process owning rvert[] 20188d2ec52aSSatish Balay PetscInt *rvertices; // The number of vertices along each dimension for the process rrank[] 20198d2ec52aSSatish Balay PetscInt *vert, *vtmp, *supp, cone[2], *leaves; 20208d2ec52aSSatish Balay PetscInt cell = 0, coordSize, Nl = 0, Nl2 = 0; 20218d2ec52aSSatish Balay PetscMPIInt rank, size; 20228d2ec52aSSatish Balay MPI_Comm comm; 2023cfb853baSMatthew G. Knepley 2024cfb853baSMatthew G. Knepley PetscFunctionBegin; 20258d2ec52aSSatish Balay PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 20268d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_rank(comm, &rank)); 20278d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_size(comm, &size)); 2028cfb853baSMatthew G. Knepley PetscCall(DMSetDimension(dm, dim)); 20298d2ec52aSSatish Balay PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 20308d2ec52aSSatish Balay PetscCall(PetscCalloc4(dim, &procs, dim, &lrank, dim, &rrank, 2 * dim, &supp)); 20318d2ec52aSSatish Balay PetscCall(PetscCalloc7(dim, &ledges, dim, &vertices, dim, &rvertices, dim, &vert, dim, &rvert, dim, &vstart, dim, &vtmp)); 2032cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 2033cfb853baSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 20348d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE; 2035cfb853baSMatthew G. Knepley if (periodic && cutMarker) { 2036cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "periodic_cut")); 2037cfb853baSMatthew G. Knepley PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 2038cfb853baSMatthew G. Knepley } 20398d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, comm, PETSC_ERR_SUP, "Hypercubic mesh must be periodic now"); 20408d2ec52aSSatish Balay overlap = overlap == PETSC_DETERMINE ? 1 : overlap; 20418d2ec52aSSatish Balay PetscCheck(overlap >= 1, comm, PETSC_ERR_SUP, "Overlap %" PetscInt_FMT " must be greater than 0", overlap); 20428d2ec52aSSatish Balay if (size > 1) { 20438d2ec52aSSatish Balay PetscInt Npr = 1; 20448d2ec52aSSatish Balay 20458d2ec52aSSatish Balay // Make process grid 20468d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "Process grid:")); 20478d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 20488d2ec52aSSatish Balay procs[d] = PetscRintReal(PetscPowReal(size, 1. / dim)); 20498d2ec52aSSatish Balay Npr *= procs[d]; 20508d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, " %" PetscInt_FMT, procs[d])); 20518d2ec52aSSatish Balay } 20528d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "\n")); 20538d2ec52aSSatish Balay PetscCheck(Npr == size, comm, PETSC_ERR_PLIB, "Process grid size %" PetscInt_FMT " != %d comm size", Npr, size); 20548d2ec52aSSatish Balay IndexToTuple_Private(dim, procs, rank, lrank); 20558d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 20568d2ec52aSSatish Balay ledges[d] = edges[d] / procs[d] + (edges[d] % procs[d] > lrank[d] ? 1 : 0); 20578d2ec52aSSatish Balay vstart[d] = 0; 20588d2ec52aSSatish Balay for (PetscInt r = 0; r < lrank[d]; ++r) vstart[d] += edges[d] / procs[d] + (edges[d] % procs[d] > r ? 1 : 0); 20598d2ec52aSSatish Balay vstart[d] -= overlap; // For halo 20608d2ec52aSSatish Balay } 20618d2ec52aSSatish Balay } else { 20628d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 20638d2ec52aSSatish Balay procs[d] = 1; 20648d2ec52aSSatish Balay ledges[d] = edges[d]; 20658d2ec52aSSatish Balay } 20668d2ec52aSSatish Balay } 20678d2ec52aSSatish Balay // Calculate local patch size 20688d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 20698d2ec52aSSatish Balay vertices[d] = ledges[d] + (procs[d] > 1 ? 2 * overlap : 0); 2070cfb853baSMatthew G. Knepley numVertices *= vertices[d]; 2071cfb853baSMatthew G. Knepley } 2072cfb853baSMatthew G. Knepley numCells = numVertices * dim; 2073cfb853baSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 20748d2ec52aSSatish Balay for (PetscInt c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2)); 20758d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim)); 2076cfb853baSMatthew G. Knepley PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */ 2077cfb853baSMatthew G. Knepley /* Build cell cones and vertex supports */ 2078cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "celltype")); 20798d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Topology for rank %d:\n", rank)); 2080cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2081cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells; 2082cfb853baSMatthew G. Knepley PetscInt s = 0; 20838d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2084cfb853baSMatthew G. Knepley 20858d2ec52aSSatish Balay if (debug) { 20868d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 20878d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d])); 20888d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 20898d2ec52aSSatish Balay } 2090cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT)); 20918d2ec52aSSatish Balay // Define edge cones 20928d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 20938d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2094cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + 1) % vertices[d]; 2095cfb853baSMatthew G. Knepley cone[0] = vertex; 2096cfb853baSMatthew G. Knepley cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells; 20978d2ec52aSSatish Balay if (debug) { 20988d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ":", cone[1])); 20998d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vtmp[e])); 21008d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 21018d2ec52aSSatish Balay } 2102cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, cell, cone)); 2103cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT)); 21048d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1])); 2105cfb853baSMatthew G. Knepley ++cell; 21068d2ec52aSSatish Balay // Shared vertices are any in the first or last overlap layers 21078d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 2108cfb853baSMatthew G. Knepley } 21098d2ec52aSSatish Balay if (size > 1 && leaf) ++Nl; 21108d2ec52aSSatish Balay // Define vertex supports 21118d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 21128d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2113cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + vertices[d] - 1) % vertices[d]; 2114cfb853baSMatthew G. Knepley supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d; 2115cfb853baSMatthew G. Knepley supp[s++] = (vertex - numCells) * dim + d; 2116cfb853baSMatthew G. Knepley PetscCall(DMPlexSetSupport(dm, vertex, supp)); 2117cfb853baSMatthew G. Knepley } 2118cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2119cfb853baSMatthew G. Knepley } 21208d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2121cfb853baSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 21228d2ec52aSSatish Balay // Allocate for SF 21238d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &leaves)); 21248d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &remotes)); 21258d2ec52aSSatish Balay // Build coordinates 2126cfb853baSMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 2127cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(coordSection, 1)); 2128cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 2129cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 21308d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) { 2131cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetDof(coordSection, v, dim)); 2132cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 2133cfb853baSMatthew G. Knepley } 2134cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetUp(coordSection)); 2135cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 21368d2ec52aSSatish Balay PetscCall(VecCreate(comm, &coordinates)); 2137cfb853baSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 2138cfb853baSMatthew G. Knepley PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 2139cfb853baSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinates, dim)); 2140cfb853baSMatthew G. Knepley PetscCall(VecSetType(coordinates, VECSTANDARD)); 2141cfb853baSMatthew G. Knepley PetscCall(VecGetArray(coordinates, &coords)); 21428d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Geometry for rank %d:\n", rank)); 21438d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) vert[d] = 0; 2144cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2145cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert); 21468d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2147cfb853baSMatthew G. Knepley 21488d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 21498d2ec52aSSatish Balay coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / edges[d]) * (vert[d] + vstart[d]); 21508d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 21518d2ec52aSSatish Balay } 21528d2ec52aSSatish Balay if (size > 1 && leaf) { 21538d2ec52aSSatish Balay PetscInt rnumCells = 1; 21548d2ec52aSSatish Balay 21558d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) rvert[d] = vert[d] + vstart[d]; 21568d2ec52aSSatish Balay TupleToRanks_Private(dim, edges, procs, rvert, rrank); 21578d2ec52aSSatish Balay leaves[Nl2] = vertex + numCells; 21588d2ec52aSSatish Balay remotes[Nl2].rank = TupleToIndex_Private(dim, procs, rrank); 21598d2ec52aSSatish Balay RanksToSizes_Private(dim, edges, procs, rrank, rvertices); 21608d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 21618d2ec52aSSatish Balay rvertices[d] += 2 * overlap; // Add halo 21628d2ec52aSSatish Balay rnumCells *= rvertices[d]; 21638d2ec52aSSatish Balay } 21648d2ec52aSSatish Balay rnumCells *= dim; 21658d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 21668d2ec52aSSatish Balay const PetscInt diff = rrank[d] - lrank[d]; 21678d2ec52aSSatish Balay 21688d2ec52aSSatish Balay if (!diff) rvert[d] = vert[d]; // Vertex is local 21698d2ec52aSSatish Balay else if (rvert[d] < 0) rvert[d] = rvertices[d] - 1 + rvert[d]; // Wrap around at the bottom 21708d2ec52aSSatish Balay else if (rvert[d] >= edges[d]) rvert[d] = rvert[d] - edges[d] + 1; // Wrap around at the top 21718d2ec52aSSatish Balay else if (diff == -1) rvert[d] = rvertices[d] - 1 + (vert[d] - overlap); 21728d2ec52aSSatish Balay else if (diff == 1) rvert[d] = (vertices[d] - vert[d] - 1) + overlap; 21738d2ec52aSSatish Balay else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Process distance %" PetscInt_FMT " in direction %" PetscInt_FMT " should not be possible", diff, d); 21748d2ec52aSSatish Balay } 21758d2ec52aSSatish Balay remotes[Nl2].index = TupleToIndex_Private(dim, rvertices, rvert) + rnumCells; 21768d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Shared Vertex %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", leaves[Nl2], remotes[Nl2].rank, remotes[Nl2].index)); 21778d2ec52aSSatish Balay ++Nl2; 21788d2ec52aSSatish Balay } 21798d2ec52aSSatish Balay if (debug) { 21808d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 21818d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d] + vstart[d])); 21828d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %g", (double)PetscRealPart(coords[vertex * dim + d]))); 21838d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 21848d2ec52aSSatish Balay } 2185cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2186cfb853baSMatthew G. Knepley } 21878d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2188cfb853baSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &coords)); 2189cfb853baSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 2190cfb853baSMatthew G. Knepley PetscCall(VecDestroy(&coordinates)); 21918d2ec52aSSatish Balay // Build SF 21928d2ec52aSSatish Balay PetscCheck(Nl == Nl2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Initial number of leaves %" PetscInt_FMT " != %" PetscInt_FMT " final number", Nl, Nl2); 21938d2ec52aSSatish Balay PetscCall(DMGetPointSF(dm, &sf)); 21948d2ec52aSSatish Balay PetscCall(PetscSFSetGraph(sf, numCells + numVertices, Nl, leaves, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 21958d2ec52aSSatish Balay if (debug) PetscCall(PetscSFView(sf, PETSC_VIEWER_STDOUT_WORLD)); 2196cfb853baSMatthew G. Knepley //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper)); 2197cfb853baSMatthew G. Knepley // Attach the extent 2198cfb853baSMatthew G. Knepley { 2199cfb853baSMatthew G. Knepley PetscContainer c; 22008d2ec52aSSatish Balay PetscInt *extent, *lextent; 2201cfb853baSMatthew G. Knepley 2202cfb853baSMatthew G. Knepley PetscCall(PetscMalloc1(dim, &extent)); 22038d2ec52aSSatish Balay PetscCall(PetscMalloc1(dim, &lextent)); 22048d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22058d2ec52aSSatish Balay extent[d] = edges[d]; 22068d2ec52aSSatish Balay lextent[d] = ledges[d]; 22078d2ec52aSSatish Balay } 2208cfb853baSMatthew G. Knepley PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 220949abdd8aSBarry Smith PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 2210cfb853baSMatthew G. Knepley PetscCall(PetscContainerSetPointer(c, extent)); 2211cfb853baSMatthew G. Knepley PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c)); 2212cfb853baSMatthew G. Knepley PetscCall(PetscContainerDestroy(&c)); 22138d2ec52aSSatish Balay PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 22148d2ec52aSSatish Balay PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 22158d2ec52aSSatish Balay PetscCall(PetscContainerSetPointer(c, lextent)); 22168d2ec52aSSatish Balay PetscCall(PetscObjectCompose((PetscObject)dm, "_lextent", (PetscObject)c)); 22178d2ec52aSSatish Balay PetscCall(PetscContainerDestroy(&c)); 2218cfb853baSMatthew G. Knepley } 22198d2ec52aSSatish Balay PetscCall(PetscFree4(procs, lrank, rrank, supp)); 22208d2ec52aSSatish Balay PetscCall(PetscFree7(ledges, vertices, rvertices, vert, rvert, vstart, vtmp)); 22213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2222cfb853baSMatthew G. Knepley } 2223cfb853baSMatthew G. Knepley 2224cfb853baSMatthew G. Knepley /*@C 2225aaa8cc7dSPierre Jolivet DMPlexCreateHypercubicMesh - Creates a periodic mesh on the tensor product of unit intervals using only vertices and edges. 2226cfb853baSMatthew G. Knepley 2227cfb853baSMatthew G. Knepley Collective 2228cfb853baSMatthew G. Knepley 2229cfb853baSMatthew G. Knepley Input Parameters: 22308d2ec52aSSatish Balay + comm - The communicator for the `DM` object 2231cfb853baSMatthew G. Knepley . dim - The spatial dimension 223220f4b53cSBarry Smith . edges - Number of edges per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 223320f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 22348d2ec52aSSatish Balay . upper - The upper right corner, or `NULL` for (1, 1, 1) 22358d2ec52aSSatish Balay - overlap - The number of vertices in each direction to include in the overlap (default is 1) 2236cfb853baSMatthew G. Knepley 2237cfb853baSMatthew G. Knepley Output Parameter: 2238cfb853baSMatthew G. Knepley . dm - The DM object 2239cfb853baSMatthew G. Knepley 224020f4b53cSBarry Smith Level: beginner 224120f4b53cSBarry Smith 224220f4b53cSBarry Smith Note: 224320f4b53cSBarry Smith If you want to customize this mesh using options, you just need to 224420f4b53cSBarry Smith .vb 224520f4b53cSBarry Smith DMCreate(comm, &dm); 224620f4b53cSBarry Smith DMSetType(dm, DMPLEX); 224720f4b53cSBarry Smith DMSetFromOptions(dm); 224820f4b53cSBarry Smith .ve 224920f4b53cSBarry Smith and use the options on the `DMSetFromOptions()` page. 2250cfb853baSMatthew G. Knepley 2251cfb853baSMatthew G. Knepley The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively, 225220f4b53cSBarry Smith .vb 225320f4b53cSBarry Smith 18--0-19--2-20--4-18 225420f4b53cSBarry Smith | | | | 225520f4b53cSBarry Smith 13 15 17 13 225620f4b53cSBarry Smith | | | | 225720f4b53cSBarry Smith 24-12-25-14-26-16-24 225820f4b53cSBarry Smith | | | | 225920f4b53cSBarry Smith 7 9 11 7 226020f4b53cSBarry Smith | | | | 226120f4b53cSBarry Smith 21--6-22--8-23-10-21 226220f4b53cSBarry Smith | | | | 226320f4b53cSBarry Smith 1 3 5 1 226420f4b53cSBarry Smith | | | | 226520f4b53cSBarry Smith 18--0-19--2-20--4-18 226620f4b53cSBarry Smith .ve 2267cfb853baSMatthew G. Knepley 226876fbde31SPierre Jolivet .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 2269cfb853baSMatthew G. Knepley @*/ 22708d2ec52aSSatish Balay PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], PetscInt overlap, DM *dm) 2271cfb853baSMatthew G. Knepley { 2272cfb853baSMatthew G. Knepley PetscInt *edg; 2273cfb853baSMatthew G. Knepley PetscReal *low, *upp; 2274cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 2275cfb853baSMatthew G. Knepley PetscInt d; 2276cfb853baSMatthew G. Knepley 2277cfb853baSMatthew G. Knepley PetscFunctionBegin; 2278cfb853baSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 2279cfb853baSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 2280cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt)); 2281cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 2282cfb853baSMatthew G. Knepley edg[d] = edges ? edges[d] : 1; 2283cfb853baSMatthew G. Knepley low[d] = lower ? lower[d] : 0.; 2284cfb853baSMatthew G. Knepley upp[d] = upper ? upper[d] : 1.; 2285cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 2286cfb853baSMatthew G. Knepley } 22878d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, overlap, bdt)); 2288cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edg, low, upp, bdt)); 22893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2290cfb853baSMatthew G. Knepley } 2291cfb853baSMatthew G. Knepley 2292cc4c1da9SBarry Smith /*@ 2293a1cb98faSBarry Smith DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database. 2294a9074c1eSMatthew G. Knepley 229520f4b53cSBarry Smith Logically Collective 2296a9074c1eSMatthew G. Knepley 2297a9074c1eSMatthew G. Knepley Input Parameters: 229820f4b53cSBarry Smith + dm - the `DM` context 2299a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 2300a9074c1eSMatthew G. Knepley 2301a1cb98faSBarry Smith Level: advanced 2302a1cb98faSBarry Smith 2303a1cb98faSBarry Smith Note: 2304a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 2305a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 2306a9074c1eSMatthew G. Knepley 23071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()` 2308a9074c1eSMatthew G. Knepley @*/ 2309d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 2310d71ae5a4SJacob Faibussowitsch { 2311a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2312a9074c1eSMatthew G. Knepley 2313a9074c1eSMatthew G. Knepley PetscFunctionBegin; 2314a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 23159566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 23169566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 23173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2318a9074c1eSMatthew G. Knepley } 2319a9074c1eSMatthew G. Knepley 23209318fe57SMatthew G. Knepley /* Remap geometry to cylinder 232161a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 232261a622f3SMatthew G. Knepley 23239318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 23249318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 23259318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 23260510c589SMatthew G. Knepley 23279318fe57SMatthew G. Knepley phi = arctan(y/x) 23289318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 23299318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 23300510c589SMatthew G. Knepley 23319318fe57SMatthew G. Knepley so we remap them using 23320510c589SMatthew G. Knepley 23339318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 23349318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 23350510c589SMatthew G. Knepley 23369318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 23379318fe57SMatthew G. Knepley */ 2338d71ae5a4SJacob 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[]) 2339d71ae5a4SJacob Faibussowitsch { 23409318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 23419318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 234222cc497dSMatthew G. Knepley 23439318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 23449318fe57SMatthew G. Knepley f0[0] = u[0]; 23459318fe57SMatthew G. Knepley f0[1] = u[1]; 23469318fe57SMatthew G. Knepley } else { 23479318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 23480510c589SMatthew G. Knepley 23499318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 23509318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 23519318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 23529318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 23539318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 23549318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 23559318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 23569318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 23579318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 23589318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 23599318fe57SMatthew G. Knepley } else { 23609318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 23619318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 23629318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 23639318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 23649318fe57SMatthew G. Knepley } 23659318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 23669318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 23679318fe57SMatthew G. Knepley } 23689318fe57SMatthew G. Knepley f0[2] = u[2]; 23699318fe57SMatthew G. Knepley } 23700510c589SMatthew G. Knepley 237149704ca5SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ, PetscInt Nr) 2372d71ae5a4SJacob Faibussowitsch { 23730510c589SMatthew G. Knepley const PetscInt dim = 3; 23749318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 2375d8c47e87SMatthew G. Knepley PetscMPIInt rank; 23760510c589SMatthew G. Knepley 23770510c589SMatthew G. Knepley PetscFunctionBegin; 237846139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 23799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 23809566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 23810510c589SMatthew G. Knepley /* Create topology */ 23820510c589SMatthew G. Knepley { 23830510c589SMatthew G. Knepley PetscInt cone[8], c; 23840510c589SMatthew G. Knepley 2385dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 2386dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 2387006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 2388ae8bcbbbSMatthew G. Knepley numCells *= 3; 2389dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 2390006a8963SMatthew G. Knepley } 23919566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 23929566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 23939566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 2394dd400576SPatrick Sanan if (rank == 0) { 2395006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 23969371c9d4SSatish Balay cone[0] = 15; 23979371c9d4SSatish Balay cone[1] = 18; 23989371c9d4SSatish Balay cone[2] = 17; 23999371c9d4SSatish Balay cone[3] = 16; 24009371c9d4SSatish Balay cone[4] = 31; 24019371c9d4SSatish Balay cone[5] = 32; 24029371c9d4SSatish Balay cone[6] = 33; 24039371c9d4SSatish Balay cone[7] = 34; 24049566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 24059371c9d4SSatish Balay cone[0] = 16; 24069371c9d4SSatish Balay cone[1] = 17; 24079371c9d4SSatish Balay cone[2] = 24; 24089371c9d4SSatish Balay cone[3] = 23; 24099371c9d4SSatish Balay cone[4] = 32; 24109371c9d4SSatish Balay cone[5] = 36; 24119371c9d4SSatish Balay cone[6] = 37; 24129371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 24139566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 24149371c9d4SSatish Balay cone[0] = 18; 24159371c9d4SSatish Balay cone[1] = 27; 24169371c9d4SSatish Balay cone[2] = 24; 24179371c9d4SSatish Balay cone[3] = 17; 24189371c9d4SSatish Balay cone[4] = 34; 24199371c9d4SSatish Balay cone[5] = 33; 24209371c9d4SSatish Balay cone[6] = 37; 24219371c9d4SSatish Balay cone[7] = 38; 24229566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 24239371c9d4SSatish Balay cone[0] = 29; 24249371c9d4SSatish Balay cone[1] = 27; 24259371c9d4SSatish Balay cone[2] = 18; 24269371c9d4SSatish Balay cone[3] = 15; 24279371c9d4SSatish Balay cone[4] = 35; 24289371c9d4SSatish Balay cone[5] = 31; 24299371c9d4SSatish Balay cone[6] = 34; 24309371c9d4SSatish Balay cone[7] = 38; 24319566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 24329371c9d4SSatish Balay cone[0] = 29; 24339371c9d4SSatish Balay cone[1] = 15; 24349371c9d4SSatish Balay cone[2] = 16; 24359371c9d4SSatish Balay cone[3] = 23; 24369371c9d4SSatish Balay cone[4] = 35; 24379371c9d4SSatish Balay cone[5] = 36; 24389371c9d4SSatish Balay cone[6] = 32; 24399371c9d4SSatish Balay cone[7] = 31; 24409566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2441006a8963SMatthew G. Knepley 24429371c9d4SSatish Balay cone[0] = 31; 24439371c9d4SSatish Balay cone[1] = 34; 24449371c9d4SSatish Balay cone[2] = 33; 24459371c9d4SSatish Balay cone[3] = 32; 24469371c9d4SSatish Balay cone[4] = 19; 24479371c9d4SSatish Balay cone[5] = 22; 24489371c9d4SSatish Balay cone[6] = 21; 24499371c9d4SSatish Balay cone[7] = 20; 24509566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 24519371c9d4SSatish Balay cone[0] = 32; 24529371c9d4SSatish Balay cone[1] = 33; 24539371c9d4SSatish Balay cone[2] = 37; 24549371c9d4SSatish Balay cone[3] = 36; 24559371c9d4SSatish Balay cone[4] = 22; 24569371c9d4SSatish Balay cone[5] = 25; 24579371c9d4SSatish Balay cone[6] = 26; 24589371c9d4SSatish Balay cone[7] = 21; 24599566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 24609371c9d4SSatish Balay cone[0] = 34; 24619371c9d4SSatish Balay cone[1] = 38; 24629371c9d4SSatish Balay cone[2] = 37; 24639371c9d4SSatish Balay cone[3] = 33; 24649371c9d4SSatish Balay cone[4] = 20; 24659371c9d4SSatish Balay cone[5] = 21; 24669371c9d4SSatish Balay cone[6] = 26; 24679371c9d4SSatish Balay cone[7] = 28; 24689566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 24699371c9d4SSatish Balay cone[0] = 35; 24709371c9d4SSatish Balay cone[1] = 38; 24719371c9d4SSatish Balay cone[2] = 34; 24729371c9d4SSatish Balay cone[3] = 31; 24739371c9d4SSatish Balay cone[4] = 30; 24749371c9d4SSatish Balay cone[5] = 19; 24759371c9d4SSatish Balay cone[6] = 20; 24769371c9d4SSatish Balay cone[7] = 28; 24779566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 24789371c9d4SSatish Balay cone[0] = 35; 24799371c9d4SSatish Balay cone[1] = 31; 24809371c9d4SSatish Balay cone[2] = 32; 24819371c9d4SSatish Balay cone[3] = 36; 24829371c9d4SSatish Balay cone[4] = 30; 24839371c9d4SSatish Balay cone[5] = 25; 24849371c9d4SSatish Balay cone[6] = 22; 24859371c9d4SSatish Balay cone[7] = 19; 24869566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 2487ae8bcbbbSMatthew G. Knepley 24889371c9d4SSatish Balay cone[0] = 19; 24899371c9d4SSatish Balay cone[1] = 20; 24909371c9d4SSatish Balay cone[2] = 21; 24919371c9d4SSatish Balay cone[3] = 22; 24929371c9d4SSatish Balay cone[4] = 15; 24939371c9d4SSatish Balay cone[5] = 16; 24949371c9d4SSatish Balay cone[6] = 17; 24959371c9d4SSatish Balay cone[7] = 18; 24969566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 24979371c9d4SSatish Balay cone[0] = 22; 24989371c9d4SSatish Balay cone[1] = 21; 24999371c9d4SSatish Balay cone[2] = 26; 25009371c9d4SSatish Balay cone[3] = 25; 25019371c9d4SSatish Balay cone[4] = 16; 25029371c9d4SSatish Balay cone[5] = 23; 25039371c9d4SSatish Balay cone[6] = 24; 25049371c9d4SSatish Balay cone[7] = 17; 25059566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 25069371c9d4SSatish Balay cone[0] = 20; 25079371c9d4SSatish Balay cone[1] = 28; 25089371c9d4SSatish Balay cone[2] = 26; 25099371c9d4SSatish Balay cone[3] = 21; 25109371c9d4SSatish Balay cone[4] = 18; 25119371c9d4SSatish Balay cone[5] = 17; 25129371c9d4SSatish Balay cone[6] = 24; 25139371c9d4SSatish Balay cone[7] = 27; 25149566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 25159371c9d4SSatish Balay cone[0] = 30; 25169371c9d4SSatish Balay cone[1] = 28; 25179371c9d4SSatish Balay cone[2] = 20; 25189371c9d4SSatish Balay cone[3] = 19; 25199371c9d4SSatish Balay cone[4] = 29; 25209371c9d4SSatish Balay cone[5] = 15; 25219371c9d4SSatish Balay cone[6] = 18; 25229371c9d4SSatish Balay cone[7] = 27; 25239566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 25249371c9d4SSatish Balay cone[0] = 30; 25259371c9d4SSatish Balay cone[1] = 19; 25269371c9d4SSatish Balay cone[2] = 22; 25279371c9d4SSatish Balay cone[3] = 25; 25289371c9d4SSatish Balay cone[4] = 29; 25299371c9d4SSatish Balay cone[5] = 23; 25309371c9d4SSatish Balay cone[6] = 16; 25319371c9d4SSatish Balay cone[7] = 15; 25329566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 2533006a8963SMatthew G. Knepley } else { 25349371c9d4SSatish Balay cone[0] = 5; 25359371c9d4SSatish Balay cone[1] = 8; 25369371c9d4SSatish Balay cone[2] = 7; 25379371c9d4SSatish Balay cone[3] = 6; 25389371c9d4SSatish Balay cone[4] = 9; 25399371c9d4SSatish Balay cone[5] = 12; 25409371c9d4SSatish Balay cone[6] = 11; 25419371c9d4SSatish Balay cone[7] = 10; 25429566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 25439371c9d4SSatish Balay cone[0] = 6; 25449371c9d4SSatish Balay cone[1] = 7; 25459371c9d4SSatish Balay cone[2] = 14; 25469371c9d4SSatish Balay cone[3] = 13; 25479371c9d4SSatish Balay cone[4] = 12; 25489371c9d4SSatish Balay cone[5] = 15; 25499371c9d4SSatish Balay cone[6] = 16; 25509371c9d4SSatish Balay cone[7] = 11; 25519566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 25529371c9d4SSatish Balay cone[0] = 8; 25539371c9d4SSatish Balay cone[1] = 17; 25549371c9d4SSatish Balay cone[2] = 14; 25559371c9d4SSatish Balay cone[3] = 7; 25569371c9d4SSatish Balay cone[4] = 10; 25579371c9d4SSatish Balay cone[5] = 11; 25589371c9d4SSatish Balay cone[6] = 16; 25599371c9d4SSatish Balay cone[7] = 18; 25609566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 25619371c9d4SSatish Balay cone[0] = 19; 25629371c9d4SSatish Balay cone[1] = 17; 25639371c9d4SSatish Balay cone[2] = 8; 25649371c9d4SSatish Balay cone[3] = 5; 25659371c9d4SSatish Balay cone[4] = 20; 25669371c9d4SSatish Balay cone[5] = 9; 25679371c9d4SSatish Balay cone[6] = 10; 25689371c9d4SSatish Balay cone[7] = 18; 25699566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 25709371c9d4SSatish Balay cone[0] = 19; 25719371c9d4SSatish Balay cone[1] = 5; 25729371c9d4SSatish Balay cone[2] = 6; 25739371c9d4SSatish Balay cone[3] = 13; 25749371c9d4SSatish Balay cone[4] = 20; 25759371c9d4SSatish Balay cone[5] = 15; 25769371c9d4SSatish Balay cone[6] = 12; 25779371c9d4SSatish Balay cone[7] = 9; 25789566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2579006a8963SMatthew G. Knepley } 2580d8c47e87SMatthew G. Knepley } 25819566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 25829566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 25830510c589SMatthew G. Knepley } 2584dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 25850510c589SMatthew G. Knepley { 25860510c589SMatthew G. Knepley Vec coordinates; 25870510c589SMatthew G. Knepley PetscSection coordSection; 25880510c589SMatthew G. Knepley PetscScalar *coords; 25890510c589SMatthew G. Knepley PetscInt coordSize, v; 25900510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 25910510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 25920510c589SMatthew G. Knepley 25930510c589SMatthew G. Knepley /* Build coordinates */ 25949566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 25959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 25969566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 25979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 25980510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 25999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 26009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 26010510c589SMatthew G. Knepley } 26029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 26039566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 26049566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 26059566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 26069566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 26079566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 26089566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 26099566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 2610dd400576SPatrick Sanan if (rank == 0) { 26119371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 26129371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 26139371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 26149371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 26159371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 26169371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 26179371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 26189371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 26199371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 26209371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 26219371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 26229371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 26239371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 26249371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 26259371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 26269371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 26279371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 26289371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 26299371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 26309371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 26319371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 26329371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 26339371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 26349371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 26359371c9d4SSatish Balay coords[8 * dim + 0] = dis; 26369371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 26379371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 26389371c9d4SSatish Balay coords[9 * dim + 0] = dis; 26399371c9d4SSatish Balay coords[9 * dim + 1] = dis; 26409371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 26419371c9d4SSatish Balay coords[10 * dim + 0] = dis; 26429371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 26439371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 26449371c9d4SSatish Balay coords[11 * dim + 0] = dis; 26459371c9d4SSatish Balay coords[11 * dim + 1] = dis; 26469371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 26479371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 26489371c9d4SSatish Balay coords[12 * dim + 1] = dis; 26499371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 26509371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 26519371c9d4SSatish Balay coords[13 * dim + 1] = dis; 26529371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 26539371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 26549371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 26559371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 26569371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 26579371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 26589371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 2659ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 26609371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 26619371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 26629371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 26639371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 26649371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 26659371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 26669371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 26679371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 26689371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 26699371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 26709371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 26719371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 26729371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 26739371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 26749371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 26759371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 26769371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 26779371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 26789371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 26799371c9d4SSatish Balay coords[22 * dim + 1] = dis; 26809371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 26819371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 26829371c9d4SSatish Balay coords[23 * dim + 1] = dis; 26839371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 2684ae8bcbbbSMatthew G. Knepley } 2685d8c47e87SMatthew G. Knepley } 26869566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 26879566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 26889566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 26890510c589SMatthew G. Knepley } 2690006a8963SMatthew G. Knepley /* Create periodicity */ 2691006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 26926858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 26936858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 2694006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 2695ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 26966858538eSMatthew G. Knepley PetscInt numZCells = 3; 2697006a8963SMatthew G. Knepley 26986858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 26996858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 27004fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 2701006a8963SMatthew G. Knepley } 2702dbc1dc17SMatthew G. Knepley { 27039318fe57SMatthew G. Knepley DM cdm; 27049318fe57SMatthew G. Knepley PetscDS cds; 27059318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 2706dbc1dc17SMatthew G. Knepley 270749704ca5SMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL)); 27089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 27099566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 27109566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 2711dbc1dc17SMatthew G. Knepley } 271246139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 271346139095SJed Brown 27149318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 27159566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 271649704ca5SMatthew G. Knepley 271749704ca5SMatthew G. Knepley char oldprefix[PETSC_MAX_PATH_LEN]; 271849704ca5SMatthew G. Knepley const char *prefix; 271949704ca5SMatthew G. Knepley 272049704ca5SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 272149704ca5SMatthew G. Knepley PetscCall(PetscStrncpy(oldprefix, prefix, PETSC_MAX_PATH_LEN)); 272249704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, "petsc_cyl_ref_")); 272349704ca5SMatthew G. Knepley for (PetscInt r = 0; r < PetscMax(0, Nr); ++r) { 272449704ca5SMatthew G. Knepley DM rdm; 272549704ca5SMatthew G. Knepley 272649704ca5SMatthew G. Knepley PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 272749704ca5SMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &rdm)); 272849704ca5SMatthew G. Knepley } 272949704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldprefix)); 273049704ca5SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, snapToCylinder)); 273149704ca5SMatthew G. Knepley 273249704ca5SMatthew G. Knepley DMLabel bdlabel, edgelabel; 273349704ca5SMatthew G. Knepley IS faceIS; 273449704ca5SMatthew G. Knepley const PetscInt *faces; 273549704ca5SMatthew G. Knepley PetscInt Nf; 273649704ca5SMatthew G. Knepley 273749704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 273849704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 273949704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "generatrix")); 274049704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "generatrix", &edgelabel)); 274149704ca5SMatthew G. Knepley PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 274249704ca5SMatthew G. Knepley // Remove faces on top and bottom 274349704ca5SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(bdlabel, 1, &faceIS)); 2744ba1b3593SJeremy L Thompson if (faceIS) { 274549704ca5SMatthew G. Knepley PetscCall(ISGetLocalSize(faceIS, &Nf)); 274649704ca5SMatthew G. Knepley PetscCall(ISGetIndices(faceIS, &faces)); 274749704ca5SMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 274849704ca5SMatthew G. Knepley PetscReal vol, normal[3]; 274949704ca5SMatthew G. Knepley 275049704ca5SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFVM(dm, faces[f], &vol, NULL, normal)); 275149704ca5SMatthew G. Knepley if (PetscAbsReal(normal[2]) < PETSC_SMALL) PetscCall(DMLabelSetValue(edgelabel, faces[f], 1)); 275249704ca5SMatthew G. Knepley } 275349704ca5SMatthew G. Knepley PetscCall(ISRestoreIndices(faceIS, &faces)); 275449704ca5SMatthew G. Knepley PetscCall(ISDestroy(&faceIS)); 2755ba1b3593SJeremy L Thompson } 275649704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, bdlabel)); 275749704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, edgelabel)); 27583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 27590510c589SMatthew G. Knepley } 27600510c589SMatthew G. Knepley 276124119c2aSMatthew G. Knepley /*@ 27629318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 276324119c2aSMatthew G. Knepley 2764d083f849SBarry Smith Collective 276524119c2aSMatthew G. Knepley 276624119c2aSMatthew G. Knepley Input Parameters: 2767a1cb98faSBarry Smith + comm - The communicator for the `DM` object 276849704ca5SMatthew G. Knepley . periodicZ - The boundary type for the Z direction 276949704ca5SMatthew G. Knepley - Nr - The number of refinements to carry out 277024119c2aSMatthew G. Knepley 277124119c2aSMatthew G. Knepley Output Parameter: 277220f4b53cSBarry Smith . dm - The `DM` object 277324119c2aSMatthew G. Knepley 277424119c2aSMatthew G. Knepley Level: beginner 277524119c2aSMatthew G. Knepley 2776a1cb98faSBarry Smith Note: 2777a4e35b19SJacob Faibussowitsch Here is the output numbering looking from the bottom of the cylinder\: 2778a1cb98faSBarry Smith .vb 2779a1cb98faSBarry Smith 17-----14 2780a1cb98faSBarry Smith | | 2781a1cb98faSBarry Smith | 2 | 2782a1cb98faSBarry Smith | | 2783a1cb98faSBarry Smith 17-----8-----7-----14 2784a1cb98faSBarry Smith | | | | 2785a1cb98faSBarry Smith | 3 | 0 | 1 | 2786a1cb98faSBarry Smith | | | | 2787a1cb98faSBarry Smith 19-----5-----6-----13 2788a1cb98faSBarry Smith | | 2789a1cb98faSBarry Smith | 4 | 2790a1cb98faSBarry Smith | | 2791a1cb98faSBarry Smith 19-----13 2792a1cb98faSBarry Smith 2793a1cb98faSBarry Smith and up through the top 2794a1cb98faSBarry Smith 2795a1cb98faSBarry Smith 18-----16 2796a1cb98faSBarry Smith | | 2797a1cb98faSBarry Smith | 2 | 2798a1cb98faSBarry Smith | | 2799a1cb98faSBarry Smith 18----10----11-----16 2800a1cb98faSBarry Smith | | | | 2801a1cb98faSBarry Smith | 3 | 0 | 1 | 2802a1cb98faSBarry Smith | | | | 2803a1cb98faSBarry Smith 20-----9----12-----15 2804a1cb98faSBarry Smith | | 2805a1cb98faSBarry Smith | 4 | 2806a1cb98faSBarry Smith | | 2807a1cb98faSBarry Smith 20-----15 2808a1cb98faSBarry Smith .ve 2809a1cb98faSBarry Smith 28101cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 281124119c2aSMatthew G. Knepley @*/ 281249704ca5SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, PetscInt Nr, DM *dm) 2813d71ae5a4SJacob Faibussowitsch { 28149318fe57SMatthew G. Knepley PetscFunctionBegin; 281549704ca5SMatthew G. Knepley PetscAssertPointer(dm, 4); 28169566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 28179566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 281849704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ, Nr)); 28193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 28209318fe57SMatthew G. Knepley } 28219318fe57SMatthew G. Knepley 2822d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 2823d71ae5a4SJacob Faibussowitsch { 282424119c2aSMatthew G. Knepley const PetscInt dim = 3; 2825412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 28269fe9f049SMatthew G. Knepley PetscMPIInt rank; 282724119c2aSMatthew G. Knepley 282824119c2aSMatthew G. Knepley PetscFunctionBegin; 282963a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 283046139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 28319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 28329566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 2833412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 28349566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 283524119c2aSMatthew G. Knepley /* Create topology */ 283624119c2aSMatthew G. Knepley { 283724119c2aSMatthew G. Knepley PetscInt cone[6], c; 283824119c2aSMatthew G. Knepley 2839dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 2840dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 28419566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 28429566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 28439566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 284424119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 28459371c9d4SSatish Balay cone[0] = c + n * 1; 28469371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 28479371c9d4SSatish Balay cone[2] = 0 + 3 * n; 28489371c9d4SSatish Balay cone[3] = c + n * 2; 28499371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 28509371c9d4SSatish Balay cone[5] = 1 + 3 * n; 28519566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 28529566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 285324119c2aSMatthew G. Knepley } 28549566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 28559566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 285624119c2aSMatthew G. Knepley } 285748a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 285824119c2aSMatthew G. Knepley /* Create cylinder geometry */ 285924119c2aSMatthew G. Knepley { 286024119c2aSMatthew G. Knepley Vec coordinates; 286124119c2aSMatthew G. Knepley PetscSection coordSection; 286224119c2aSMatthew G. Knepley PetscScalar *coords; 2863412e9a14SMatthew G. Knepley PetscInt coordSize, c; 286424119c2aSMatthew G. Knepley 286524119c2aSMatthew G. Knepley /* Build coordinates */ 28669566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 28679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 28689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 28699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 287024119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 28719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 28729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 287324119c2aSMatthew G. Knepley } 28749566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 28759566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 28769566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 28779566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 28789566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 28799566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 28809566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 28819566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 288224119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 28839371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 28849371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 28859371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 28869371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 28879371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 28889371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 288924119c2aSMatthew G. Knepley } 2890dd400576SPatrick Sanan if (rank == 0) { 28919371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 28929371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 28939371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 28949371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 28959371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 28969371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 28979fe9f049SMatthew G. Knepley } 28989566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 28999566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 29009566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 290124119c2aSMatthew G. Knepley } 290246139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 29039318fe57SMatthew G. Knepley /* Interpolate */ 29049566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 29053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29069318fe57SMatthew G. Knepley } 29079318fe57SMatthew G. Knepley 29089318fe57SMatthew G. Knepley /*@ 29099318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 29109318fe57SMatthew G. Knepley 29119318fe57SMatthew G. Knepley Collective 29129318fe57SMatthew G. Knepley 29139318fe57SMatthew G. Knepley Input Parameters: 2914a1cb98faSBarry Smith + comm - The communicator for the `DM` object 29159318fe57SMatthew G. Knepley . n - The number of wedges around the origin 29169318fe57SMatthew G. Knepley - interpolate - Create edges and faces 29179318fe57SMatthew G. Knepley 29189318fe57SMatthew G. Knepley Output Parameter: 2919a1cb98faSBarry Smith . dm - The `DM` object 29209318fe57SMatthew G. Knepley 29219318fe57SMatthew G. Knepley Level: beginner 29229318fe57SMatthew G. Knepley 29231cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 29249318fe57SMatthew G. Knepley @*/ 2925d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 2926d71ae5a4SJacob Faibussowitsch { 29279318fe57SMatthew G. Knepley PetscFunctionBegin; 29284f572ea9SToby Isaac PetscAssertPointer(dm, 4); 29299566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 29309566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 29319566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 29323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 293324119c2aSMatthew G. Knepley } 293424119c2aSMatthew G. Knepley 2935d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2936d71ae5a4SJacob Faibussowitsch { 293765a81367SMatthew G. Knepley PetscReal prod = 0.0; 293865a81367SMatthew G. Knepley PetscInt i; 293965a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 294065a81367SMatthew G. Knepley return PetscSqrtReal(prod); 294165a81367SMatthew G. Knepley } 2942dd2b43ebSStefano Zampini 2943d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 2944d71ae5a4SJacob Faibussowitsch { 294565a81367SMatthew G. Knepley PetscReal prod = 0.0; 294665a81367SMatthew G. Knepley PetscInt i; 294765a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += x[i] * y[i]; 294865a81367SMatthew G. Knepley return prod; 294965a81367SMatthew G. Knepley } 295065a81367SMatthew G. Knepley 295151a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 2952d71ae5a4SJacob 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[]) 2953d71ae5a4SJacob Faibussowitsch { 295451a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 295551a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 295651a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 295751a74b61SMatthew G. Knepley 295851a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 295951a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 296051a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 296151a74b61SMatthew G. Knepley } 296251a74b61SMatthew G. Knepley 2963d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 2964d71ae5a4SJacob Faibussowitsch { 296565a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 296665a81367SMatthew G. Knepley PetscSection coordSection; 296765a81367SMatthew G. Knepley Vec coordinates; 296865a81367SMatthew G. Knepley PetscScalar *coords; 296965a81367SMatthew G. Knepley PetscReal *coordsIn; 297007c565c5SJose E. Roman PetscInt numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, e; 297165a81367SMatthew G. Knepley PetscMPIInt rank; 297265a81367SMatthew G. Knepley 297365a81367SMatthew G. Knepley PetscFunctionBegin; 29749318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 297546139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 29769566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 29779566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 29789566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 297965a81367SMatthew G. Knepley switch (dim) { 29805c344501SMatthew G. Knepley case 1: 29815c344501SMatthew G. Knepley numCells = 16; 29825c344501SMatthew G. Knepley numVerts = numCells; 29835c344501SMatthew G. Knepley 29845c344501SMatthew G. Knepley // Build Topology 29855c344501SMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 29865c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 29875c344501SMatthew G. Knepley PetscCall(DMSetUp(dm)); 29885c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 29895c344501SMatthew G. Knepley PetscInt cone[2]; 29905c344501SMatthew G. Knepley 29915c344501SMatthew G. Knepley cone[0] = c + numCells; 29925c344501SMatthew G. Knepley cone[1] = (c + 1) % numVerts + numCells; 29935c344501SMatthew G. Knepley PetscCall(DMPlexSetCone(dm, c, cone)); 29945c344501SMatthew G. Knepley } 29955c344501SMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 29965c344501SMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 29975c344501SMatthew G. Knepley PetscCall(PetscMalloc1(numVerts * embedDim, &coordsIn)); 29985c344501SMatthew G. Knepley for (PetscInt v = 0; v < numVerts; ++v) { 29995c344501SMatthew G. Knepley const PetscReal rad = 2. * PETSC_PI * v / numVerts; 30005c344501SMatthew G. Knepley 30015c344501SMatthew G. Knepley coordsIn[v * embedDim + 0] = PetscCosReal(rad); 30025c344501SMatthew G. Knepley coordsIn[v * embedDim + 1] = PetscSinReal(rad); 30035c344501SMatthew G. Knepley } 30045c344501SMatthew G. Knepley break; 300565a81367SMatthew G. Knepley case 2: 300665a81367SMatthew G. Knepley if (simplex) { 300751a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 300851a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 300965a81367SMatthew G. Knepley const PetscInt degree = 5; 301051a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 301165a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 301265a81367SMatthew G. Knepley PetscInt cone[3]; 301307c565c5SJose E. Roman PetscInt *graph; 301465a81367SMatthew G. Knepley 30159371c9d4SSatish Balay vertex[0] *= R / radius; 30169371c9d4SSatish Balay vertex[1] *= R / radius; 30179371c9d4SSatish Balay vertex[2] *= R / radius; 3018dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 3019dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 302065a81367SMatthew G. Knepley firstVertex = numCells; 302151a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 302265a81367SMatthew G. Knepley 302365a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 302465a81367SMatthew G. Knepley 302565a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 302651a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 302765a81367SMatthew G. Knepley */ 302865a81367SMatthew G. Knepley /* Construct vertices */ 30299566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3030dd400576SPatrick Sanan if (rank == 0) { 303107c565c5SJose E. Roman for (PetscInt p = 0, i = 0; p < embedDim; ++p) { 303265a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 303365a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 303465a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 303565a81367SMatthew G. Knepley ++i; 303665a81367SMatthew G. Knepley } 303765a81367SMatthew G. Knepley } 303865a81367SMatthew G. Knepley } 303945da822fSValeria Barra } 304065a81367SMatthew G. Knepley /* Construct graph */ 30419566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 304207c565c5SJose E. Roman for (PetscInt i = 0; i < numVerts; ++i) { 304307c565c5SJose E. Roman PetscInt k = 0; 304407c565c5SJose E. Roman for (PetscInt j = 0; j < numVerts; ++j) { 30459371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 30469371c9d4SSatish Balay graph[i * numVerts + j] = 1; 30479371c9d4SSatish Balay ++k; 30489371c9d4SSatish Balay } 304965a81367SMatthew G. Knepley } 305063a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 305165a81367SMatthew G. Knepley } 305265a81367SMatthew G. Knepley /* Build Topology */ 30539566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 305407c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 30559566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 305665a81367SMatthew G. Knepley /* Cells */ 305707c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 305807c565c5SJose E. Roman for (PetscInt j = 0; j < i; ++j) { 305907c565c5SJose E. Roman for (PetscInt k = 0; k < j; ++k) { 306065a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 30619371c9d4SSatish Balay cone[0] = firstVertex + i; 30629371c9d4SSatish Balay cone[1] = firstVertex + j; 30639371c9d4SSatish Balay cone[2] = firstVertex + k; 306465a81367SMatthew G. Knepley /* Check orientation */ 306565a81367SMatthew G. Knepley { 30669371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 30679371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 30689371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 30699371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 30709371c9d4SSatish Balay }; 307165a81367SMatthew G. Knepley PetscReal normal[3]; 307265a81367SMatthew G. Knepley PetscInt e, f; 307365a81367SMatthew G. Knepley 307465a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 307565a81367SMatthew G. Knepley normal[d] = 0.0; 307665a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3077ad540459SPierre 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]); 307865a81367SMatthew G. Knepley } 307965a81367SMatthew G. Knepley } 30809371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 30819371c9d4SSatish Balay PetscInt tmp = cone[1]; 30829371c9d4SSatish Balay cone[1] = cone[2]; 30839371c9d4SSatish Balay cone[2] = tmp; 308465a81367SMatthew G. Knepley } 308565a81367SMatthew G. Knepley } 30869566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 308765a81367SMatthew G. Knepley } 308865a81367SMatthew G. Knepley } 308965a81367SMatthew G. Knepley } 309065a81367SMatthew G. Knepley } 30919566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 30929566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 30939566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 309465a81367SMatthew G. Knepley } else { 30952829fed8SMatthew G. Knepley /* 30962829fed8SMatthew G. Knepley 12-21--13 30972829fed8SMatthew G. Knepley | | 30982829fed8SMatthew G. Knepley 25 4 24 30992829fed8SMatthew G. Knepley | | 31002829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 31012829fed8SMatthew G. Knepley | | | | 31022829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 31032829fed8SMatthew G. Knepley | | | | 31042829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 31052829fed8SMatthew G. Knepley | | 31062829fed8SMatthew G. Knepley 20 1 19 31072829fed8SMatthew G. Knepley | | 31082829fed8SMatthew G. Knepley 10-18--11 31092829fed8SMatthew G. Knepley | | 31102829fed8SMatthew G. Knepley 23 2 22 31112829fed8SMatthew G. Knepley | | 31122829fed8SMatthew G. Knepley 12-21--13 31132829fed8SMatthew G. Knepley */ 31142829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 31152829fed8SMatthew G. Knepley 3116dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 3117dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 3118dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 311965a81367SMatthew G. Knepley firstVertex = numCells; 312065a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 31212829fed8SMatthew G. Knepley /* Build Topology */ 31229566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 312307c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 312448a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 31259566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3126dd400576SPatrick Sanan if (rank == 0) { 31272829fed8SMatthew G. Knepley /* Cell 0 */ 31289371c9d4SSatish Balay cone[0] = 14; 31299371c9d4SSatish Balay cone[1] = 15; 31309371c9d4SSatish Balay cone[2] = 16; 31319371c9d4SSatish Balay cone[3] = 17; 31329566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 31339371c9d4SSatish Balay ornt[0] = 0; 31349371c9d4SSatish Balay ornt[1] = 0; 31359371c9d4SSatish Balay ornt[2] = 0; 31369371c9d4SSatish Balay ornt[3] = 0; 31379566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 31382829fed8SMatthew G. Knepley /* Cell 1 */ 31399371c9d4SSatish Balay cone[0] = 18; 31409371c9d4SSatish Balay cone[1] = 19; 31419371c9d4SSatish Balay cone[2] = 14; 31429371c9d4SSatish Balay cone[3] = 20; 31439566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 31449371c9d4SSatish Balay ornt[0] = 0; 31459371c9d4SSatish Balay ornt[1] = 0; 31469371c9d4SSatish Balay ornt[2] = -1; 31479371c9d4SSatish Balay ornt[3] = 0; 31489566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 31492829fed8SMatthew G. Knepley /* Cell 2 */ 31509371c9d4SSatish Balay cone[0] = 21; 31519371c9d4SSatish Balay cone[1] = 22; 31529371c9d4SSatish Balay cone[2] = 18; 31539371c9d4SSatish Balay cone[3] = 23; 31549566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 31559371c9d4SSatish Balay ornt[0] = 0; 31569371c9d4SSatish Balay ornt[1] = 0; 31579371c9d4SSatish Balay ornt[2] = -1; 31589371c9d4SSatish Balay ornt[3] = 0; 31599566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 31602829fed8SMatthew G. Knepley /* Cell 3 */ 31619371c9d4SSatish Balay cone[0] = 19; 31629371c9d4SSatish Balay cone[1] = 22; 31639371c9d4SSatish Balay cone[2] = 24; 31649371c9d4SSatish Balay cone[3] = 15; 31659566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 31669371c9d4SSatish Balay ornt[0] = -1; 31679371c9d4SSatish Balay ornt[1] = -1; 31689371c9d4SSatish Balay ornt[2] = 0; 31699371c9d4SSatish Balay ornt[3] = -1; 31709566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 31712829fed8SMatthew G. Knepley /* Cell 4 */ 31729371c9d4SSatish Balay cone[0] = 16; 31739371c9d4SSatish Balay cone[1] = 24; 31749371c9d4SSatish Balay cone[2] = 21; 31759371c9d4SSatish Balay cone[3] = 25; 31769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 31779371c9d4SSatish Balay ornt[0] = -1; 31789371c9d4SSatish Balay ornt[1] = -1; 31799371c9d4SSatish Balay ornt[2] = -1; 31809371c9d4SSatish Balay ornt[3] = 0; 31819566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 31822829fed8SMatthew G. Knepley /* Cell 5 */ 31839371c9d4SSatish Balay cone[0] = 20; 31849371c9d4SSatish Balay cone[1] = 17; 31859371c9d4SSatish Balay cone[2] = 25; 31869371c9d4SSatish Balay cone[3] = 23; 31879566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 31889371c9d4SSatish Balay ornt[0] = -1; 31899371c9d4SSatish Balay ornt[1] = -1; 31909371c9d4SSatish Balay ornt[2] = -1; 31919371c9d4SSatish Balay ornt[3] = -1; 31929566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 31932829fed8SMatthew G. Knepley /* Edges */ 31949371c9d4SSatish Balay cone[0] = 6; 31959371c9d4SSatish Balay cone[1] = 7; 31969566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 31979371c9d4SSatish Balay cone[0] = 7; 31989371c9d4SSatish Balay cone[1] = 8; 31999566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 32009371c9d4SSatish Balay cone[0] = 8; 32019371c9d4SSatish Balay cone[1] = 9; 32029566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 32039371c9d4SSatish Balay cone[0] = 9; 32049371c9d4SSatish Balay cone[1] = 6; 32059566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 32069371c9d4SSatish Balay cone[0] = 10; 32079371c9d4SSatish Balay cone[1] = 11; 32089566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 32099371c9d4SSatish Balay cone[0] = 11; 32109371c9d4SSatish Balay cone[1] = 7; 32119566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 32129371c9d4SSatish Balay cone[0] = 6; 32139371c9d4SSatish Balay cone[1] = 10; 32149566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 32159371c9d4SSatish Balay cone[0] = 12; 32169371c9d4SSatish Balay cone[1] = 13; 32179566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 32189371c9d4SSatish Balay cone[0] = 13; 32199371c9d4SSatish Balay cone[1] = 11; 32209566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 32219371c9d4SSatish Balay cone[0] = 10; 32229371c9d4SSatish Balay cone[1] = 12; 32239566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 32249371c9d4SSatish Balay cone[0] = 13; 32259371c9d4SSatish Balay cone[1] = 8; 32269566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 32279371c9d4SSatish Balay cone[0] = 12; 32289371c9d4SSatish Balay cone[1] = 9; 32299566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 323045da822fSValeria Barra } 32319566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 32329566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 32332829fed8SMatthew G. Knepley /* Build coordinates */ 32349566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3235dd400576SPatrick Sanan if (rank == 0) { 32369371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 32379371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 32389371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 32399371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 32409371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 32419371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 32429371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 32439371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 32449371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 32459371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 32469371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 32479371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 32489371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 32499371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 32509371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 32519371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 32529371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 32539371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 32549371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 32559371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 32569371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 32579371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 32589371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 32599371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 326065a81367SMatthew G. Knepley } 326145da822fSValeria Barra } 326265a81367SMatthew G. Knepley break; 326365a81367SMatthew G. Knepley case 3: 3264116ded15SMatthew G. Knepley if (simplex) { 3265116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 326651a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 326751a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 326851a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 3269116ded15SMatthew G. Knepley const PetscInt degree = 12; 3270116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 32719371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 32729371c9d4SSatish Balay {0, 1, 2, 3}, 32739371c9d4SSatish Balay {0, 2, 3, 1}, 32749371c9d4SSatish Balay {0, 3, 1, 2}, 32759371c9d4SSatish Balay {1, 0, 3, 2}, 32769371c9d4SSatish Balay {1, 2, 0, 3}, 32779371c9d4SSatish Balay {1, 3, 2, 0}, 32789371c9d4SSatish Balay {2, 0, 1, 3}, 32799371c9d4SSatish Balay {2, 1, 3, 0}, 32809371c9d4SSatish Balay {2, 3, 0, 1}, 32819371c9d4SSatish Balay {3, 0, 2, 1}, 32829371c9d4SSatish Balay {3, 1, 0, 2}, 32839371c9d4SSatish Balay {3, 2, 1, 0} 32849371c9d4SSatish Balay }; 3285116ded15SMatthew G. Knepley PetscInt cone[4]; 3286116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 3287116ded15SMatthew G. Knepley 32889371c9d4SSatish Balay vertexA[0] *= R; 32899371c9d4SSatish Balay vertexA[1] *= R; 32909371c9d4SSatish Balay vertexA[2] *= R; 32919371c9d4SSatish Balay vertexA[3] *= R; 32929371c9d4SSatish Balay vertexB[0] *= R; 32939371c9d4SSatish Balay vertexB[1] *= R; 32949371c9d4SSatish Balay vertexB[2] *= R; 32959371c9d4SSatish Balay vertexB[3] *= R; 32969371c9d4SSatish Balay vertexC[0] *= R; 32979371c9d4SSatish Balay vertexC[1] *= R; 32989371c9d4SSatish Balay vertexC[2] *= R; 32999371c9d4SSatish Balay vertexC[3] *= R; 3300dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 3301dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 3302116ded15SMatthew G. Knepley firstVertex = numCells; 3303116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 3304116ded15SMatthew G. Knepley 3305116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 3306116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 3307116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 3308116ded15SMatthew G. Knepley 3309116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 33106333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 3311116ded15SMatthew G. Knepley 3312116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 3313116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 3314116ded15SMatthew G. Knepley */ 3315116ded15SMatthew G. Knepley /* Construct vertices */ 33169566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3317116ded15SMatthew G. Knepley i = 0; 3318dd400576SPatrick Sanan if (rank == 0) { 3319116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3320116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3321116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3322116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 3323116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 3324116ded15SMatthew G. Knepley ++i; 3325116ded15SMatthew G. Knepley } 3326116ded15SMatthew G. Knepley } 3327116ded15SMatthew G. Knepley } 3328116ded15SMatthew G. Knepley } 3329116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 3330116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 3331116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3332116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 3333116ded15SMatthew G. Knepley ++i; 3334116ded15SMatthew G. Knepley } 3335116ded15SMatthew G. Knepley } 3336116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 3337116ded15SMatthew G. Knepley s[3] = 1; 3338116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3339116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3340116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3341116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 3342116ded15SMatthew G. Knepley ++i; 3343116ded15SMatthew G. Knepley } 3344116ded15SMatthew G. Knepley } 3345116ded15SMatthew G. Knepley } 3346116ded15SMatthew G. Knepley } 334745da822fSValeria Barra } 334863a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 3349116ded15SMatthew G. Knepley /* Construct graph */ 33509566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 3351116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 3352116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 33539371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 33549371c9d4SSatish Balay graph[i * numVerts + j] = 1; 33559371c9d4SSatish Balay ++k; 33569371c9d4SSatish Balay } 3357116ded15SMatthew G. Knepley } 335863a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 3359116ded15SMatthew G. Knepley } 3360116ded15SMatthew G. Knepley /* Build Topology */ 33619566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 336207c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 33639566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3364116ded15SMatthew G. Knepley /* Cells */ 3365dd400576SPatrick Sanan if (rank == 0) { 336607c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 3367116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 3368116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 3369116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 33709371c9d4SSatish 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]) { 33719371c9d4SSatish Balay cone[0] = firstVertex + i; 33729371c9d4SSatish Balay cone[1] = firstVertex + j; 33739371c9d4SSatish Balay cone[2] = firstVertex + k; 33749371c9d4SSatish Balay cone[3] = firstVertex + l; 3375116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 3376116ded15SMatthew G. Knepley { 33779371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 33789371c9d4SSatish 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}}}, 3379116ded15SMatthew G. Knepley 33809371c9d4SSatish 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}}}, 3381116ded15SMatthew G. Knepley 33829371c9d4SSatish 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}}}, 3383116ded15SMatthew G. Knepley 33849371c9d4SSatish 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}} } 33859371c9d4SSatish Balay }; 3386116ded15SMatthew G. Knepley PetscReal normal[4]; 3387116ded15SMatthew G. Knepley PetscInt e, f, g; 3388116ded15SMatthew G. Knepley 3389116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 3390116ded15SMatthew G. Knepley normal[d] = 0.0; 3391116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3392116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 3393116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 3394116ded15SMatthew 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]); 3395116ded15SMatthew G. Knepley } 3396116ded15SMatthew G. Knepley } 3397116ded15SMatthew G. Knepley } 3398116ded15SMatthew G. Knepley } 33999371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 34009371c9d4SSatish Balay PetscInt tmp = cone[1]; 34019371c9d4SSatish Balay cone[1] = cone[2]; 34029371c9d4SSatish Balay cone[2] = tmp; 34039371c9d4SSatish Balay } 3404116ded15SMatthew G. Knepley } 34059566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 3406116ded15SMatthew G. Knepley } 3407116ded15SMatthew G. Knepley } 3408116ded15SMatthew G. Knepley } 3409116ded15SMatthew G. Knepley } 3410116ded15SMatthew G. Knepley } 341145da822fSValeria Barra } 34129566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 34139566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 34149566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 3415116ded15SMatthew G. Knepley } 3416f4d061e9SPierre Jolivet break; 3417d71ae5a4SJacob Faibussowitsch default: 3418d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 341965a81367SMatthew G. Knepley } 342065a81367SMatthew G. Knepley /* Create coordinates */ 34219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 34229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 34239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 34249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 34252829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 34269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 34279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 34282829fed8SMatthew G. Knepley } 34299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 34309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 34319566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 34329566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 34339566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 34349566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 34359566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 34369566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 34379371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 3438ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 34399566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 34409566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 34419566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 34429566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 344351a74b61SMatthew G. Knepley { 344451a74b61SMatthew G. Knepley DM cdm; 344551a74b61SMatthew G. Knepley PetscDS cds; 34469318fe57SMatthew G. Knepley PetscScalar c = R; 344751a74b61SMatthew G. Knepley 3448e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, snapToSphere)); 34499566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 34509566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 34519566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 345251a74b61SMatthew G. Knepley } 345346139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 34549318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 34559566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 34563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 34579318fe57SMatthew G. Knepley } 34589318fe57SMatthew G. Knepley 3459b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 3460b7f5c055SJed Brown 3461b7f5c055SJed Brown /* 3462b7f5c055SJed Brown The Schwarz P implicit surface is 3463b7f5c055SJed Brown 3464b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 3465b7f5c055SJed Brown */ 3466d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3467d71ae5a4SJacob Faibussowitsch { 3468b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 3469b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 3470b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 3471b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3472b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 3473ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 3474b7f5c055SJed Brown } 3475b7f5c055SJed Brown } 3476b7f5c055SJed Brown 34774663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3478d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3479d71ae5a4SJacob Faibussowitsch { 3480ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 34813ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 34824663dae6SJed Brown } 34834663dae6SJed Brown 3484b7f5c055SJed Brown /* 3485b7f5c055SJed Brown The Gyroid implicit surface is 3486b7f5c055SJed Brown 3487b7f5c055SJed 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) 3488b7f5c055SJed Brown 3489b7f5c055SJed Brown */ 3490d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3491d71ae5a4SJacob Faibussowitsch { 3492b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 3493b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 3494b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 3495b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 3496b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 3497b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 3498b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 3499b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3500b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3501b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 3502b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3503b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3504b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 3505b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3506b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3507b7f5c055SJed Brown } 3508b7f5c055SJed Brown 35094663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3510d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3511d71ae5a4SJacob Faibussowitsch { 35124663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 35134663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 35144663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 35154663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 35164663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 35173ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 35184663dae6SJed Brown } 35194663dae6SJed Brown 3520b7f5c055SJed Brown /* 3521b7f5c055SJed Brown We wish to solve 3522b7f5c055SJed Brown 3523b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 3524b7f5c055SJed Brown 3525b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 3526b7f5c055SJed 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 3527b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 3528b7f5c055SJed Brown 3529b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 3530b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 3531b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 3532b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 3533da81f932SPierre Jolivet Since Q is symmetric, this is equivalent to multiplying by Q and taking the last two entries. 3534b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 3535b7f5c055SJed Brown 3536b7f5c055SJed Brown f(y) = 0 1 equation 3537b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 3538b7f5c055SJed Brown 3539b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 3540b7f5c055SJed Brown */ 3541d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 3542d71ae5a4SJacob Faibussowitsch { 3543b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 3544b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 35452f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 35469371c9d4SSatish Balay PetscReal n_y[3][3] = { 35479371c9d4SSatish Balay {0, 0, 0}, 35489371c9d4SSatish Balay {0, 0, 0}, 35499371c9d4SSatish Balay {0, 0, 0} 35509371c9d4SSatish Balay }; 3551b7f5c055SJed Brown 3552b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 3553b7f5c055SJed Brown 3554b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 3555b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3556ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 3557b7f5c055SJed Brown 3558b7f5c055SJed Brown // Define the Householder reflector 3559b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 3560b7f5c055SJed Brown n[0] += norm * sign; 3561b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 3562b7f5c055SJed Brown 3563b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3564b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 3565b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 3566b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 3567b7f5c055SJed Brown 3568b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3569b7f5c055SJed Brown n[i] /= norm; 3570b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3571b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 3572b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 3573b7f5c055SJed Brown } 3574b7f5c055SJed Brown } 3575b7f5c055SJed Brown 3576b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 3577b7f5c055SJed 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]; 3578b7f5c055SJed Brown 3579b7f5c055SJed Brown res[0] = f; 3580b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 3581b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 3582b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 3583b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3584b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 3585b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 3586b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 3587b7f5c055SJed Brown } 3588b7f5c055SJed Brown } 3589b7f5c055SJed Brown 3590b7f5c055SJed Brown /* 3591b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 3592b7f5c055SJed Brown */ 3593d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 3594d71ae5a4SJacob Faibussowitsch { 3595b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 3596b7f5c055SJed Brown 3597b7f5c055SJed Brown PetscFunctionBegin; 3598b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 3599b7f5c055SJed Brown PetscScalar res[3], J[9]; 3600b7f5c055SJed Brown PetscReal resnorm; 3601b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 3602b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 3603b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 360463a3b9bcSJacob 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]))); 3605b7f5c055SJed Brown } 3606b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 3607b7f5c055SJed Brown 3608b7f5c055SJed Brown // Take the Newton step 36099566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 3610b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 3611b7f5c055SJed Brown } 3612b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 36133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3614b7f5c055SJed Brown } 3615b7f5c055SJed Brown 3616b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 3617b7f5c055SJed Brown 3618d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 3619d71ae5a4SJacob Faibussowitsch { 3620b7f5c055SJed Brown PetscMPIInt rank; 3621b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 3622b7f5c055SJed Brown PetscInt (*edges)[2] = NULL, *edgeSets = NULL; 3623b7f5c055SJed Brown PetscInt *cells_flat = NULL; 3624b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 3625b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 36268434afd1SBarry Smith PetscSimplePointFn *normalFunc = NULL; 3627b7f5c055SJed Brown DMLabel label; 3628b7f5c055SJed Brown 3629b7f5c055SJed Brown PetscFunctionBegin; 363046139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 36319566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 363263a3b9bcSJacob 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); 3633b7f5c055SJed Brown switch (tpstype) { 3634b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 3635b7f5c055SJed 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"); 3636c5853193SPierre Jolivet if (rank == 0) { 3637b7f5c055SJed Brown PetscInt (*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 3638b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 3639b7f5c055SJed Brown PetscReal L = 1; 3640b7f5c055SJed Brown 3641b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 3642b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 3643b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 3644b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 3645b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 3646b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 36479566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 36489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 36499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 36509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 3651b7f5c055SJed Brown // x-normal pipes 3652b7f5c055SJed Brown vcount = 0; 3653b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 3654b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3655b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3656b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3657b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 3658b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3659b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3660b7f5c055SJed Brown } 3661b7f5c055SJed Brown } 3662b7f5c055SJed Brown } 3663b7f5c055SJed Brown } 3664b7f5c055SJed Brown // y-normal pipes 3665b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3666b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 3667b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3668b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3669b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3670b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 3671b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3672b7f5c055SJed Brown } 3673b7f5c055SJed Brown } 3674b7f5c055SJed Brown } 3675b7f5c055SJed Brown } 3676b7f5c055SJed Brown // z-normal pipes 3677b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3678b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3679b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 3680b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3681b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3682b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3683b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 3684b7f5c055SJed Brown } 3685b7f5c055SJed Brown } 3686b7f5c055SJed Brown } 3687b7f5c055SJed Brown } 3688b7f5c055SJed Brown // junctions 3689b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3690b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3691b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3692b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 3693b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 3694b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 3695b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 3696b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 3697b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 3698b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 3699b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 3700b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 3701b7f5c055SJed Brown } 3702b7f5c055SJed Brown } 3703b7f5c055SJed Brown } 3704b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 3705b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 3706b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 3707b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 3708b7f5c055SJed Brown }; 3709b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 37109371c9d4SSatish 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}; 3711b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 37129371c9d4SSatish 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}; 3713b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 3714b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 3715b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 3716b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 3717b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 3718b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 3719b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 3720b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 3721b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 3722b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 3723b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 3724b7f5c055SJed Brown if (ijk[dir] == 0) { 3725b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 3726b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 3727b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 3728b7f5c055SJed Brown numEdges++; 3729b7f5c055SJed Brown } 3730b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 3731b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 3732b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 3733b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 3734b7f5c055SJed Brown numEdges++; 3735b7f5c055SJed Brown } 3736b7f5c055SJed Brown } 3737b7f5c055SJed Brown } 3738b7f5c055SJed Brown } 3739b7f5c055SJed Brown } 3740b7f5c055SJed Brown } 374163a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 3742b7f5c055SJed Brown numFaces = 24 * Njunctions; 3743b7f5c055SJed Brown cells_flat = cells[0][0][0]; 3744b7f5c055SJed Brown } 3745b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 37464663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 3747b7f5c055SJed Brown break; 3748b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 3749c5853193SPierre Jolivet if (rank == 0) { 3750b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 3751b7f5c055SJed Brown // 3752b7f5c055SJed 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) 3753b7f5c055SJed Brown // 3754b7f5c055SJed Brown // on the cell [0,2]^3. 3755b7f5c055SJed Brown // 3756b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 3757b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 3758b7f5c055SJed Brown // like a boomerang: 3759b7f5c055SJed Brown // 3760b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 3761b7f5c055SJed Brown // ----- ------- ------- ------- // 3762b7f5c055SJed Brown // // 3763b7f5c055SJed Brown // + + + + + + + \ + // 3764b7f5c055SJed Brown // \ / \ // 3765b7f5c055SJed Brown // \ `-_ _-' / } // 3766b7f5c055SJed Brown // *-_ `-' _-' / // 3767b7f5c055SJed Brown // + `-+ + + +-' + + / + // 3768b7f5c055SJed Brown // // 3769b7f5c055SJed Brown // // 3770b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 3771b7f5c055SJed Brown // ----- ------- ------- ------- // 3772b7f5c055SJed Brown // // 3773b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 3774b7f5c055SJed Brown // `-_ _-_ _-` / // 3775b7f5c055SJed Brown // \ _-' `-_ / { // 3776b7f5c055SJed Brown // \ / \ // 3777b7f5c055SJed Brown // + + + + + + + \ + // 3778b7f5c055SJed Brown // 3779b7f5c055SJed Brown // 3780b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 3781b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 3782b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 3783b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 3784b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 3785b7f5c055SJed Brown // 3786b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 3787b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 3788b7f5c055SJed Brown // 3789b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 3790b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 3791b7f5c055SJed Brown 3792b7f5c055SJed Brown PetscInt facesPerBlock = 64; 3793b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 3794b7f5c055SJed Brown PetscInt extentPlus[3]; 3795b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 37969371c9d4SSatish 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; 37979371c9d4SSatish Balay const PetscInt pattern[64][4] = { 37989371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 3799b7f5c055SJed Brown /* layer 0 */ 38009371c9d4SSatish Balay {A, C, K, G }, 38019371c9d4SSatish Balay {C, B, II, K }, 38029371c9d4SSatish Balay {D, A, H, L }, 38039371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 38049371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 38059371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 38069371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 38079371c9d4SSatish Balay {B, F, M, II }, 3808b7f5c055SJed Brown /* layer 1 */ 38099371c9d4SSatish Balay {G, K, Q, O }, 38109371c9d4SSatish Balay {K, II, P, Q }, 38119371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 38129371c9d4SSatish Balay {J, L, R, P }, 38139371c9d4SSatish Balay {N, J, P, S }, 38149371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 38159371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 38169371c9d4SSatish Balay {II, M, T, P }, 3817b7f5c055SJed Brown /* layer 2 */ 38189371c9d4SSatish Balay {O, Q, Y, U }, 38199371c9d4SSatish Balay {Q, P, W, Y }, 38209371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 38219371c9d4SSatish Balay {P, R, Ap, W }, 38229371c9d4SSatish Balay {S, P, X, Bp }, 38239371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 38249371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 38259371c9d4SSatish Balay {P, T, Z, X }, 3826b7f5c055SJed Brown /* layer 3 */ 38279371c9d4SSatish Balay {U, Y, Ep, Dp }, 38289371c9d4SSatish Balay {Y, W, Cp, Ep }, 38299371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 38309371c9d4SSatish Balay {W, Ap, Gp, Cp }, 38319371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 38329371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 38339371c9d4SSatish Balay {Z, V, Dp, Hp }, 38349371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 3835b7f5c055SJed Brown /* layer 4 */ 38369371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 38379371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 38389371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 38399371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 38409371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 38419371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 38429371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 38439371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 3844b7f5c055SJed Brown /* layer 5 */ 38459371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 38469371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 38479371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 38489371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 38499371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 38509371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 38519371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 38529371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 3853b7f5c055SJed Brown /* layer 6 */ 38549371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 38559371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 38569371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 38579371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 38589371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 38599371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 38609371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 38619371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 3862b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 38639371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 38649371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 38659371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 38669371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 38679371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 38689371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 38699371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 38709371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 3871b7f5c055SJed Brown }; 3872b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 38739371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 3874bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 3875bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 3876bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 3877bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 3878bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 3879bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 3880b7f5c055SJed Brown 3881bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 3882bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 3883bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 3884bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 3885bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 3886bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 3887bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 3888bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 3889b7f5c055SJed Brown 3890bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 3891bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 3892bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 3893bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 3894bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 3895bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 3896b7f5c055SJed Brown 3897bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 3898bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 3899bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 3900bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 3901bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 3902bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 3903bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 3904bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 3905b7f5c055SJed Brown 3906bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 3907bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 3908bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 3909bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 3910bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 3911bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 3912b7f5c055SJed Brown 3913bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 3914bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 3915bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 3916bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 3917bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 3918bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 3919bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 3920bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 3921b7f5c055SJed Brown 3922bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 3923bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 3924bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 3925bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 3926bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 3927bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 3928b7f5c055SJed Brown 3929bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 3930bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 3931bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 3932bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 3933bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 3934bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 3935bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 3936bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 3937b7f5c055SJed Brown }; 3938b7f5c055SJed Brown PetscInt (*cells)[64][4] = NULL; 3939b7f5c055SJed Brown PetscBool *seen; 3940b7f5c055SJed Brown PetscInt *vertToTrueVert; 3941b7f5c055SJed Brown PetscInt count; 3942b7f5c055SJed Brown 3943b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 3944b7f5c055SJed Brown numBlocks = 1; 3945b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 3946b7f5c055SJed Brown numBlocksPlus = 1; 3947b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 3948b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 39499566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 39509566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 3951b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3952b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3953b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3954b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 3955b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 3956b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 3957b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 3958b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 3959b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 3960b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 3961b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 3962b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 3963b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 3964b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 3965b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 3966b7f5c055SJed Brown 3967b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 3968b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 3969b7f5c055SJed Brown } 3970b7f5c055SJed Brown } 3971b7f5c055SJed Brown } 3972b7f5c055SJed Brown } 3973b7f5c055SJed Brown } 39749371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 39759371c9d4SSatish Balay if (seen[i]) numVertices++; 3976b7f5c055SJed Brown count = 0; 39779566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 39789566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 3979b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 3980b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 3981b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 3982b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 3983b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 3984b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 3985b7f5c055SJed Brown 3986b7f5c055SJed Brown if (seen[vIdx]) { 3987b7f5c055SJed Brown PetscInt thisVert; 3988b7f5c055SJed Brown 3989b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 3990b7f5c055SJed Brown 3991b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 3992b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 3993b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 3994b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 3995b7f5c055SJed Brown } 3996b7f5c055SJed Brown } 3997b7f5c055SJed Brown } 3998b7f5c055SJed Brown } 3999b7f5c055SJed Brown } 4000b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 4001b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 4002ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 4003b7f5c055SJed Brown } 4004b7f5c055SJed Brown } 40059566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 40069566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 4007b7f5c055SJed Brown cells_flat = cells[0][0]; 4008b7f5c055SJed Brown numEdges = 0; 4009b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 4010b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 4011b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 4012b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 4013b7f5c055SJed Brown 4014b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 4015b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 4016b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 4017b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 4018b7f5c055SJed Brown } 4019b7f5c055SJed Brown } 4020b7f5c055SJed Brown } 4021b7f5c055SJed Brown } 40229566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 40239566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 4024b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 4025b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 4026b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 4027b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 4028b7f5c055SJed Brown 4029b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 4030b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 4031b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 4032b7f5c055SJed Brown edges[edge][0] = ev[0]; 4033b7f5c055SJed Brown edges[edge][1] = ev[1]; 4034b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 4035b7f5c055SJed Brown } 4036b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 4037b7f5c055SJed Brown edges[edge][0] = ev[0]; 4038b7f5c055SJed Brown edges[edge][1] = ev[1]; 4039b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 4040b7f5c055SJed Brown } 4041b7f5c055SJed Brown } 4042b7f5c055SJed Brown } 4043b7f5c055SJed Brown } 4044b7f5c055SJed Brown } 4045b7f5c055SJed Brown } 4046b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 40474663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 4048b7f5c055SJed Brown break; 4049b7f5c055SJed Brown } 4050b7f5c055SJed Brown 40519566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 4052c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 40539566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 40549566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 4055b7f5c055SJed Brown { 4056b7f5c055SJed Brown DM idm; 40579566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 405869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 4059b7f5c055SJed Brown } 4060c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 40619566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 40629566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 4063b7f5c055SJed Brown 40649566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 40659566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 4066b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 4067b7f5c055SJed Brown PetscInt njoin; 4068b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 40699566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 407063a3b9bcSJacob 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]); 40719566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 40729566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 4073b7f5c055SJed Brown } 40749566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 40759566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 40761436d7faSJed Brown if (tps_distribute) { 40771436d7faSJed Brown DM pdm = NULL; 40781436d7faSJed Brown PetscPartitioner part; 40791436d7faSJed Brown 40809566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 40819566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 40829566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 408348a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 40841436d7faSJed Brown // Do not auto-distribute again 40859566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 40861436d7faSJed Brown } 4087b7f5c055SJed Brown 40889566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 4089b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 4090b7f5c055SJed Brown PetscInt m; 4091b7f5c055SJed Brown DM dmf; 4092b7f5c055SJed Brown Vec X; 4093b7f5c055SJed Brown PetscScalar *x; 40949566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 409569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 4096b7f5c055SJed Brown 40979566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 40989566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 40999566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 410048a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 41019566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 4102b7f5c055SJed Brown } 4103b7f5c055SJed Brown 4104b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 41059566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 41069566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 4107b7f5c055SJed Brown 410846139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 410946139095SJed Brown 4110b7f5c055SJed Brown if (thickness > 0) { 41114663dae6SJed Brown DM edm, cdm, ecdm; 41124663dae6SJed Brown DMPlexTransform tr; 41134663dae6SJed Brown const char *prefix; 41144663dae6SJed Brown PetscOptions options; 41154663dae6SJed Brown // Code from DMPlexExtrude 41164663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 41174663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 4118ce78bad3SBarry Smith PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDETYPE)); 41194663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 41204663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 41214663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 41224663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 41234663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 41244663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 41254663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 41264663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 41274663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 41284663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 41294663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 41304663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 41314663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 41324663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 41334663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 41344663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 41354663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 41364663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 41374663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 41384663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 4139a77a5016SMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, edm)); 414069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 4141b7f5c055SJed Brown } 41423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4143b7f5c055SJed Brown } 4144b7f5c055SJed Brown 4145b7f5c055SJed Brown /*@ 4146b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 4147b7f5c055SJed Brown 4148b7f5c055SJed Brown Collective 4149b7f5c055SJed Brown 4150b7f5c055SJed Brown Input Parameters: 4151a1cb98faSBarry Smith + comm - The communicator for the `DM` object 4152b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 4153b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 415420f4b53cSBarry Smith . periodic - array of length 3 with periodicity, or `NULL` for non-periodic 41551436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 4156817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 41571436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 4158817da375SSatish Balay - thickness - Thickness in normal direction 4159b7f5c055SJed Brown 4160b7f5c055SJed Brown Output Parameter: 4161a1cb98faSBarry Smith . dm - The `DM` object 4162a1cb98faSBarry Smith 4163a1cb98faSBarry Smith Level: beginner 4164b7f5c055SJed Brown 4165b7f5c055SJed Brown Notes: 416615229ffcSPierre Jolivet This meshes the surface of the Schwarz P or Gyroid surfaces. Schwarz P is the simplest member of the triply-periodic minimal surfaces. 41671d27aa22SBarry Smith <https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22)> and can be cut with "clean" boundaries. 41681d27aa22SBarry 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. 4169b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 4170b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 4171b7f5c055SJed Brown This projection could readily be extended to related surfaces. 4172b7f5c055SJed Brown 41731d27aa22SBarry Smith See {cite}`maskery2018insights` 41741d27aa22SBarry Smith 41751d27aa22SBarry Smith The face (edge) sets for the Schwarz P surface are numbered $1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z)$. 41761d27aa22SBarry Smith When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). 41771d27aa22SBarry Smith Use `DMPlexLabelComplete()` to propagate to coarse-level vertices. 4178b7f5c055SJed Brown 417960225df5SJacob Faibussowitsch Developer Notes: 4180b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 4181b7f5c055SJed Brown 41821cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 4183b7f5c055SJed Brown @*/ 4184d71ae5a4SJacob 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) 4185d71ae5a4SJacob Faibussowitsch { 4186b7f5c055SJed Brown PetscFunctionBegin; 41879566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 41889566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 41899566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 41903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4191b7f5c055SJed Brown } 4192b7f5c055SJed Brown 41939318fe57SMatthew G. Knepley /*@ 41949318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 41959318fe57SMatthew G. Knepley 41969318fe57SMatthew G. Knepley Collective 41979318fe57SMatthew G. Knepley 41989318fe57SMatthew G. Knepley Input Parameters: 4199a1cb98faSBarry Smith + comm - The communicator for the `DM` object 42009318fe57SMatthew G. Knepley . dim - The dimension 42019318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 42029318fe57SMatthew G. Knepley - R - The radius 42039318fe57SMatthew G. Knepley 42049318fe57SMatthew G. Knepley Output Parameter: 4205a1cb98faSBarry Smith . dm - The `DM` object 42069318fe57SMatthew G. Knepley 42079318fe57SMatthew G. Knepley Level: beginner 42089318fe57SMatthew G. Knepley 42091cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 42109318fe57SMatthew G. Knepley @*/ 4211d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 4212d71ae5a4SJacob Faibussowitsch { 42139318fe57SMatthew G. Knepley PetscFunctionBegin; 42144f572ea9SToby Isaac PetscAssertPointer(dm, 5); 42159566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 42169566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 42179566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 42183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42199318fe57SMatthew G. Knepley } 42209318fe57SMatthew G. Knepley 4221d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 4222d71ae5a4SJacob Faibussowitsch { 42239318fe57SMatthew G. Knepley DM sdm, vol; 42249318fe57SMatthew G. Knepley DMLabel bdlabel; 4225dd2b43ebSStefano Zampini const char *prefix; 42269318fe57SMatthew G. Knepley 42279318fe57SMatthew G. Knepley PetscFunctionBegin; 42289566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 42299566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 4230dd2b43ebSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 4231dd2b43ebSStefano Zampini PetscCall(DMSetOptionsPrefix(sdm, prefix)); 4232dd2b43ebSStefano Zampini PetscCall(DMAppendOptionsPrefix(sdm, "bd_")); 4233dd2b43ebSStefano Zampini PetscCall(DMPlexDistributeSetDefault(sdm, PETSC_FALSE)); 42349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 42359566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 42369566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 42379566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 42389566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 423969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 42409566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 42419566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 42429566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 42439566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 42443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 424551a74b61SMatthew G. Knepley } 424651a74b61SMatthew G. Knepley 424751a74b61SMatthew G. Knepley /*@ 424851a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 424951a74b61SMatthew G. Knepley 425051a74b61SMatthew G. Knepley Collective 425151a74b61SMatthew G. Knepley 425251a74b61SMatthew G. Knepley Input Parameters: 4253a1cb98faSBarry Smith + comm - The communicator for the `DM` object 425451a74b61SMatthew G. Knepley . dim - The dimension 425551a74b61SMatthew G. Knepley - R - The radius 425651a74b61SMatthew G. Knepley 425751a74b61SMatthew G. Knepley Output Parameter: 4258a1cb98faSBarry Smith . dm - The `DM` object 425951a74b61SMatthew G. Knepley 4260a1cb98faSBarry Smith Options Database Key: 426160225df5SJacob Faibussowitsch . bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 426251a74b61SMatthew G. Knepley 426351a74b61SMatthew G. Knepley Level: beginner 426451a74b61SMatthew G. Knepley 42651cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 426651a74b61SMatthew G. Knepley @*/ 4267d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 4268d71ae5a4SJacob Faibussowitsch { 426951a74b61SMatthew G. Knepley PetscFunctionBegin; 42709566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 42719566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 42729566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 42733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 42742829fed8SMatthew G. Knepley } 42752829fed8SMatthew G. Knepley 4276d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 4277d71ae5a4SJacob Faibussowitsch { 42780a6ba040SMatthew G. Knepley PetscFunctionBegin; 42799318fe57SMatthew G. Knepley switch (ct) { 42809371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 42819318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 42829318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 42839318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 42849318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 42859318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 42869318fe57SMatthew G. Knepley 42879566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 42889566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 42899371c9d4SSatish Balay } break; 42909371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 42919318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 42929318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 42939318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 42949318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 42959318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 42969318fe57SMatthew G. Knepley 42979566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 42989566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 42999371c9d4SSatish Balay } break; 43009371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 4301b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 4302b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 4303b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 4304b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 4305b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 4306b5a892a1SMatthew G. Knepley 43079566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 43089566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 43099371c9d4SSatish Balay } break; 43109371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 43119318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 43129318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 43139318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 43149318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 43159318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 43169318fe57SMatthew G. Knepley 43179566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 43189566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 43199371c9d4SSatish Balay } break; 43209371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 43219318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 43229318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 43239318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 43249318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 43259318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 43269318fe57SMatthew G. Knepley 43279566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 43289566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 43299371c9d4SSatish Balay } break; 43309371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 43319318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 43329318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 43339318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 43349318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 43359318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 43369318fe57SMatthew G. Knepley 43379566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 43389566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 43399371c9d4SSatish Balay } break; 43409371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 43419318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 43429318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 4343f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 43449318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 4345f0edb160SMatthew 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}; 43469318fe57SMatthew G. Knepley 43479566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 43489566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 43499371c9d4SSatish Balay } break; 43509371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 43519318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 43529318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 4353f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 43549318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 43559371c9d4SSatish 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}; 43569318fe57SMatthew G. Knepley 43579566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 43589566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 43599371c9d4SSatish Balay } break; 43609371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 43619318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 43629318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 4363f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 43649318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 43659371c9d4SSatish 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}; 43669318fe57SMatthew G. Knepley 43679566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 43689566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 43699371c9d4SSatish Balay } break; 43709371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 43719318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 43729318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 43739318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 43749318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 43759371c9d4SSatish 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}; 43769318fe57SMatthew G. Knepley 43779566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 43789566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 43799371c9d4SSatish Balay } break; 43809371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 43819318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 43829318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 43839318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 43849318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 43859371c9d4SSatish 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}; 43869318fe57SMatthew G. Knepley 43879566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 43889566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 43899371c9d4SSatish Balay } break; 43909371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 43919318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 43929318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 4393f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 43949318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 43959371c9d4SSatish 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}; 43969318fe57SMatthew G. Knepley 43979566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 43989566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 43999371c9d4SSatish Balay } break; 4400d71ae5a4SJacob Faibussowitsch default: 4401d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 44029318fe57SMatthew G. Knepley } 44039318fe57SMatthew G. Knepley { 44049318fe57SMatthew G. Knepley PetscInt Nv, v; 44059318fe57SMatthew G. Knepley 44069318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 44079566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 44089566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 44099566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 44109566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 44119318fe57SMatthew G. Knepley } 44129566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 44139566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 44143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44150a6ba040SMatthew G. Knepley } 44160a6ba040SMatthew G. Knepley 44179318fe57SMatthew G. Knepley /*@ 4418a1cb98faSBarry Smith DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell 44199318fe57SMatthew G. Knepley 44209318fe57SMatthew G. Knepley Collective 44219318fe57SMatthew G. Knepley 44229318fe57SMatthew G. Knepley Input Parameters: 44239318fe57SMatthew G. Knepley + comm - The communicator 44249318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 44259318fe57SMatthew G. Knepley 44269318fe57SMatthew G. Knepley Output Parameter: 44279318fe57SMatthew G. Knepley . refdm - The reference cell 44289318fe57SMatthew G. Knepley 44299318fe57SMatthew G. Knepley Level: intermediate 44309318fe57SMatthew G. Knepley 443142747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()` 44329318fe57SMatthew G. Knepley @*/ 4433d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 4434d71ae5a4SJacob Faibussowitsch { 44350a6ba040SMatthew G. Knepley PetscFunctionBegin; 44369566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 44379566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 44389566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 44393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44409318fe57SMatthew G. Knepley } 444179a015ccSMatthew G. Knepley 4442d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 4443d71ae5a4SJacob Faibussowitsch { 44449318fe57SMatthew G. Knepley DM plex; 44459318fe57SMatthew G. Knepley DMLabel label; 44469318fe57SMatthew G. Knepley PetscBool hasLabel; 44470a6ba040SMatthew G. Knepley 4448c22d3578SMatthew G. Knepley PetscFunctionBegin; 44499566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 44503ba16761SJacob Faibussowitsch if (hasLabel) PetscFunctionReturn(PETSC_SUCCESS); 44519566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 44529566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 44539566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 44549566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 44551c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 44569566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 44573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44589318fe57SMatthew G. Knepley } 4459acdc6f61SToby Isaac 4460669647acSMatthew G. Knepley /* 4461669647acSMatthew 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. 4462669647acSMatthew G. Knepley 4463669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 4464669647acSMatthew G. Knepley */ 4465d71ae5a4SJacob 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[]) 4466d71ae5a4SJacob Faibussowitsch { 4467669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 4468669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 4469669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 4470669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 4471669647acSMatthew G. Knepley 4472669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 4473669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 4474669647acSMatthew G. Knepley } 4475669647acSMatthew G. Knepley 44765390be7dSMatthew G. Knepley // Insert vertices and their joins, marked by depth 44775390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Vertices(DM dm, DMLabel label, DMLabel vlabel, PetscInt val, PetscInt n, const PetscInt vertices[]) 44785390be7dSMatthew G. Knepley { 44795390be7dSMatthew G. Knepley PetscFunctionBegin; 44805390be7dSMatthew G. Knepley PetscCall(DMPlexMarkSubmesh_Interpolated(dm, vlabel, val, PETSC_FALSE, PETSC_FALSE, label, NULL)); 44815390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 44825390be7dSMatthew G. Knepley } 44835390be7dSMatthew G. Knepley 44845390be7dSMatthew G. Knepley // Insert faces and their closures, marked by depth 44855390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Faces(DM dm, DMLabel label, PetscInt n, const PetscInt faces[]) 44865390be7dSMatthew G. Knepley { 44875390be7dSMatthew G. Knepley PetscFunctionBegin; 44885390be7dSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) { 44895390be7dSMatthew G. Knepley const PetscInt point = faces[p]; 44905390be7dSMatthew G. Knepley PetscInt *closure = NULL; 44915390be7dSMatthew G. Knepley PetscInt clSize, pdepth; 44925390be7dSMatthew G. Knepley 44935390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, point, &pdepth)); 44945390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, point, pdepth)); 44955390be7dSMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 44965390be7dSMatthew G. Knepley for (PetscInt cl = 0; cl < clSize * 2; cl += 2) { 44975390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, closure[cl], &pdepth)); 44985390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, closure[cl], pdepth)); 44995390be7dSMatthew G. Knepley } 45005390be7dSMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 45015390be7dSMatthew G. Knepley } 45025390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 45035390be7dSMatthew G. Knepley } 45045390be7dSMatthew G. Knepley 45054e22dd4cSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *flg); 45064e22dd4cSMatthew G. Knepley 45075dca41c3SJed Brown const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "zbox", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 45089318fe57SMatthew G. Knepley 4509ce78bad3SBarry Smith static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 4510d71ae5a4SJacob Faibussowitsch { 45119318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 45129318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 45139318fe57SMatthew G. Knepley PetscInt dim = 2; 4514b9da1bb3SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, orient = PETSC_FALSE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 4515d0812dedSMatthew G. Knepley PetscBool flg, flg2, fflg, strflg, bdfflg, nameflg; 45169318fe57SMatthew G. Knepley MPI_Comm comm; 4517ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4518ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4519ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 45204e22dd4cSMatthew G. Knepley const char *option; 45219318fe57SMatthew G. Knepley 45229318fe57SMatthew G. Knepley PetscFunctionBegin; 4523708be2fdSJed Brown PetscCall(PetscLogEventBegin(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 45249566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 45259318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 45269566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 4527d0812dedSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_file_contents", "Contents of a file format in a string", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &strflg)); 45289566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 45299566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 45309566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 45319566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 45329566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 45339566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 45349566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 45359566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 4536b9da1bb3SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_orient", "Orient the constructed mesh", "DMPlexOrient", orient, &orient, &flg)); 45379566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 45389566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 45399566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 45403f3e541fSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_adj", "Debug output level all adjacency computations", "", 0, &((DM_Plex *)dm->data)->printAdj, NULL, 0)); 45419318fe57SMatthew G. Knepley 454261a622f3SMatthew G. Knepley switch (cell) { 454361a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 454461a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 454561a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 454661a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 454761a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 454861a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 4549d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 4550d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_TRUE; 4551d71ae5a4SJacob Faibussowitsch break; 4552d71ae5a4SJacob Faibussowitsch default: 4553d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_FALSE; 4554d71ae5a4SJacob Faibussowitsch break; 455561a622f3SMatthew G. Knepley } 455661a622f3SMatthew G. Knepley 45579318fe57SMatthew G. Knepley if (fflg) { 45589318fe57SMatthew G. Knepley DM dmnew; 45591e4a82c4SMatthew G. Knepley const char *name; 45609318fe57SMatthew G. Knepley 45611e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 45621e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, nameflg ? plexname : name, interpolate, &dmnew)); 45635de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 456469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 45659318fe57SMatthew G. Knepley } else if (refDomain) { 45669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 45679318fe57SMatthew G. Knepley } else if (bdfflg) { 45689318fe57SMatthew G. Knepley DM bdm, dmnew; 45691e4a82c4SMatthew G. Knepley const char *name; 45709318fe57SMatthew G. Knepley 45711e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 45721e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, nameflg ? plexname : name, interpolate, &bdm)); 45739566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 45749566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 45759566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 45769566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 45775de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 457869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 4579d0812dedSMatthew G. Knepley } else if (strflg) { 4580d0812dedSMatthew G. Knepley DM dmnew; 4581d0812dedSMatthew G. Knepley PetscViewer viewer; 4582d0812dedSMatthew G. Knepley const char *contents; 4583d0812dedSMatthew G. Knepley char *strname; 4584d0812dedSMatthew G. Knepley char tmpdir[PETSC_MAX_PATH_LEN]; 4585d0812dedSMatthew G. Knepley char tmpfilename[PETSC_MAX_PATH_LEN]; 4586d0812dedSMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 4587d0812dedSMatthew G. Knepley MPI_Comm comm; 4588d0812dedSMatthew G. Knepley PetscMPIInt rank; 4589d0812dedSMatthew G. Knepley 4590d0812dedSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4591d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 4592d0812dedSMatthew G. Knepley PetscCall(PetscStrchr(filename, ':', &strname)); 4593d0812dedSMatthew G. Knepley PetscCheck(strname, comm, PETSC_ERR_ARG_WRONG, "File contents must have the form \"ext:string_name\", not %s", filename); 4594d0812dedSMatthew G. Knepley strname[0] = '\0'; 4595d0812dedSMatthew G. Knepley ++strname; 4596d0812dedSMatthew G. Knepley PetscCall(PetscDLSym(NULL, strname, (void **)&contents)); 4597d0812dedSMatthew G. Knepley PetscCheck(contents, comm, PETSC_ERR_ARG_WRONG, "Could not locate mesh string %s", strname); 4598d0812dedSMatthew G. Knepley PetscCall(PetscGetTmp(comm, tmpdir, PETSC_MAX_PATH_LEN)); 4599ed32af8cSMatthew G. Knepley PetscCall(PetscStrlcat(tmpdir, "/meshXXXXXX", PETSC_MAX_PATH_LEN)); 4600ed32af8cSMatthew G. Knepley PetscCall(PetscMkdtemp(tmpdir)); 4601ed32af8cSMatthew G. Knepley PetscCall(PetscSNPrintf(tmpfilename, PETSC_MAX_PATH_LEN, "%s/mesh.%s", tmpdir, filename)); 4602d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIOpen(comm, tmpfilename, &viewer)); 4603d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", contents)); 4604d0812dedSMatthew G. Knepley PetscCall(PetscViewerDestroy(&viewer)); 4605d0812dedSMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), tmpfilename, plexname, interpolate, &dmnew)); 4606ed32af8cSMatthew G. Knepley PetscCall(PetscRMTree(tmpdir)); 4607d0812dedSMatthew G. Knepley PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%s Mesh", strname)); 4608d0812dedSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, name)); 4609d0812dedSMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 4610d0812dedSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 46119318fe57SMatthew G. Knepley } else { 46129566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 46139318fe57SMatthew G. Knepley switch (shape) { 4614669647acSMatthew G. Knepley case DM_SHAPE_BOX: 46155dca41c3SJed Brown case DM_SHAPE_ZBOX: 4616669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 46179318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 46189318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 46199318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 46209318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4621669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 46229318fe57SMatthew G. Knepley PetscInt i, n; 46239318fe57SMatthew G. Knepley 46249318fe57SMatthew G. Knepley n = dim; 46259318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 46269566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 46279318fe57SMatthew G. Knepley n = 3; 46289566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 462963a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 46309318fe57SMatthew G. Knepley n = 3; 46319566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 463263a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 46339318fe57SMatthew G. Knepley n = 3; 46349566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 463563a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 4636669647acSMatthew G. Knepley 4637669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 4638669647acSMatthew G. Knepley if (isAnnular) 4639669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 4640669647acSMatthew G. Knepley 46419318fe57SMatthew G. Knepley switch (cell) { 464261a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 46439566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 4644d410b0cfSMatthew G. Knepley if (!interpolate) { 4645d410b0cfSMatthew G. Knepley DM udm; 4646d410b0cfSMatthew G. Knepley 46479566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 464869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 4649d410b0cfSMatthew G. Knepley } 46509318fe57SMatthew G. Knepley break; 4651d71ae5a4SJacob Faibussowitsch default: 46525dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(dm, shape, dim, simplex, faces, lower, upper, bdt, interpolate)); 4653d71ae5a4SJacob Faibussowitsch break; 46549318fe57SMatthew G. Knepley } 4655669647acSMatthew G. Knepley if (isAnnular) { 4656669647acSMatthew G. Knepley DM cdm; 4657669647acSMatthew G. Knepley PetscDS cds; 4658669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 4659669647acSMatthew G. Knepley 4660669647acSMatthew G. Knepley // Fix coordinates for annular region 4661669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 4662669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 4663669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 4664e44f6aebSMatthew G. Knepley PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_TRUE, NULL)); 4665669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 4666669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 4667669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 4668669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 4669669647acSMatthew G. Knepley } 46709371c9d4SSatish Balay } break; 46719371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 46729318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 46739318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 46749318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 46759318fe57SMatthew G. Knepley PetscInt i, n; 46769318fe57SMatthew G. Knepley 46779318fe57SMatthew G. Knepley n = dim + 1; 46789318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 46799566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 46809318fe57SMatthew G. Knepley n = 3; 46819566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 468263a3b9bcSJacob 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); 46839318fe57SMatthew G. Knepley n = 3; 46849566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 468563a3b9bcSJacob 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); 46869566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 46879371c9d4SSatish Balay } break; 46889371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 46899318fe57SMatthew G. Knepley PetscReal R = 1.0; 46909318fe57SMatthew G. Knepley 46919566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 46929566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 46939371c9d4SSatish Balay } break; 46949371c9d4SSatish Balay case DM_SHAPE_BALL: { 46959318fe57SMatthew G. Knepley PetscReal R = 1.0; 46969318fe57SMatthew G. Knepley 46979566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 46989566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 46999371c9d4SSatish Balay } break; 47009371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 47019318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 47029318fe57SMatthew G. Knepley PetscInt Nw = 6; 470349704ca5SMatthew G. Knepley PetscInt Nr = 0; 47049318fe57SMatthew G. Knepley 47059566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 47069566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 470749704ca5SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_refine", "Number of refinements before projection", "", Nr, &Nr, NULL)); 47089318fe57SMatthew G. Knepley switch (cell) { 4709d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_TRI_PRISM_TENSOR: 4710d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 4711d71ae5a4SJacob Faibussowitsch break; 4712d71ae5a4SJacob Faibussowitsch default: 471349704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt, Nr)); 4714d71ae5a4SJacob Faibussowitsch break; 47159318fe57SMatthew G. Knepley } 47169371c9d4SSatish Balay } break; 4717b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 47189371c9d4SSatish Balay case DM_SHAPE_GYROID: { 4719b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 4720b7f5c055SJed Brown PetscReal thickness = 0.; 4721b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4722b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 47231436d7faSJed Brown PetscBool tps_distribute; 47249566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 47259566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 47269566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 47279566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 47289566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 47299566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 47309566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 47319566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 47329371c9d4SSatish Balay } break; 47339371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 473405bd46c0SStefano Zampini DM dmnew; 473505bd46c0SStefano Zampini PetscReal rl = 0.0; 473605bd46c0SStefano Zampini 473705bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 473805bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 47395de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 474069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 47419371c9d4SSatish Balay } break; 4742cfb853baSMatthew G. Knepley case DM_SHAPE_HYPERCUBIC: { 47438d2ec52aSSatish Balay PetscInt *edges, overlap = 1; 4744cfb853baSMatthew G. Knepley PetscReal *lower, *upper; 4745cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 4746cfb853baSMatthew G. Knepley PetscInt n, d; 4747cfb853baSMatthew G. Knepley 4748cfb853baSMatthew G. Knepley *useCoordSpace = PETSC_FALSE; 4749cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt)); 4750cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 4751cfb853baSMatthew G. Knepley edges[d] = 1; 4752cfb853baSMatthew G. Knepley lower[d] = 0.; 4753cfb853baSMatthew G. Knepley upper[d] = 1.; 4754cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 4755cfb853baSMatthew G. Knepley } 4756cfb853baSMatthew G. Knepley n = dim; 4757cfb853baSMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg)); 4758cfb853baSMatthew G. Knepley n = dim; 4759cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 4760cfb853baSMatthew 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); 4761cfb853baSMatthew G. Knepley n = dim; 4762cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 4763cfb853baSMatthew 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); 4764cfb853baSMatthew G. Knepley n = dim; 4765cfb853baSMatthew G. Knepley PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 4766cfb853baSMatthew 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); 47678d2ec52aSSatish Balay PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", overlap, &overlap, NULL, 0)); 47688d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, overlap, bdt)); 4769cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edges, lower, upper, bdt)); 4770cfb853baSMatthew G. Knepley } break; 4771d71ae5a4SJacob Faibussowitsch default: 4772d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 47739318fe57SMatthew G. Knepley } 47749318fe57SMatthew G. Knepley } 47759566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 477648a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 4777b9da1bb3SMatthew G. Knepley if (orient) PetscCall(DMPlexOrient(dm)); 47784e22dd4cSMatthew G. Knepley // Allow label creation 47794e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_label_", &option, NULL, &flg)); 47804e22dd4cSMatthew G. Knepley if (flg) { 47814e22dd4cSMatthew G. Knepley DMLabel label; 47824e22dd4cSMatthew G. Knepley PetscInt points[1024], n = 1024; 47834e22dd4cSMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 47844e22dd4cSMatthew G. Knepley const char *name = &option[14]; 47854e22dd4cSMatthew G. Knepley 47864e22dd4cSMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 47874e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 47884e22dd4cSMatthew G. Knepley fulloption[0] = '-'; 47894e22dd4cSMatthew G. Knepley fulloption[1] = 0; 47904e22dd4cSMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, option, PETSC_MAX_PATH_LEN)); 47914e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, NULL)); 47924e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) PetscCall(DMLabelSetValue(label, points[p], 1)); 47934e22dd4cSMatthew G. Knepley } 4794dd0eeac9SMatthew G. Knepley // Allow cohesive label creation 4795dd0eeac9SMatthew G. Knepley // Faces are input, completed, and all points are marked with their depth 4796dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_cohesive_label_", &option, NULL, &flg)); 4797dd0eeac9SMatthew G. Knepley if (flg) { 4798dd0eeac9SMatthew G. Knepley DMLabel label; 4799dd0eeac9SMatthew G. Knepley PetscInt points[1024], n, pStart, pEnd, Nl = 1; 48005390be7dSMatthew G. Knepley PetscBool noCreate = PETSC_FALSE; 4801dd0eeac9SMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 4802dd0eeac9SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 4803dd0eeac9SMatthew G. Knepley size_t len; 4804dd0eeac9SMatthew G. Knepley 4805dd0eeac9SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 4806dd0eeac9SMatthew G. Knepley PetscCall(PetscStrncpy(name, &option[23], PETSC_MAX_PATH_LEN)); 4807dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlen(name, &len)); 4808dd0eeac9SMatthew G. Knepley if (name[len - 1] == '0') Nl = 10; 4809dd0eeac9SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 48106497c311SBarry Smith if (l > 0) name[len - 1] = (char)('0' + l); 4811dd0eeac9SMatthew G. Knepley fulloption[0] = 0; 4812dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, "-dm_plex_cohesive_label_", 32)); 4813dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, name, PETSC_MAX_PATH_LEN - 32)); 4814dd0eeac9SMatthew G. Knepley n = 1024; 4815dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, &flg)); 4816dd0eeac9SMatthew G. Knepley if (!flg) break; 48175390be7dSMatthew G. Knepley PetscCall(DMHasLabel(dm, name, &noCreate)); 48185390be7dSMatthew G. Knepley if (noCreate) { 48195390be7dSMatthew G. Knepley DMLabel inlabel; 48205390be7dSMatthew G. Knepley IS pointIS; 48215390be7dSMatthew G. Knepley const PetscInt *lpoints; 48225390be7dSMatthew G. Knepley PetscInt pdep, ln, inval = points[0]; 48235390be7dSMatthew G. Knepley char newname[PETSC_MAX_PATH_LEN]; 48245390be7dSMatthew G. Knepley 48255390be7dSMatthew G. Knepley PetscCheck(n == 1, comm, PETSC_ERR_ARG_WRONG, "Must specify a label value with this option"); 48265390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &inlabel)); 48275390be7dSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(inlabel, inval, &pointIS)); 48285390be7dSMatthew G. Knepley PetscCall(ISGetLocalSize(pointIS, &ln)); 48295390be7dSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &lpoints)); 48305390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, lpoints[0], &pdep)); 48315390be7dSMatthew G. Knepley PetscCall(PetscSNPrintf(newname, PETSC_MAX_PATH_LEN, "%s%" PetscInt_FMT, name, points[0])); 48325390be7dSMatthew G. Knepley PetscCall(DMCreateLabel(dm, newname)); 48335390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, newname, &label)); 48345390be7dSMatthew G. Knepley if (!pdep) PetscCall(ProcessCohesiveLabel_Vertices(dm, label, inlabel, inval, ln, lpoints)); 48355390be7dSMatthew G. Knepley else PetscCall(ProcessCohesiveLabel_Faces(dm, label, ln, lpoints)); 48365390be7dSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &lpoints)); 48375390be7dSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 48385390be7dSMatthew G. Knepley } else { 4839dd0eeac9SMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 4840dd0eeac9SMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 4841dd0eeac9SMatthew G. Knepley if (pStart >= pEnd) n = 0; 48425390be7dSMatthew G. Knepley PetscCall(ProcessCohesiveLabel_Faces(dm, label, n, points)); 4843dd0eeac9SMatthew G. Knepley } 4844dd0eeac9SMatthew G. Knepley PetscCall(DMPlexOrientLabel(dm, label)); 48450542aa8cSMatthew G. Knepley PetscCall(DMPlexLabelCohesiveComplete(dm, label, NULL, 1, PETSC_FALSE, PETSC_FALSE, NULL)); 4846dd0eeac9SMatthew G. Knepley } 4847dd0eeac9SMatthew G. Knepley } 48485390be7dSMatthew G. Knepley PetscCall(DMViewFromOptions(dm, NULL, "-created_dm_view")); 4849708be2fdSJed Brown PetscCall(PetscLogEventEnd(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 48503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 48510a6ba040SMatthew G. Knepley } 48520a6ba040SMatthew G. Knepley 4853ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems PetscOptionsObject) 4854d71ae5a4SJacob Faibussowitsch { 48550a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 48567f9d8d6cSVaclav Hapla PetscBool flg, flg2; 48579318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 4858adc21957SMatthew G. Knepley char method[PETSC_MAX_PATH_LEN]; 48590a6ba040SMatthew G. Knepley 48600a6ba040SMatthew G. Knepley PetscFunctionBegin; 48610a6ba040SMatthew G. Knepley /* Handle viewing */ 48629566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 48635962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level for all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 48645962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fvm", "Debug output level for all fvm computations", "DMPlexSNESComputeResidualFVM", 0, &mesh->printFVM, NULL, 0)); 48659566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 48669566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 4867f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 4868a77a5016SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_project", "Debug output level all projection computations", "DMPlexProject", 0, &mesh->printProject, NULL, 0)); 48699566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 48709566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 48715e2c5519SMatthew G. Knepley // Interpolation 48725e2c5519SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_interpolate_prefer_tensor", "When different orderings exist, prefer the tensor order", "DMPlexSetInterpolationPreferTensor", mesh->interpolatePreferTensor, &mesh->interpolatePreferTensor, NULL)); 48739318fe57SMatthew G. Knepley /* Labeling */ 48749566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 48759566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 4876953fc75cSMatthew G. Knepley /* Point Location */ 48779566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 48780848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 48799566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 4880d02c7345SMatthew G. Knepley /* Reordering */ 4881adc21957SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_reorder_section", "Compute point permutation for local section", "DMReorderSectionSetDefault", PETSC_FALSE, &flg2, &flg)); 4882adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetDefault(dm, flg2 ? DM_REORDER_DEFAULT_TRUE : DM_REORDER_DEFAULT_FALSE)); 4883adc21957SMatthew G. Knepley PetscCall(PetscOptionsString("-dm_reorder_section_type", "Reordering method for local section", "DMReorderSectionSetType", method, method, PETSC_MAX_PATH_LEN, &flg)); 4884adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetType(dm, method)); 48852e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 48869566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 4887b29cfa1cSToby Isaac /* Projection behavior */ 4888d5b43468SJose E. Roman PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 48899566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 4890f12cf164SMatthew G. Knepley /* Checking structure */ 4891f12cf164SMatthew G. Knepley { 48927f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 4893f12cf164SMatthew G. Knepley 48947f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 48957f9d8d6cSVaclav Hapla if (all) { 48967f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 48977f9d8d6cSVaclav Hapla } else { 48989566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 48997f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 49009566063dSJacob 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)); 49017f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 49029566063dSJacob 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)); 49037f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 49049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 49057f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 49069566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 4907d7d32a9aSMatthew G. Knepley if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 49089566063dSJacob 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)); 49097f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 49107f9d8d6cSVaclav Hapla } 49119566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 49129566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 4913f12cf164SMatthew G. Knepley } 49149318fe57SMatthew G. Knepley { 49159318fe57SMatthew G. Knepley PetscReal scale = 1.0; 49164f3833eaSMatthew G. Knepley 49179566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 49189318fe57SMatthew G. Knepley if (flg) { 49199318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 49209318fe57SMatthew G. Knepley 49219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 49229566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 49239566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 49249566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 49259318fe57SMatthew G. Knepley } 49269318fe57SMatthew G. Knepley } 49279566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 49283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 492968d4fef7SMatthew G. Knepley } 493068d4fef7SMatthew G. Knepley 4931ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems PetscOptionsObject, PetscInt *overlap) 4932d71ae5a4SJacob Faibussowitsch { 4933c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 4934c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 4935c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 4936c506a872SMatthew G. Knepley PetscBool flg; 4937c506a872SMatthew G. Knepley 4938c506a872SMatthew G. Knepley PetscFunctionBegin; 4939c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 4940c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 4941c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 4942c506a872SMatthew G. Knepley if (numOvLabels) { 4943c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 4944c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 4945c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 4946c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 4947c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 4948c506a872SMatthew G. Knepley } 4949c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 4950c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 4951c506a872SMatthew 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); 4952c506a872SMatthew G. Knepley 4953c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 4954c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 4955c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 4956c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 4957c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 4958c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 4959c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 4960c506a872SMatthew G. Knepley } 4961c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 4962c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 4963c506a872SMatthew 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); 4964c506a872SMatthew G. Knepley } 49653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4966c506a872SMatthew G. Knepley } 4967c506a872SMatthew G. Knepley 4968ce78bad3SBarry Smith static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems PetscOptionsObject) 4969d71ae5a4SJacob Faibussowitsch { 4970bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 4971bdf63967SMatthew G. Knepley char oname[256]; 49724e22dd4cSMatthew G. Knepley char sublabelname[PETSC_MAX_PATH_LEN] = ""; 4973adc21957SMatthew G. Knepley DMReorderDefaultFlag reorder; 4974d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 49759318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 4976*530e699aSMatthew G. Knepley PetscBool uniformOrig = PETSC_FALSE, uniform = PETSC_TRUE, distribute, saveSF = PETSC_FALSE, interpolate = PETSC_TRUE, coordSpace = PETSC_FALSE, remap = PETSC_TRUE, ghostCells = PETSC_FALSE, isHierarchy, flg; 497768d4fef7SMatthew G. Knepley 497868d4fef7SMatthew G. Knepley PetscFunctionBegin; 4979d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 4980dd4c3f67SMatthew G. Knepley if (dm->cloneOpts) goto non_refine; 49819318fe57SMatthew G. Knepley /* Handle automatic creation */ 49829566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 4983*530e699aSMatthew G. Knepley if (dim < 0) PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 49846bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 4985d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 49869566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 4987d89e6e46SMatthew G. Knepley if (flg) { 4988d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 4989d89e6e46SMatthew G. Knepley 49909566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 4991d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 4992d89e6e46SMatthew G. Knepley DM udm; 4993d89e6e46SMatthew G. Knepley 49949566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 499569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 4996d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 4997d89e6e46SMatthew G. Knepley DM idm; 4998d89e6e46SMatthew G. Knepley 49999566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 500069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 5001d89e6e46SMatthew G. Knepley } 5002d89e6e46SMatthew G. Knepley } 50034e22dd4cSMatthew G. Knepley // Handle submesh selection before distribution 50044e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_submesh", "Label to use for submesh selection", "", sublabelname, sublabelname, PETSC_MAX_PATH_LEN, &flg)); 50054e22dd4cSMatthew G. Knepley if (flg) { 50064e22dd4cSMatthew G. Knepley DM subdm; 50074e22dd4cSMatthew G. Knepley DMLabel label; 50084e22dd4cSMatthew G. Knepley IS valueIS, pointIS; 50094e22dd4cSMatthew G. Knepley const PetscInt *values, *points; 50104e22dd4cSMatthew G. Knepley PetscBool markedFaces = PETSC_FALSE; 50114e22dd4cSMatthew G. Knepley PetscInt Nv, value, Np; 50124e22dd4cSMatthew G. Knepley 50134e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, sublabelname, &label)); 50144e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &Nv)); 50154e22dd4cSMatthew 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); 50164e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetValueIS(label, &valueIS)); 50174e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &values)); 50184e22dd4cSMatthew G. Knepley value = values[0]; 50194e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(valueIS, &values)); 50204e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 50214e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumSize(label, value, &Np)); 50224e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, value, &pointIS)); 50234e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &points)); 50244e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 50254e22dd4cSMatthew G. Knepley PetscInt pdepth; 50264e22dd4cSMatthew G. Knepley 50274e22dd4cSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, points[p], &pdepth)); 50284e22dd4cSMatthew G. Knepley if (pdepth) { 50294e22dd4cSMatthew G. Knepley markedFaces = PETSC_TRUE; 50304e22dd4cSMatthew G. Knepley break; 50314e22dd4cSMatthew G. Knepley } 50324e22dd4cSMatthew G. Knepley } 50334e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &points)); 50344e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 50354e22dd4cSMatthew G. Knepley PetscCall(DMPlexCreateSubmesh(dm, label, value, markedFaces, &subdm)); 50364e22dd4cSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &subdm)); 50374e22dd4cSMatthew G. Knepley PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 50384e22dd4cSMatthew G. Knepley } 50399b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 50409566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 50419566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 50429566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 50439566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 50449566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 50459566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 50469318fe57SMatthew G. Knepley if (flg) { 50479566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 50489566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 50499318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 50509318fe57SMatthew G. Knepley } 5051b23db253SStefano Zampini if (prerefine) PetscCall(DMLocalizeCoordinates(dm)); 50529b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 50539b44eab4SMatthew G. Knepley DM rdm; 50549b44eab4SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 50559b44eab4SMatthew G. Knepley 5056dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 50579566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 505869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 5059dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 506061a622f3SMatthew G. Knepley if (coordFunc && remap) { 50619566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 50629b44eab4SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 50639b44eab4SMatthew G. Knepley } 50649b44eab4SMatthew G. Knepley } 50659566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 50669318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 50679566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 50689318fe57SMatthew G. Knepley if (extLayers) { 50699318fe57SMatthew G. Knepley DM edm; 50709318fe57SMatthew G. Knepley 50719566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 507269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 507348d16a33SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = NULL; 5074dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5075d410b0cfSMatthew G. Knepley extLayers = 0; 50765e17fc22SAidan Hamilton PetscCall(DMGetDimension(dm, &dim)); 50779318fe57SMatthew G. Knepley } 5078bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 50796bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 50809566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 50816bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 50829566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 5083adc21957SMatthew G. Knepley if (reorder == DM_REORDER_DEFAULT_TRUE || flg) { 5084bdf63967SMatthew G. Knepley DM pdm; 5085bdf63967SMatthew G. Knepley IS perm; 5086bdf63967SMatthew G. Knepley 50879566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 50889566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 50899566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 509069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 5091dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5092bdf63967SMatthew G. Knepley } 50939b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 50949566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 5095c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 5096a286e215SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute_save_sf", "Flag to save the migration SF", "DMPlexSetMigrationSF", saveSF, &saveSF, NULL)); 5097dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 50989b44eab4SMatthew G. Knepley if (distribute) { 50999b44eab4SMatthew G. Knepley DM pdm = NULL; 51009b44eab4SMatthew G. Knepley PetscPartitioner part; 5101a286e215SMatthew G. Knepley PetscSF sfMigration; 51029b44eab4SMatthew G. Knepley 51039566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 51049566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 5105a286e215SMatthew G. Knepley PetscCall(DMPlexDistribute(dm, overlap, &sfMigration, &pdm)); 51065d2873a6SJames Wright if (pdm) { 51075d2873a6SJames Wright // Delete the local section to force the existing one to be rebuilt with the distributed DM 51085d2873a6SJames Wright PetscCall(DMSetLocalSection(dm, pdm->localSection)); 51095d2873a6SJames Wright PetscCall(DMPlexReplace_Internal(dm, &pdm)); 51105d2873a6SJames Wright } 5111a286e215SMatthew G. Knepley if (saveSF) PetscCall(DMPlexSetMigrationSF(dm, sfMigration)); 5112a286e215SMatthew G. Knepley PetscCall(PetscSFDestroy(&sfMigration)); 51139b44eab4SMatthew G. Knepley } 51144054ae39SJames Wright 51154054ae39SJames Wright { 51164054ae39SJames Wright PetscBool useBoxLabel = PETSC_FALSE; 51174054ae39SJames Wright PetscCall(PetscOptionsBool("-dm_plex_box_label", "Create 'Face Sets' assuming boundary faces align with cartesian directions", "DMCreate", useBoxLabel, &useBoxLabel, NULL)); 5118d7d2d1d2SJames Wright if (useBoxLabel) { 5119d7d2d1d2SJames Wright PetscInt n = 3; 5120d7d2d1d2SJames Wright DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 5121d7d2d1d2SJames Wright 5122d7d2d1d2SJames Wright PetscCall(PetscOptionsEnumArray("-dm_plex_box_label_bd", "Boundary type for each dimension when using -dm_plex_box_label", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 5123d7d2d1d2SJames 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); 5124d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, bdt)); 5125d7d2d1d2SJames Wright } 51264054ae39SJames Wright } 5127d2b2dc1eSMatthew G. Knepley /* Must check CEED options before creating function space for coordinates */ 5128d2b2dc1eSMatthew G. Knepley { 5129d2b2dc1eSMatthew G. Knepley PetscBool useCeed = PETSC_FALSE, flg; 5130d2b2dc1eSMatthew G. Knepley 5131d2b2dc1eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_use_ceed", "Use LibCEED as the FEM backend", "DMPlexSetUseCeed", useCeed, &useCeed, &flg)); 5132d2b2dc1eSMatthew G. Knepley if (flg) PetscCall(DMPlexSetUseCeed(dm, useCeed)); 5133d2b2dc1eSMatthew G. Knepley } 51349318fe57SMatthew G. Knepley /* Create coordinate space */ 5135*530e699aSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, NULL)); 5136*530e699aSMatthew G. Knepley if (coordSpace) { 513761a622f3SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 5138e44f6aebSMatthew G. Knepley PetscInt degree = 1, deg; 51395515ebd3SMatthew G. Knepley PetscInt height = 0; 51405515ebd3SMatthew G. Knepley DM cdm; 5141*530e699aSMatthew G. Knepley PetscBool localize = PETSC_TRUE, sparseLocalize = PETSC_TRUE; 51429318fe57SMatthew G. Knepley 51439566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 5144e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDegree_Internal(dm, °)); 5145e44f6aebSMatthew G. Knepley if (coordSpace && deg <= 1) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_TRUE, mesh->coordFunc)); 51465515ebd3SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5147*530e699aSMatthew G. Knepley if (!coordSpace) { 514861a622f3SMatthew G. Knepley PetscDS cds; 514961a622f3SMatthew G. Knepley PetscObject obj; 515061a622f3SMatthew G. Knepley PetscClassId id; 515161a622f3SMatthew G. Knepley 51529566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 51539566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 51549566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 515561a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 515661a622f3SMatthew G. Knepley PetscContainer dummy; 515761a622f3SMatthew G. Knepley 51589566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 51599566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 51609566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 51619566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 51629566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 516361a622f3SMatthew G. Knepley } 516461a622f3SMatthew G. Knepley mesh->coordFunc = NULL; 516561a622f3SMatthew G. Knepley } 5166c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_localize", "Localize mesh coordinates", "", localize, &localize, NULL)); 5167c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "DMSetSparseLocalize", sparseLocalize, &sparseLocalize, &flg)); 5168c3db174cSMatthew G. Knepley if (flg) PetscCall(DMSetSparseLocalize(dm, sparseLocalize)); 51695515ebd3SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg)); 51705515ebd3SMatthew G. Knepley if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height)); 5171c3db174cSMatthew G. Knepley if (localize) PetscCall(DMLocalizeCoordinates(dm)); 51729318fe57SMatthew G. Knepley } 517368d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 517461a622f3SMatthew G. Knepley remap = PETSC_TRUE; 51759566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 51769566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 51779566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 51789566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 517968d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 5180acdc6f61SToby Isaac DM *dms, coarseDM; 518168d4fef7SMatthew G. Knepley 51829566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 51839566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 51849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 51859566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 518668d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 51879566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 518868d4fef7SMatthew G. Knepley if (refine == 1) { 51899566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 51909566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 519168d4fef7SMatthew G. Knepley } else { 51929566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 51939566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 51949566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 51959566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 519668d4fef7SMatthew G. Knepley } 51979566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 51989566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 519968d4fef7SMatthew G. Knepley /* Free DMs */ 520068d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 5201dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 52029566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 520368d4fef7SMatthew G. Knepley } 52049566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 520568d4fef7SMatthew G. Knepley } else { 520668d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 52079318fe57SMatthew G. Knepley DM rdm; 520851a74b61SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 520968d4fef7SMatthew G. Knepley 5210dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 52119566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 521268d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 521369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 5214dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 521561a622f3SMatthew G. Knepley if (coordFunc && remap) { 52169566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 521751a74b61SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 521851a74b61SMatthew G. Knepley } 521968d4fef7SMatthew G. Knepley } 522068d4fef7SMatthew G. Knepley } 52213cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 52229566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 52239566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 5224b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 5225b653a561SMatthew G. Knepley DM *dms; 5226b653a561SMatthew G. Knepley 52279566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 52289566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 5229b653a561SMatthew G. Knepley /* Free DMs */ 5230b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 5231dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 52329566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 5233b653a561SMatthew G. Knepley } 52349566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 5235b653a561SMatthew G. Knepley } else { 5236b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 52379318fe57SMatthew G. Knepley DM cdm; 52389318fe57SMatthew G. Knepley PetscPointFunc coordFunc = ((DM_Plex *)dm->data)->coordFunc; 52393cf6fe12SMatthew G. Knepley 5240dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 52419566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 52423cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 524369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 5244dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 52459318fe57SMatthew G. Knepley if (coordFunc) { 52469566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 52479318fe57SMatthew G. Knepley ((DM_Plex *)dm->data)->coordFunc = coordFunc; 52489318fe57SMatthew G. Knepley } 52493cf6fe12SMatthew G. Knepley } 5250b653a561SMatthew G. Knepley } 5251be664eb1SMatthew G. Knepley // Handle coordinate remapping 5252be664eb1SMatthew G. Knepley remap = PETSC_FALSE; 5253be664eb1SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_coord_remap", "Flag to control coordinate remapping", "", remap, &remap, NULL)); 5254be664eb1SMatthew G. Knepley if (remap) { 5255be664eb1SMatthew G. Knepley DMPlexCoordMap map = DM_COORD_MAP_NONE; 5256be664eb1SMatthew G. Knepley PetscPointFunc mapFunc = NULL; 5257be664eb1SMatthew G. Knepley PetscScalar params[16]; 5258f45b553cSPierre Jolivet PetscInt Np = PETSC_STATIC_ARRAY_LENGTH(params), cdim; 5259be664eb1SMatthew G. Knepley MPI_Comm comm; 5260be664eb1SMatthew G. Knepley 5261be664eb1SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 5262be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 5263be664eb1SMatthew G. Knepley PetscCall(PetscOptionsScalarArray("-dm_coord_map_params", "Parameters for the coordinate remapping", "", params, &Np, &flg)); 5264be664eb1SMatthew G. Knepley if (!flg) Np = 0; 5265be664eb1SMatthew G. Knepley // TODO Allow user to pass a map function by name 5266be664eb1SMatthew G. Knepley PetscCall(PetscOptionsEnum("-dm_coord_map", "Coordinate mapping for built-in mesh", "", DMPlexCoordMaps, (PetscEnum)map, (PetscEnum *)&map, &flg)); 5267be664eb1SMatthew G. Knepley if (flg) { 5268be664eb1SMatthew G. Knepley switch (map) { 5269be664eb1SMatthew G. Knepley case DM_COORD_MAP_NONE: 5270be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5271be664eb1SMatthew G. Knepley break; 5272be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHEAR: 5273be664eb1SMatthew G. Knepley mapFunc = coordMap_shear; 5274be664eb1SMatthew G. Knepley if (!Np) { 5275be664eb1SMatthew G. Knepley Np = cdim + 1; 5276be664eb1SMatthew G. Knepley params[0] = 0; 5277be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5278be664eb1SMatthew G. Knepley } 5279be664eb1SMatthew 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); 5280be664eb1SMatthew G. Knepley break; 5281be664eb1SMatthew G. Knepley case DM_COORD_MAP_FLARE: 5282be664eb1SMatthew G. Knepley mapFunc = coordMap_flare; 5283be664eb1SMatthew G. Knepley if (!Np) { 5284be664eb1SMatthew G. Knepley Np = cdim + 1; 5285be664eb1SMatthew G. Knepley params[0] = 0; 5286be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5287be664eb1SMatthew G. Knepley } 5288be664eb1SMatthew 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); 5289be664eb1SMatthew G. Knepley break; 5290be664eb1SMatthew G. Knepley case DM_COORD_MAP_ANNULUS: 5291be664eb1SMatthew G. Knepley mapFunc = coordMap_annulus; 5292be664eb1SMatthew G. Knepley if (!Np) { 5293be664eb1SMatthew G. Knepley Np = 2; 5294be664eb1SMatthew G. Knepley params[0] = 1.; 5295be664eb1SMatthew G. Knepley params[1] = 2.; 5296be664eb1SMatthew G. Knepley } 5297be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The annulus coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5298be664eb1SMatthew G. Knepley break; 5299be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHELL: 5300be664eb1SMatthew G. Knepley mapFunc = coordMap_shell; 5301be664eb1SMatthew G. Knepley if (!Np) { 5302be664eb1SMatthew G. Knepley Np = 2; 5303be664eb1SMatthew G. Knepley params[0] = 1.; 5304be664eb1SMatthew G. Knepley params[1] = 2.; 5305be664eb1SMatthew G. Knepley } 5306be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The spherical shell coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5307be664eb1SMatthew G. Knepley break; 5308*530e699aSMatthew G. Knepley case DM_COORD_MAP_SINUSOID: 5309*530e699aSMatthew G. Knepley mapFunc = coordMap_sinusoid; 5310*530e699aSMatthew G. Knepley if (!Np) { 5311*530e699aSMatthew G. Knepley Np = 3; 5312*530e699aSMatthew G. Knepley params[0] = 1.; 5313*530e699aSMatthew G. Knepley params[1] = 1.; 5314*530e699aSMatthew G. Knepley params[2] = 1.; 5315*530e699aSMatthew G. Knepley } 5316*530e699aSMatthew G. Knepley PetscCheck(Np == 3, comm, PETSC_ERR_ARG_WRONG, "The sinusoidal coordinate map must have 3 parameters, not %" PetscInt_FMT, Np); 5317*530e699aSMatthew G. Knepley break; 5318be664eb1SMatthew G. Knepley default: 5319be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5320be664eb1SMatthew G. Knepley } 5321be664eb1SMatthew G. Knepley } 5322be664eb1SMatthew G. Knepley if (Np) { 5323be664eb1SMatthew G. Knepley DM cdm; 5324be664eb1SMatthew G. Knepley PetscDS cds; 5325be664eb1SMatthew G. Knepley 5326be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5327be664eb1SMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 5328be664eb1SMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, Np, params)); 5329be664eb1SMatthew G. Knepley } 5330be664eb1SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, mapFunc)); 5331be664eb1SMatthew G. Knepley } 5332909dfd52SMatthew G. Knepley /* Handle ghost cells */ 53339566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 5334909dfd52SMatthew G. Knepley if (ghostCells) { 5335909dfd52SMatthew G. Knepley DM gdm; 5336909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 5337909dfd52SMatthew G. Knepley 5338909dfd52SMatthew G. Knepley lname[0] = '\0'; 53399566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 53409566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 534169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 5342909dfd52SMatthew G. Knepley } 53436913077dSMatthew G. Knepley /* Handle 1D order */ 5344adc21957SMatthew G. Knepley if (reorder != DM_REORDER_DEFAULT_FALSE && dim == 1) { 53456913077dSMatthew G. Knepley DM cdm, rdm; 53466913077dSMatthew G. Knepley PetscDS cds; 53476913077dSMatthew G. Knepley PetscObject obj; 53486913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 53496913077dSMatthew G. Knepley IS perm; 53506bc1bd01Sksagiyam PetscInt Nf; 53516913077dSMatthew G. Knepley PetscBool distributed; 53526913077dSMatthew G. Knepley 53539566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 53549566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 53559566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 53569566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 53576913077dSMatthew G. Knepley if (Nf) { 53589566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 53599566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 53606913077dSMatthew G. Knepley } 53616bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 53629566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 53639566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 536469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 53659566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 53666913077dSMatthew G. Knepley } 53676913077dSMatthew G. Knepley } 53683cf6fe12SMatthew G. Knepley /* Handle */ 5369dd4c3f67SMatthew G. Knepley non_refine: 5370dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 537122d6dc08SStefano Zampini char *phases[16]; 537222d6dc08SStefano Zampini PetscInt Nphases = 16; 537322d6dc08SStefano Zampini PetscCall(PetscOptionsStringArray("-dm_plex_option_phases", "Option phase prefixes", "DMSetFromOptions", phases, &Nphases, &flg)); 5374d0609cedSBarry Smith PetscOptionsHeadEnd(); 537522d6dc08SStefano Zampini 537622d6dc08SStefano Zampini // Phases 537722d6dc08SStefano Zampini if (flg) { 5378*530e699aSMatthew G. Knepley DM cdm; 5379*530e699aSMatthew G. Knepley char *oldPrefix, *oldCoordPrefix; 5380*530e699aSMatthew G. Knepley const char *tmp; 538122d6dc08SStefano Zampini 5382*530e699aSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5383*530e699aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &tmp)); 5384*530e699aSMatthew G. Knepley PetscCall(PetscStrallocpy(tmp, &oldPrefix)); 5385*530e699aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)cdm, &tmp)); 5386*530e699aSMatthew G. Knepley PetscCall(PetscStrallocpy(tmp, &oldCoordPrefix)); 538722d6dc08SStefano Zampini for (PetscInt ph = 0; ph < Nphases; ++ph) { 538822d6dc08SStefano Zampini PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, phases[ph])); 5389*530e699aSMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)cdm, phases[ph])); 539022d6dc08SStefano Zampini PetscCall(PetscInfo(dm, "Options phase %s for DM %s\n", phases[ph], dm->hdr.name)); 539122d6dc08SStefano Zampini PetscCall(DMSetFromOptions(dm)); 539222d6dc08SStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix)); 5393*530e699aSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5394*530e699aSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)cdm, oldCoordPrefix)); 539522d6dc08SStefano Zampini PetscCall(PetscFree(phases[ph])); 539622d6dc08SStefano Zampini } 5397*530e699aSMatthew G. Knepley PetscCall(PetscFree(oldPrefix)); 5398*530e699aSMatthew G. Knepley PetscCall(PetscFree(oldCoordPrefix)); 539922d6dc08SStefano Zampini } 54003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 54010a6ba040SMatthew G. Knepley } 54020a6ba040SMatthew G. Knepley 5403d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) 5404d71ae5a4SJacob Faibussowitsch { 5405552f7358SJed Brown PetscFunctionBegin; 54069566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 54079566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 54089566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 54099566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 54109566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 54119566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 54123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5413552f7358SJed Brown } 5414552f7358SJed Brown 5415d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) 5416d71ae5a4SJacob Faibussowitsch { 5417552f7358SJed Brown PetscFunctionBegin; 54189566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 54199566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 54209566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 54213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5422552f7358SJed Brown } 5423552f7358SJed Brown 5424d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 5425d71ae5a4SJacob Faibussowitsch { 5426793f3fe5SMatthew G. Knepley PetscInt depth, d; 5427793f3fe5SMatthew G. Knepley 5428793f3fe5SMatthew G. Knepley PetscFunctionBegin; 54299566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 5430793f3fe5SMatthew G. Knepley if (depth == 1) { 54319566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 54329566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 54339566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 54349371c9d4SSatish Balay else { 54359371c9d4SSatish Balay *pStart = 0; 54369371c9d4SSatish Balay *pEnd = 0; 54379371c9d4SSatish Balay } 5438793f3fe5SMatthew G. Knepley } else { 54399566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 5440793f3fe5SMatthew G. Knepley } 54413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5442793f3fe5SMatthew G. Knepley } 5443793f3fe5SMatthew G. Knepley 5444d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 5445d71ae5a4SJacob Faibussowitsch { 5446502a2867SDave May PetscSF sf; 54476497c311SBarry Smith PetscMPIInt niranks, njranks; 54486497c311SBarry Smith PetscInt n; 54490a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 54500a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 5451502a2867SDave May 54522f356facSMatthew G. Knepley PetscFunctionBegin; 54539566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 54540a19bb7dSprj- if (!data->neighbors) { 54559566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 54569566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 54579566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 54589566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 54599566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 54609566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 54610a19bb7dSprj- n = njranks + niranks; 54629566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 54630a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 54649566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 54650a19bb7dSprj- } 54660a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 54670a19bb7dSprj- if (ranks) { 54680a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 54690a19bb7dSprj- else *ranks = NULL; 54700a19bb7dSprj- } 54713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5472502a2867SDave May } 5473502a2867SDave May 54741eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 54751eb70e55SToby Isaac 5476d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm) 5477d71ae5a4SJacob Faibussowitsch { 5478552f7358SJed Brown PetscFunctionBegin; 5479552f7358SJed Brown dm->ops->view = DMView_Plex; 54802c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 5481552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 548238221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 5483552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 54841bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 5485adc21957SMatthew G. Knepley dm->ops->createsectionpermutation = DMCreateSectionPermutation_Plex; 548666ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 5487552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 5488552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 5489184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 54900298fd71SBarry Smith dm->ops->createfieldis = NULL; 5491552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 5492f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 54930a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 5494552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 5495bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 5496bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 5497b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 54985a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 5499552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 55000a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 55010a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 5502b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 5503d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 55040298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 55050298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 55060298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 55070298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 5508552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 5509552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 55102adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 5511793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 5512552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 55130709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 55140709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 5515bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 55168c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 5517ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 55180709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 5519b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 55202a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 552128d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 55226c6a6b79SMatthew G. Knepley dm->ops->getlocalboundingbox = DMGetLocalBoundingBox_Coordinates; 5523907a3e9cSStefano Zampini dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_Plex; 5524907a3e9cSStefano Zampini dm->ops->createddscatters = DMCreateDomainDecompositionScatters_Plex; 55259566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 55266c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 55279566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 55289566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 55299566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 55309566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 55316bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 55326bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 5533adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", DMReorderSectionGetDefault_Plex)); 5534adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", DMReorderSectionSetDefault_Plex)); 5535adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", DMReorderSectionGetType_Plex)); 5536adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", DMReorderSectionSetType_Plex)); 55379566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 5538c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 5539c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 5540d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", DMPlexGetUseCeed_Plex)); 5541d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", DMPlexSetUseCeed_Plex)); 55423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5543552f7358SJed Brown } 5544552f7358SJed Brown 5545d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 5546d71ae5a4SJacob Faibussowitsch { 554763a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 55481fca310dSJames Wright const PetscSF *face_sfs; 55491fca310dSJames Wright PetscInt num_face_sfs; 555063a16f15SMatthew G. Knepley 555163a16f15SMatthew G. Knepley PetscFunctionBegin; 555263a16f15SMatthew G. Knepley mesh->refct++; 555363a16f15SMatthew G. Knepley (*newdm)->data = mesh; 55541fca310dSJames Wright PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &face_sfs)); 55551fca310dSJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, num_face_sfs, (PetscSF *)face_sfs)); 55569566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 55579566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 55583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 555963a16f15SMatthew G. Knepley } 556063a16f15SMatthew G. Knepley 55618818961aSMatthew G Knepley /*MC 55620b4b7b1cSBarry Smith DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh (or grid), or CW Complex {cite}`cwcomplex`, 55630b4b7b1cSBarry Smith which can be expressed using a Hasse Diagram {cite}`hassediagram`. 556420f4b53cSBarry Smith In the local representation, `Vec`s contain all unknowns in the interior and shared boundary. This is 55650b4b7b1cSBarry Smith specified by a `PetscSection` object. Ownership in the global representation is determined by 5566a1cb98faSBarry Smith ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object. 55678818961aSMatthew G Knepley 5568e5893cccSMatthew G. Knepley Options Database Keys: 5569250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 5570250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 5571250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 5572250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 5573250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 5574250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 5575c3db174cSMatthew G. Knepley . -dm_localize <bool> - Whether to localize coordinates for periodic meshes 5576c3db174cSMatthew G. Knepley . -dm_sparse_localize <bool> - Whether to only localize cells on the periodic boundary 5577250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 5578ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 5579f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 5580f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 5581d5b43468SJose E. Roman . -dm_plex_max_projection_height - Maximum mesh point height used to project locally 5582f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 5583d02c7345SMatthew G. Knepley . -dm_plex_reorder_section - Use specialized blocking if available 5584aaa8cc7dSPierre Jolivet . -dm_plex_check_all - Perform all checks below 5585f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 5586f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 5587f12cf164SMatthew 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 5588f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 5589f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 5590e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 55915962854dSMatthew G. Knepley . -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 55925962854dSMatthew G. Knepley - -dm_plex_print_fvm <num> - View FVM assembly information, such as flux updates 5593e5893cccSMatthew G. Knepley 55948818961aSMatthew G Knepley Level: intermediate 55958818961aSMatthew G Knepley 55961cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection` 55978818961aSMatthew G Knepley M*/ 55988818961aSMatthew G Knepley 5599d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 5600d71ae5a4SJacob Faibussowitsch { 5601552f7358SJed Brown DM_Plex *mesh; 5602412e9a14SMatthew G. Knepley PetscInt unit; 5603552f7358SJed Brown 5604552f7358SJed Brown PetscFunctionBegin; 5605f39ec787SMatthew G. Knepley PetscCall(PetscCitationsRegister(PlexCitation, &Plexcite)); 5606552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 56074dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mesh)); 5608adc21957SMatthew G. Knepley dm->reorderSection = DM_REORDER_DEFAULT_NOTSET; 5609552f7358SJed Brown dm->data = mesh; 5610552f7358SJed Brown 5611552f7358SJed Brown mesh->refct = 1; 56129566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 56139566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 5614552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 5615552f7358SJed Brown mesh->refinementLimit = -1.0; 5616e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 5617adc21957SMatthew G. Knepley mesh->reorderDefault = DM_REORDER_DEFAULT_NOTSET; 56181d1f2f2aSksagiyam mesh->distributionName = NULL; 56197d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 56207d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 56215e2c5519SMatthew G. Knepley mesh->interpolatePreferTensor = PETSC_TRUE; 5622552f7358SJed Brown 56239566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 56242e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 5625d9deefdfSMatthew G. Knepley 56268865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 5627552f7358SJed Brown 5628df0420ecSMatthew G. Knepley mesh->depthState = -1; 5629ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 56306113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 5631c29ce622SStefano Zampini mesh->nonempty_comm = MPI_COMM_SELF; 5632552f7358SJed Brown 56339566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 56343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5635552f7358SJed Brown } 5636552f7358SJed Brown 5637552f7358SJed Brown /*@ 5638a1cb98faSBarry Smith DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 5639552f7358SJed Brown 5640d083f849SBarry Smith Collective 5641552f7358SJed Brown 5642552f7358SJed Brown Input Parameter: 5643a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object 5644552f7358SJed Brown 5645552f7358SJed Brown Output Parameter: 5646a1cb98faSBarry Smith . mesh - The `DMPLEX` object 5647552f7358SJed Brown 5648552f7358SJed Brown Level: beginner 5649552f7358SJed Brown 565042747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMCreate()`, `DMSetType()` 5651552f7358SJed Brown @*/ 5652d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 5653d71ae5a4SJacob Faibussowitsch { 5654552f7358SJed Brown PetscFunctionBegin; 56554f572ea9SToby Isaac PetscAssertPointer(mesh, 2); 56569566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 56579566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 56583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5659552f7358SJed Brown } 5660552f7358SJed Brown 5661b09969d6SVaclav Hapla /*@C 5662b0fe842aSMatthew 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 5663a1cb98faSBarry Smith 566420f4b53cSBarry Smith Collective; No Fortran Support 5665b09969d6SVaclav Hapla 5666b09969d6SVaclav Hapla Input Parameters: 5667a1cb98faSBarry Smith + dm - The `DM` 5668b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 5669a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 5670a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DETERMINE` 5671b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 56725e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 5673b09969d6SVaclav Hapla 5674be8c289dSNicolas Barral Output Parameters: 5675a1cb98faSBarry Smith + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 5676be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 5677b09969d6SVaclav Hapla 5678b09969d6SVaclav Hapla Level: advanced 5679b09969d6SVaclav Hapla 5680a1cb98faSBarry Smith Notes: 5681a1cb98faSBarry Smith Two triangles sharing a face 5682a1cb98faSBarry Smith .vb 5683a1cb98faSBarry Smith 5684a1cb98faSBarry Smith 2 5685a1cb98faSBarry Smith / | \ 5686a1cb98faSBarry Smith / | \ 5687a1cb98faSBarry Smith / | \ 5688a1cb98faSBarry Smith 0 0 | 1 3 5689a1cb98faSBarry Smith \ | / 5690a1cb98faSBarry Smith \ | / 5691a1cb98faSBarry Smith \ | / 5692a1cb98faSBarry Smith 1 5693a1cb98faSBarry Smith .ve 5694a1cb98faSBarry Smith would have input 5695a1cb98faSBarry Smith .vb 5696a1cb98faSBarry Smith numCells = 2, numVertices = 4 5697a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 5698a1cb98faSBarry Smith .ve 5699a1cb98faSBarry Smith which would result in the `DMPLEX` 5700a1cb98faSBarry Smith .vb 5701a1cb98faSBarry Smith 5702a1cb98faSBarry Smith 4 5703a1cb98faSBarry Smith / | \ 5704a1cb98faSBarry Smith / | \ 5705a1cb98faSBarry Smith / | \ 5706a1cb98faSBarry Smith 2 0 | 1 5 5707a1cb98faSBarry Smith \ | / 5708a1cb98faSBarry Smith \ | / 5709a1cb98faSBarry Smith \ | / 5710a1cb98faSBarry Smith 3 5711a1cb98faSBarry Smith .ve 5712a1cb98faSBarry Smith 5713a1cb98faSBarry Smith Vertices are implicitly numbered consecutively 0,...,NVertices. 5714a1cb98faSBarry Smith Each rank owns a chunk of numVertices consecutive vertices. 5715a1cb98faSBarry Smith If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 5716a1cb98faSBarry Smith If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 5717a1cb98faSBarry Smith If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 5718a1cb98faSBarry Smith 5719a1cb98faSBarry Smith The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 5720a1cb98faSBarry Smith 57211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 5722a1cb98faSBarry Smith `PetscSF` 5723b09969d6SVaclav Hapla @*/ 5724ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[]) 5725d71ae5a4SJacob Faibussowitsch { 57262464107aSksagiyam PetscSF sfPoint; 57272464107aSksagiyam PetscLayout layout; 572882fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 5729a47d0d45SMatthew G. Knepley 5730a47d0d45SMatthew G. Knepley PetscFunctionBegin; 573125b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 57329566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 573325b6865aSVaclav Hapla /* Get/check global number of vertices */ 573425b6865aSVaclav Hapla { 573525b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 573625b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 573725b6865aSVaclav Hapla 573825b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 57391690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 57409371c9d4SSatish Balay for (i = 0; i < len; i++) 57419371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 574225b6865aSVaclav Hapla ++NVerticesInCells; 5743462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 574425b6865aSVaclav Hapla 574525b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 57469371c9d4SSatish Balay else 57479371c9d4SSatish 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); 574825b6865aSVaclav Hapla } 57499079aca8SVaclav Hapla /* Count locally unique vertices */ 57509079aca8SVaclav Hapla { 57519079aca8SVaclav Hapla PetscHSetI vhash; 57529079aca8SVaclav Hapla PetscInt off = 0; 57539079aca8SVaclav Hapla 57549566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 5755a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 575648a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 5757a47d0d45SMatthew G. Knepley } 57589566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 57599566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 5760ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 57619566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 57629566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 576363a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 5764a47d0d45SMatthew G. Knepley } 57659566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 5766a47d0d45SMatthew G. Knepley /* Create cones */ 57679566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 57689566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 57699566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 57709566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 5771a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 5772a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 5773a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 5774a47d0d45SMatthew G. Knepley PetscInt lv; 5775a47d0d45SMatthew G. Knepley 57769079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 57779079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 57789566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 577963a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 5780961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 5781a47d0d45SMatthew G. Knepley } 5782a47d0d45SMatthew G. Knepley } 57832464107aSksagiyam /* Build point sf */ 57849566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 57859566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 57869566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 57879566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 57889566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 57899566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 57909566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 57919566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 57922464107aSksagiyam if (dm->sf) { 57932464107aSksagiyam const char *prefix; 57942464107aSksagiyam 57959566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 57969566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 57972464107aSksagiyam } 57989566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 57999566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 5800f4f49eeaSPierre Jolivet if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 5801a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 58029566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 58039566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 58049566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 58053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5806a47d0d45SMatthew G. Knepley } 5807a47d0d45SMatthew G. Knepley 5808b0fe842aSMatthew G. Knepley /*@C 5809b0fe842aSMatthew G. Knepley DMPlexBuildFromCellSectionParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) allowing multiple celltypes 5810b0fe842aSMatthew G. Knepley 5811b0fe842aSMatthew G. Knepley Collective; No Fortran Support 5812b0fe842aSMatthew G. Knepley 5813b0fe842aSMatthew G. Knepley Input Parameters: 5814b0fe842aSMatthew G. Knepley + dm - The `DM` 5815b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 5816b0fe842aSMatthew G. Knepley . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 5817b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DETERMINE` 5818b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 5819b0fe842aSMatthew G. Knepley - cells - An array of the global vertex numbers for each cell 5820b0fe842aSMatthew G. Knepley 5821b0fe842aSMatthew G. Knepley Output Parameters: 5822b0fe842aSMatthew G. Knepley + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 5823b0fe842aSMatthew G. Knepley - verticesAdjSaved - (Optional) vertex adjacency array 5824b0fe842aSMatthew G. Knepley 5825b0fe842aSMatthew G. Knepley Level: advanced 5826b0fe842aSMatthew G. Knepley 5827b0fe842aSMatthew G. Knepley Notes: 5828b0fe842aSMatthew G. Knepley A triangle and quadrilateral sharing a face 5829b0fe842aSMatthew G. Knepley .vb 5830b0fe842aSMatthew G. Knepley 2----------3 5831b0fe842aSMatthew G. Knepley / | | 5832b0fe842aSMatthew G. Knepley / | | 5833b0fe842aSMatthew G. Knepley / | | 5834b0fe842aSMatthew G. Knepley 0 0 | 1 | 5835b0fe842aSMatthew G. Knepley \ | | 5836b0fe842aSMatthew G. Knepley \ | | 5837b0fe842aSMatthew G. Knepley \ | | 5838b0fe842aSMatthew G. Knepley 1----------4 5839b0fe842aSMatthew G. Knepley .ve 5840b0fe842aSMatthew G. Knepley would have input 5841b0fe842aSMatthew G. Knepley .vb 5842b0fe842aSMatthew G. Knepley numCells = 2, numVertices = 5 5843b0fe842aSMatthew G. Knepley cells = [0 1 2 1 4 3 2] 5844b0fe842aSMatthew G. Knepley .ve 5845b0fe842aSMatthew G. Knepley which would result in the `DMPLEX` 5846b0fe842aSMatthew G. Knepley .vb 5847b0fe842aSMatthew G. Knepley 4----------5 5848b0fe842aSMatthew G. Knepley / | | 5849b0fe842aSMatthew G. Knepley / | | 5850b0fe842aSMatthew G. Knepley / | | 5851b0fe842aSMatthew G. Knepley 2 0 | 1 | 5852b0fe842aSMatthew G. Knepley \ | | 5853b0fe842aSMatthew G. Knepley \ | | 5854b0fe842aSMatthew G. Knepley \ | | 5855b0fe842aSMatthew G. Knepley 3----------6 5856b0fe842aSMatthew G. Knepley .ve 5857b0fe842aSMatthew G. Knepley 5858b0fe842aSMatthew G. Knepley Vertices are implicitly numbered consecutively 0,...,NVertices. 5859b0fe842aSMatthew G. Knepley Each rank owns a chunk of numVertices consecutive vertices. 5860b0fe842aSMatthew G. Knepley If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 5861b0fe842aSMatthew 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. 5862b0fe842aSMatthew G. Knepley If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 5863b0fe842aSMatthew G. Knepley 5864b0fe842aSMatthew G. Knepley The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 5865b0fe842aSMatthew G. Knepley 5866b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexCreateFromCellSectionParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 5867b0fe842aSMatthew G. Knepley `PetscSF` 5868b0fe842aSMatthew G. Knepley @*/ 5869ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellSectionParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[]) 5870b0fe842aSMatthew G. Knepley { 5871b0fe842aSMatthew G. Knepley PetscSF sfPoint; 5872b0fe842aSMatthew G. Knepley PetscLayout layout; 5873b0fe842aSMatthew G. Knepley PetscInt numVerticesAdj, *verticesAdj, *cones, cStart, cEnd, len; 5874b0fe842aSMatthew G. Knepley 5875b0fe842aSMatthew G. Knepley PetscFunctionBegin; 5876b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, NVertices, 4); 5877b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 5878b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetChart(cellSection, &cStart, &cEnd)); 5879b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(cellSection, &len)); 5880b0fe842aSMatthew 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); 5881b0fe842aSMatthew G. Knepley /* Get/check global number of vertices */ 5882b0fe842aSMatthew G. Knepley { 5883b0fe842aSMatthew G. Knepley PetscInt NVerticesInCells; 5884b0fe842aSMatthew G. Knepley 5885b0fe842aSMatthew G. Knepley /* NVerticesInCells = max(cells) + 1 */ 5886b0fe842aSMatthew G. Knepley NVerticesInCells = PETSC_MIN_INT; 5887b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) 5888b0fe842aSMatthew G. Knepley if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 5889b0fe842aSMatthew G. Knepley ++NVerticesInCells; 5890b0fe842aSMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 5891b0fe842aSMatthew G. Knepley 5892b0fe842aSMatthew G. Knepley if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 5893b0fe842aSMatthew G. Knepley else 5894b0fe842aSMatthew 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); 5895b0fe842aSMatthew G. Knepley } 5896b0fe842aSMatthew G. Knepley /* Count locally unique vertices */ 5897b0fe842aSMatthew G. Knepley { 5898b0fe842aSMatthew G. Knepley PetscHSetI vhash; 5899b0fe842aSMatthew G. Knepley PetscInt off = 0; 5900b0fe842aSMatthew G. Knepley 5901b0fe842aSMatthew G. Knepley PetscCall(PetscHSetICreate(&vhash)); 5902b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) PetscCall(PetscHSetIAdd(vhash, cells[i])); 5903b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 5904b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 5905b0fe842aSMatthew G. Knepley else verticesAdj = *verticesAdjSaved; 5906b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 5907b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIDestroy(&vhash)); 5908b0fe842aSMatthew 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); 5909b0fe842aSMatthew G. Knepley } 5910b0fe842aSMatthew G. Knepley PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 5911b0fe842aSMatthew G. Knepley /* Create cones */ 5912b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 5913b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 5914b0fe842aSMatthew G. Knepley PetscInt dof; 5915b0fe842aSMatthew G. Knepley 5916b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 5917b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetConeSize(dm, c, dof)); 5918b0fe842aSMatthew G. Knepley } 5919b0fe842aSMatthew G. Knepley PetscCall(DMSetUp(dm)); 5920b0fe842aSMatthew G. Knepley PetscCall(DMPlexGetCones(dm, &cones)); 5921b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 5922b0fe842aSMatthew G. Knepley PetscInt dof, off; 5923b0fe842aSMatthew G. Knepley 5924b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 5925b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cellSection, c, &off)); 5926b0fe842aSMatthew G. Knepley for (PetscInt p = off; p < off + dof; ++p) { 5927b0fe842aSMatthew G. Knepley const PetscInt gv = cells[p]; 5928b0fe842aSMatthew G. Knepley PetscInt lv; 5929b0fe842aSMatthew G. Knepley 5930b0fe842aSMatthew G. Knepley /* Positions within verticesAdj form 0-based local vertex numbering; 5931b0fe842aSMatthew G. Knepley we need to shift it by numCells to get correct DAG points (cells go first) */ 5932b0fe842aSMatthew G. Knepley PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 5933b0fe842aSMatthew G. Knepley PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 5934b0fe842aSMatthew G. Knepley cones[p] = lv + numCells; 5935b0fe842aSMatthew G. Knepley } 5936b0fe842aSMatthew G. Knepley } 5937b0fe842aSMatthew G. Knepley /* Build point sf */ 5938b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 5939b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetSize(layout, NVertices)); 5940b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 5941b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetBlockSize(layout, 1)); 5942b0fe842aSMatthew G. Knepley PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 5943b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutDestroy(&layout)); 5944b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 5945b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 5946b0fe842aSMatthew G. Knepley if (dm->sf) { 5947b0fe842aSMatthew G. Knepley const char *prefix; 5948b0fe842aSMatthew G. Knepley 5949b0fe842aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 5950b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 5951b0fe842aSMatthew G. Knepley } 5952b0fe842aSMatthew G. Knepley PetscCall(DMSetPointSF(dm, sfPoint)); 5953b0fe842aSMatthew G. Knepley PetscCall(PetscSFDestroy(&sfPoint)); 5954b0fe842aSMatthew G. Knepley if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 5955b0fe842aSMatthew G. Knepley /* Fill in the rest of the topology structure */ 5956b0fe842aSMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 5957b0fe842aSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 5958b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 5959b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 5960b0fe842aSMatthew G. Knepley } 5961b0fe842aSMatthew G. Knepley 5962cc4c1da9SBarry Smith /*@ 5963a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 5964a1cb98faSBarry Smith 596520f4b53cSBarry Smith Collective; No Fortran Support 5966b09969d6SVaclav Hapla 5967b09969d6SVaclav Hapla Input Parameters: 5968a1cb98faSBarry Smith + dm - The `DM` 5969b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 5970a1cb98faSBarry Smith . sfVert - `PetscSF` describing complete vertex ownership 5971b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 5972b09969d6SVaclav Hapla 5973b09969d6SVaclav Hapla Level: advanced 5974b09969d6SVaclav Hapla 59751cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 5976b09969d6SVaclav Hapla @*/ 5977d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 5978d71ae5a4SJacob Faibussowitsch { 5979a47d0d45SMatthew G. Knepley PetscSection coordSection; 5980a47d0d45SMatthew G. Knepley Vec coordinates; 5981a47d0d45SMatthew G. Knepley PetscScalar *coords; 59821edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 5983835f2295SStefano Zampini PetscMPIInt spaceDimi; 5984a47d0d45SMatthew G. Knepley 5985a47d0d45SMatthew G. Knepley PetscFunctionBegin; 59869566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 59879566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 59881dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 59899566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 59909566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 59911dca8a05SBarry 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); 59929566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 59939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 59949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 59959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 59961edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 59979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 59989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 5999a47d0d45SMatthew G. Knepley } 60009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 60019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 60029566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 60039566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 60049566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 60059566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 60069566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 60079566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6008a47d0d45SMatthew G. Knepley { 6009a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 6010a47d0d45SMatthew G. Knepley 6011a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 6012835f2295SStefano Zampini PetscCall(PetscMPIIntCast(spaceDim, &spaceDimi)); 6013835f2295SStefano Zampini PetscCallMPI(MPI_Type_contiguous(spaceDimi, MPIU_SCALAR, &coordtype)); 60149566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 601521016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 601621016a8bSBarry Smith { 601721016a8bSBarry Smith PetscScalar *svertexCoords; 601821016a8bSBarry Smith PetscInt i; 60199566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 60203612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 60219566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 60229566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 60239566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 602421016a8bSBarry Smith } 602521016a8bSBarry Smith #else 60269566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 60279566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 602821016a8bSBarry Smith #endif 60299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 6030a47d0d45SMatthew G. Knepley } 60319566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 60329566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 60339566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 60349566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 60353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6036a47d0d45SMatthew G. Knepley } 6037a47d0d45SMatthew G. Knepley 6038c3edce3dSSatish Balay /*@ 6039b0fe842aSMatthew 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 6040a1cb98faSBarry Smith 6041a1cb98faSBarry Smith Collective 6042a47d0d45SMatthew G. Knepley 6043a47d0d45SMatthew G. Knepley Input Parameters: 6044a47d0d45SMatthew G. Knepley + comm - The communicator 6045a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 6046a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 6047a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 6048a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DECIDE` 6049a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 6050a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6051a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 6052a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 6053a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6054a47d0d45SMatthew G. Knepley 6055d8d19677SJose E. Roman Output Parameters: 6056a1cb98faSBarry Smith + dm - The `DM` 6057a1cb98faSBarry Smith . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 605860225df5SJacob Faibussowitsch - verticesAdj - (Optional) vertex adjacency array 6059a47d0d45SMatthew G. Knepley 6060b09969d6SVaclav Hapla Level: intermediate 6061a47d0d45SMatthew G. Knepley 6062a1cb98faSBarry Smith Notes: 6063a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 6064a1cb98faSBarry Smith `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 6065a1cb98faSBarry Smith 6066a1cb98faSBarry Smith See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters. 6067a1cb98faSBarry Smith 6068a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 6069a1cb98faSBarry Smith 60701cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 6071a47d0d45SMatthew G. Knepley @*/ 6072ce78bad3SBarry 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) 6073d71ae5a4SJacob Faibussowitsch { 6074a47d0d45SMatthew G. Knepley PetscSF sfVert; 6075a47d0d45SMatthew G. Knepley 6076a47d0d45SMatthew G. Knepley PetscFunctionBegin; 60779566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 60789566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 6079a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 6080064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 60819566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 60829566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 6083a47d0d45SMatthew G. Knepley if (interpolate) { 60845fd9971aSMatthew G. Knepley DM idm; 6085a47d0d45SMatthew G. Knepley 60869566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 60879566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 6088a47d0d45SMatthew G. Knepley *dm = idm; 6089a47d0d45SMatthew G. Knepley } 60909566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 609118d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 60929566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 60933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6094a47d0d45SMatthew G. Knepley } 6095a47d0d45SMatthew G. Knepley 6096cc4c1da9SBarry Smith /*@ 6097b0fe842aSMatthew G. Knepley DMPlexCreateFromCellSectionParallel - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) and supports multiple celltypes 6098b0fe842aSMatthew G. Knepley 6099b0fe842aSMatthew G. Knepley Collective 6100b0fe842aSMatthew G. Knepley 6101b0fe842aSMatthew G. Knepley Input Parameters: 6102b0fe842aSMatthew G. Knepley + comm - The communicator 6103b0fe842aSMatthew G. Knepley . dim - The topological dimension of the mesh 6104b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 6105b0fe842aSMatthew G. Knepley . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 6106b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DECIDE` 6107b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 6108b0fe842aSMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6109b0fe842aSMatthew G. Knepley . cells - An array of the global vertex numbers for each cell 6110b0fe842aSMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 6111b0fe842aSMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6112b0fe842aSMatthew G. Knepley 6113b0fe842aSMatthew G. Knepley Output Parameters: 6114b0fe842aSMatthew G. Knepley + dm - The `DM` 6115b0fe842aSMatthew G. Knepley . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 6116b0fe842aSMatthew G. Knepley - verticesAdj - (Optional) vertex adjacency array 6117b0fe842aSMatthew G. Knepley 6118b0fe842aSMatthew G. Knepley Level: intermediate 6119b0fe842aSMatthew G. Knepley 6120b0fe842aSMatthew G. Knepley Notes: 6121b0fe842aSMatthew G. Knepley This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 6122b0fe842aSMatthew G. Knepley `DMPlexBuildFromCellSectionParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 6123b0fe842aSMatthew G. Knepley 6124b0fe842aSMatthew G. Knepley See `DMPlexBuildFromCellSectionParallel()` for an example and details about the topology-related parameters. 6125b0fe842aSMatthew G. Knepley 6126b0fe842aSMatthew G. Knepley See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 6127b0fe842aSMatthew G. Knepley 6128b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 6129b0fe842aSMatthew G. Knepley @*/ 6130ce78bad3SBarry 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) 6131b0fe842aSMatthew G. Knepley { 6132b0fe842aSMatthew G. Knepley PetscSF sfVert; 6133b0fe842aSMatthew G. Knepley 6134b0fe842aSMatthew G. Knepley PetscFunctionBegin; 6135b0fe842aSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 6136b0fe842aSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 6137b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 6138b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 6139b0fe842aSMatthew G. Knepley PetscCall(DMSetDimension(*dm, dim)); 6140b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildFromCellSectionParallel(*dm, numCells, numVertices, NVertices, cellSection, cells, &sfVert, verticesAdj)); 6141b0fe842aSMatthew G. Knepley if (interpolate) { 6142b0fe842aSMatthew G. Knepley DM idm; 6143b0fe842aSMatthew G. Knepley 6144b0fe842aSMatthew G. Knepley PetscCall(DMPlexInterpolate(*dm, &idm)); 6145b0fe842aSMatthew G. Knepley PetscCall(DMDestroy(dm)); 6146b0fe842aSMatthew G. Knepley *dm = idm; 6147b0fe842aSMatthew G. Knepley } 6148b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 6149b0fe842aSMatthew G. Knepley if (vertexSF) *vertexSF = sfVert; 6150b0fe842aSMatthew G. Knepley else PetscCall(PetscSFDestroy(&sfVert)); 6151b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 6152b0fe842aSMatthew G. Knepley } 6153b0fe842aSMatthew G. Knepley 6154b0fe842aSMatthew G. Knepley /*@ 6155a1cb98faSBarry Smith DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) 6156a1cb98faSBarry Smith 615720f4b53cSBarry Smith Collective; No Fortran Support 61589298eaa6SMatthew G Knepley 61599298eaa6SMatthew G Knepley Input Parameters: 6160a1cb98faSBarry Smith + dm - The `DM` 6161b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 6162a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE` 61639298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 6164a3b724e8SBarry Smith - cells - An array of `numCells` x `numCorners` numbers, the global vertex numbers for each cell 61659298eaa6SMatthew G Knepley 6166b09969d6SVaclav Hapla Level: advanced 61679298eaa6SMatthew G Knepley 6168b09969d6SVaclav Hapla Notes: 6169b09969d6SVaclav Hapla Two triangles sharing a face 6170a1cb98faSBarry Smith .vb 61719298eaa6SMatthew G Knepley 6172a1cb98faSBarry Smith 2 6173a1cb98faSBarry Smith / | \ 6174a1cb98faSBarry Smith / | \ 6175a1cb98faSBarry Smith / | \ 6176a1cb98faSBarry Smith 0 0 | 1 3 6177a1cb98faSBarry Smith \ | / 6178a1cb98faSBarry Smith \ | / 6179a1cb98faSBarry Smith \ | / 6180a1cb98faSBarry Smith 1 6181a1cb98faSBarry Smith .ve 6182a1cb98faSBarry Smith would have input 6183a1cb98faSBarry Smith .vb 6184a1cb98faSBarry Smith numCells = 2, numVertices = 4 6185a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 6186a1cb98faSBarry Smith .ve 6187a1cb98faSBarry Smith which would result in the `DMPLEX` 6188a1cb98faSBarry Smith .vb 6189a1cb98faSBarry Smith 6190a1cb98faSBarry Smith 4 6191a1cb98faSBarry Smith / | \ 6192a1cb98faSBarry Smith / | \ 6193a1cb98faSBarry Smith / | \ 6194a1cb98faSBarry Smith 2 0 | 1 5 6195a1cb98faSBarry Smith \ | / 6196a1cb98faSBarry Smith \ | / 6197a1cb98faSBarry Smith \ | / 6198a1cb98faSBarry Smith 3 6199a1cb98faSBarry Smith .ve 6200a1cb98faSBarry Smith 6201a1cb98faSBarry Smith If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1. 620225b6865aSVaclav Hapla 62031cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 6204b09969d6SVaclav Hapla @*/ 6205d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 6206d71ae5a4SJacob Faibussowitsch { 6207961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 6208b09969d6SVaclav Hapla 6209b09969d6SVaclav Hapla PetscFunctionBegin; 62109566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 62119566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 621225b6865aSVaclav Hapla /* Get/check global number of vertices */ 621325b6865aSVaclav Hapla { 621425b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 621525b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 621625b6865aSVaclav Hapla 621725b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 62181690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 62199371c9d4SSatish Balay for (i = 0; i < len; i++) 62209371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 622125b6865aSVaclav Hapla ++NVerticesInCells; 622225b6865aSVaclav Hapla 622325b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 62249371c9d4SSatish Balay else 62259371c9d4SSatish 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); 622625b6865aSVaclav Hapla } 62279566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 622848a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 62299566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 62309566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 6231b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 6232ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 6233b09969d6SVaclav Hapla } 62349566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 62359566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 62369566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 62373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6238b09969d6SVaclav Hapla } 6239b09969d6SVaclav Hapla 6240cc4c1da9SBarry Smith /*@ 6241a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 6242a1cb98faSBarry Smith 6243cc4c1da9SBarry Smith Collective 6244b09969d6SVaclav Hapla 6245b09969d6SVaclav Hapla Input Parameters: 6246a1cb98faSBarry Smith + dm - The `DM` 6247b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6248b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6249b09969d6SVaclav Hapla 6250b09969d6SVaclav Hapla Level: advanced 6251b09969d6SVaclav Hapla 62521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 6253b09969d6SVaclav Hapla @*/ 6254d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 6255d71ae5a4SJacob Faibussowitsch { 6256b09969d6SVaclav Hapla PetscSection coordSection; 6257b09969d6SVaclav Hapla Vec coordinates; 6258b09969d6SVaclav Hapla DM cdm; 6259b09969d6SVaclav Hapla PetscScalar *coords; 62601edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 6261b09969d6SVaclav Hapla 6262b09969d6SVaclav Hapla PetscFunctionBegin; 62639566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 62649566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 62651dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 62669566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 62679566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 62689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 62699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 62709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 62711edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 62729566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 62739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 6274b09969d6SVaclav Hapla } 62759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6276b09969d6SVaclav Hapla 62779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 62789566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 62799566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 62809566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 62819566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 62821edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 6283ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 6284b09969d6SVaclav Hapla } 62859566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 62869566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 62879566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 62889566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 62893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6290b09969d6SVaclav Hapla } 6291b09969d6SVaclav Hapla 6292b09969d6SVaclav Hapla /*@ 6293a1cb98faSBarry Smith DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 62943df08285SMatthew G. Knepley 6295a1cb98faSBarry Smith Collective 6296b09969d6SVaclav Hapla 6297b09969d6SVaclav Hapla Input Parameters: 6298b09969d6SVaclav Hapla + comm - The communicator 6299b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 63003df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 6301a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0 63023df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 6303b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6304ce78bad3SBarry Smith . cells - An array of $ numCells \times numCorners$ numbers, the vertices for each cell, only on process 0 6305b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6306ce78bad3SBarry Smith - vertexCoords - An array of $ numVertices \times spaceDim$ numbers, the coordinates of each vertex, only on process 0 6307b09969d6SVaclav Hapla 6308b09969d6SVaclav Hapla Output Parameter: 6309a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0 631025b6865aSVaclav Hapla 6311b09969d6SVaclav Hapla Level: intermediate 6312b09969d6SVaclav Hapla 6313a1cb98faSBarry Smith Notes: 6314a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`, 6315a1cb98faSBarry Smith `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()` 6316a1cb98faSBarry Smith 6317a1cb98faSBarry Smith See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters. 6318a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters. 6319a1cb98faSBarry Smith See `DMPlexCreateFromCellListParallelPetsc()` for parallel input 6320a1cb98faSBarry Smith 63211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 63229298eaa6SMatthew G Knepley @*/ 6323d71ae5a4SJacob 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) 6324d71ae5a4SJacob Faibussowitsch { 63253df08285SMatthew G. Knepley PetscMPIInt rank; 63269298eaa6SMatthew G Knepley 63279298eaa6SMatthew G Knepley PetscFunctionBegin; 632828b400f6SJacob 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."); 63299566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 63309566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 63319566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 63329566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 6333c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 63349566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 63359298eaa6SMatthew G Knepley if (interpolate) { 63365fd9971aSMatthew G. Knepley DM idm; 63379298eaa6SMatthew G Knepley 63389566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 63399566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 63409298eaa6SMatthew G Knepley *dm = idm; 63419298eaa6SMatthew G Knepley } 6342c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 63439566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 63443ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 63459298eaa6SMatthew G Knepley } 63469298eaa6SMatthew G Knepley 6347939f6067SMatthew G. Knepley /*@ 634820f4b53cSBarry Smith DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a `DM` 6349939f6067SMatthew G. Knepley 6350939f6067SMatthew G. Knepley Input Parameters: 635120f4b53cSBarry Smith + dm - The empty `DM` object, usually from `DMCreate()` and `DMSetDimension()` 6352939f6067SMatthew G. Knepley . depth - The depth of the DAG 6353ce78bad3SBarry Smith . numPoints - Array of size $ depth + 1 $ containing the number of points at each `depth` 6354939f6067SMatthew G. Knepley . coneSize - The cone size of each point 6355939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 6356939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 6357ce78bad3SBarry Smith - vertexCoords - An array of $ numPoints[0] \times spacedim $ numbers representing the coordinates of each vertex, with `spacedim` the value set via `DMSetCoordinateDim()` 6358939f6067SMatthew G. Knepley 6359939f6067SMatthew G. Knepley Output Parameter: 636020f4b53cSBarry Smith . dm - The `DM` 636120f4b53cSBarry Smith 636220f4b53cSBarry Smith Level: advanced 6363939f6067SMatthew G. Knepley 6364a1cb98faSBarry Smith Note: 6365a1cb98faSBarry Smith Two triangles sharing a face would have input 6366a1cb98faSBarry Smith .vb 6367a1cb98faSBarry Smith depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 6368a1cb98faSBarry Smith cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 6369a1cb98faSBarry Smith vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 6370a1cb98faSBarry Smith .ve 6371939f6067SMatthew G. Knepley which would result in the DMPlex 6372a1cb98faSBarry Smith .vb 6373a1cb98faSBarry Smith 4 6374a1cb98faSBarry Smith / | \ 6375a1cb98faSBarry Smith / | \ 6376a1cb98faSBarry Smith / | \ 6377a1cb98faSBarry Smith 2 0 | 1 5 6378a1cb98faSBarry Smith \ | / 6379a1cb98faSBarry Smith \ | / 6380a1cb98faSBarry Smith \ | / 6381a1cb98faSBarry Smith 3 6382a1cb98faSBarry Smith .ve 6383a1cb98faSBarry Smith Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()` 6384939f6067SMatthew G. Knepley 6385ce78bad3SBarry Smith Developer Note: 6386ce78bad3SBarry Smith This does not create anything so should not have create in the name. 6387ce78bad3SBarry Smith 63881cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 6389939f6067SMatthew G. Knepley @*/ 6390d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 6391d71ae5a4SJacob Faibussowitsch { 63929298eaa6SMatthew G Knepley Vec coordinates; 63939298eaa6SMatthew G Knepley PetscSection coordSection; 63949298eaa6SMatthew G Knepley PetscScalar *coords; 6395811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 63969298eaa6SMatthew G Knepley 63979298eaa6SMatthew G Knepley PetscFunctionBegin; 63989566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 63999566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 640063a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 64019298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 64029566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 64039298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 64049566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 6405ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 640697e052ccSToby Isaac } 64071dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 64089566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 64099298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 64109566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 64119566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 64129298eaa6SMatthew G Knepley } 64139566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 64149566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 64159298eaa6SMatthew G Knepley /* Build coordinates */ 64169566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 64179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 64189566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 64199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 64209298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 64219566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 64229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 64239298eaa6SMatthew G Knepley } 64249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 64259566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 64269566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 64279566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 64289566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 64299566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dimEmbed)); 64309566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 64319318fe57SMatthew G. Knepley if (vertexCoords) { 64329566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 64339298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 64349298eaa6SMatthew G Knepley PetscInt off; 64359298eaa6SMatthew G Knepley 64369566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 6437ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 64389298eaa6SMatthew G Knepley } 64399318fe57SMatthew G. Knepley } 64409566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 64419566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 64429566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 64433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 64449298eaa6SMatthew G Knepley } 64458415267dSToby Isaac 6446a4e35b19SJacob Faibussowitsch /* 6447a1cb98faSBarry Smith DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file. 6448a1cb98faSBarry Smith 6449a1cb98faSBarry Smith Collective 64508ca92349SMatthew G. Knepley 64518ca92349SMatthew G. Knepley + comm - The MPI communicator 64528ca92349SMatthew G. Knepley . filename - Name of the .dat file 64538ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 64548ca92349SMatthew G. Knepley 64558ca92349SMatthew G. Knepley Output Parameter: 6456a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 64578ca92349SMatthew G. Knepley 64588ca92349SMatthew G. Knepley Level: beginner 64598ca92349SMatthew G. Knepley 6460a1cb98faSBarry Smith Note: 6461a1cb98faSBarry Smith The format is the simplest possible: 6462a1cb98faSBarry Smith .vb 6463d0812dedSMatthew G. Knepley dim Ne Nv Nc Nl 6464d0812dedSMatthew G. Knepley v_1 v_2 ... v_Nc 6465d0812dedSMatthew G. Knepley ... 6466d0812dedSMatthew G. Knepley x y z marker_1 ... marker_Nl 6467a1cb98faSBarry Smith .ve 6468a1cb98faSBarry Smith 6469a1cb98faSBarry Smith Developer Note: 6470a1cb98faSBarry Smith Should use a `PetscViewer` not a filename 6471a1cb98faSBarry Smith 64726afe31f6SMartin Diehl .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 6473a4e35b19SJacob Faibussowitsch */ 6474ff6a9541SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 6475d71ae5a4SJacob Faibussowitsch { 64768ca92349SMatthew G. Knepley DMLabel marker; 64778ca92349SMatthew G. Knepley PetscViewer viewer; 64788ca92349SMatthew G. Knepley Vec coordinates; 64798ca92349SMatthew G. Knepley PetscSection coordSection; 64808ca92349SMatthew G. Knepley PetscScalar *coords; 64818ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 6482d0812dedSMatthew G. Knepley PetscInt cdim, coordSize, v, c, d; 64838ca92349SMatthew G. Knepley PetscMPIInt rank; 6484d0812dedSMatthew G. Knepley int snum, dim, Nv, Nc, Ncn, Nl; 64858ca92349SMatthew G. Knepley 64868ca92349SMatthew G. Knepley PetscFunctionBegin; 64879566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 64889566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 64899566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 64909566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 64919566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 6492dd400576SPatrick Sanan if (rank == 0) { 6493d0812dedSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING)); 6494d0812dedSMatthew G. Knepley snum = sscanf(line, "%d %d %d %d %d", &dim, &Nc, &Nv, &Ncn, &Nl); 6495d0812dedSMatthew G. Knepley PetscCheck(snum == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 649625ce1634SJed Brown } else { 6497f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 64988ca92349SMatthew G. Knepley } 6499d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm)); 6500835f2295SStefano Zampini cdim = dim; 65019566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 65029566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 65039566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 6504835f2295SStefano Zampini PetscCall(DMSetDimension(*dm, dim)); 65059566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 65068ca92349SMatthew G. Knepley /* Read topology */ 6507dd400576SPatrick Sanan if (rank == 0) { 6508f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 6509f8d5e320SMatthew G. Knepley PetscInt cone[8]; 65108ca92349SMatthew G. Knepley int vbuf[8], v; 65118ca92349SMatthew G. Knepley 65129371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 65139371c9d4SSatish Balay format[c * 3 + 0] = '%'; 65149371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 65159371c9d4SSatish Balay format[c * 3 + 2] = ' '; 65169371c9d4SSatish Balay } 6517f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 65189566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 65199566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 65208ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 65219566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 6522f8d5e320SMatthew G. Knepley switch (Ncn) { 6523d71ae5a4SJacob Faibussowitsch case 2: 6524d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1]); 6525d71ae5a4SJacob Faibussowitsch break; 6526d71ae5a4SJacob Faibussowitsch case 3: 6527d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); 6528d71ae5a4SJacob Faibussowitsch break; 6529d71ae5a4SJacob Faibussowitsch case 4: 6530d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); 6531d71ae5a4SJacob Faibussowitsch break; 6532d71ae5a4SJacob Faibussowitsch case 6: 6533d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); 6534d71ae5a4SJacob Faibussowitsch break; 6535d71ae5a4SJacob Faibussowitsch case 8: 6536d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 6537d71ae5a4SJacob Faibussowitsch break; 6538d71ae5a4SJacob Faibussowitsch default: 6539d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 6540f8d5e320SMatthew G. Knepley } 654108401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6542f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 65438ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 6544f8d5e320SMatthew G. Knepley if (Ncn == 8) { 65458ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 65468ca92349SMatthew G. Knepley cone[1] = cone[3]; 65478ca92349SMatthew G. Knepley cone[3] = tmp; 65488ca92349SMatthew G. Knepley } 65499566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 65508ca92349SMatthew G. Knepley } 65518ca92349SMatthew G. Knepley } 65529566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 65539566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 65548ca92349SMatthew G. Knepley /* Read coordinates */ 65559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 65569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 65579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 65589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 65598ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 65609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 65619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 65628ca92349SMatthew G. Knepley } 65639566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 65649566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 65659566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 65669566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 65679566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 65689566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 65699566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 65709566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6571dd400576SPatrick Sanan if (rank == 0) { 6572f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 65738ca92349SMatthew G. Knepley double x[3]; 6574f8d5e320SMatthew G. Knepley int l, val[3]; 65758ca92349SMatthew G. Knepley 6576f8d5e320SMatthew G. Knepley if (Nl) { 65779371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 65789371c9d4SSatish Balay format[l * 3 + 0] = '%'; 65799371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 65809371c9d4SSatish Balay format[l * 3 + 2] = ' '; 65819371c9d4SSatish Balay } 6582f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 65839566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 65849566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 6585f8d5e320SMatthew G. Knepley } 65868ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 65879566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 6588f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 658908401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6590f8d5e320SMatthew G. Knepley switch (Nl) { 6591d71ae5a4SJacob Faibussowitsch case 0: 6592d71ae5a4SJacob Faibussowitsch snum = 0; 6593d71ae5a4SJacob Faibussowitsch break; 6594d71ae5a4SJacob Faibussowitsch case 1: 6595d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0]); 6596d71ae5a4SJacob Faibussowitsch break; 6597d71ae5a4SJacob Faibussowitsch case 2: 6598d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1]); 6599d71ae5a4SJacob Faibussowitsch break; 6600d71ae5a4SJacob Faibussowitsch case 3: 6601d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1], &val[2]); 6602d71ae5a4SJacob Faibussowitsch break; 6603d71ae5a4SJacob Faibussowitsch default: 6604d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 6605f8d5e320SMatthew G. Knepley } 660608401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 66078ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 66089566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 66098ca92349SMatthew G. Knepley } 66108ca92349SMatthew G. Knepley } 66119566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 66129566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 66139566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 66149566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 66158ca92349SMatthew G. Knepley if (interpolate) { 66168ca92349SMatthew G. Knepley DM idm; 66178ca92349SMatthew G. Knepley DMLabel bdlabel; 66188ca92349SMatthew G. Knepley 66199566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 66209566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 66218ca92349SMatthew G. Knepley *dm = idm; 66228ca92349SMatthew G. Knepley 6623f8d5e320SMatthew G. Knepley if (!Nl) { 66249566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 66259566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 66269566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 66279566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 66288ca92349SMatthew G. Knepley } 6629f8d5e320SMatthew G. Knepley } 66303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 66318ca92349SMatthew G. Knepley } 66328ca92349SMatthew G. Knepley 6633cc4c1da9SBarry Smith /*@ 6634a1cb98faSBarry Smith DMPlexCreateFromFile - This takes a filename and produces a `DM` 6635a1cb98faSBarry Smith 6636a1cb98faSBarry Smith Collective 6637ca522641SMatthew G. Knepley 6638ca522641SMatthew G. Knepley Input Parameters: 6639ca522641SMatthew G. Knepley + comm - The communicator 6640ca522641SMatthew G. Knepley . filename - A file name 6641a1cb98faSBarry Smith . plexname - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats 6642ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 6643ca522641SMatthew G. Knepley 6644ca522641SMatthew G. Knepley Output Parameter: 6645a1cb98faSBarry Smith . dm - The `DM` 6646ca522641SMatthew G. Knepley 6647a1cb98faSBarry Smith Options Database Key: 6648a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5 664902ef0d99SVaclav Hapla 665037fdd005SBarry Smith Use `-dm_plex_create_ prefix` to pass options to the internal `PetscViewer`, e.g. 6651bca97951SVaclav Hapla $ -dm_plex_create_viewer_hdf5_collective 6652bca97951SVaclav Hapla 6653ca522641SMatthew G. Knepley Level: beginner 6654ca522641SMatthew G. Knepley 6655a1cb98faSBarry Smith Notes: 6656a1cb98faSBarry Smith Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX` 6657a1cb98faSBarry Smith meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()` 6658a1cb98faSBarry Smith before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object. 6659a1cb98faSBarry Smith The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally 6660a1cb98faSBarry Smith calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats. 6661a1cb98faSBarry Smith 66621cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 6663ca522641SMatthew G. Knepley @*/ 6664d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 6665d71ae5a4SJacob Faibussowitsch { 6666ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 6667ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 6668ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 6669ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 6670ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 6671ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 6672ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 6673ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 6674ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 66756f2c871aSStefano Zampini const char extXDMFHDF5[] = ".xdmf.h5"; 6676ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 66775552b385SBrandon const char extEGADSlite[] = ".egadslite"; 6678ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 6679ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 66805552b385SBrandon const char extIGES2[] = ".iges"; 6681ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 66825552b385SBrandon const char extSTEP2[] = ".step"; 66835552b385SBrandon const char extBREP[] = ".brep"; 6684ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 6685ca522641SMatthew G. Knepley size_t len; 66865552b385SBrandon PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isPLY, isEGADSlite, isEGADS, isIGES, isIGES2, isSTEP, isSTEP2, isBREP, isCV, isXDMFHDF5; 6687ca522641SMatthew G. Knepley PetscMPIInt rank; 6688ca522641SMatthew G. Knepley 6689ca522641SMatthew G. Knepley PetscFunctionBegin; 66904f572ea9SToby Isaac PetscAssertPointer(filename, 2); 66914f572ea9SToby Isaac if (plexname) PetscAssertPointer(plexname, 3); 66924f572ea9SToby Isaac PetscAssertPointer(dm, 5); 66939566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 66949566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 66959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 66969566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 669728b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 6698ef3a5affSJacob Faibussowitsch 66999371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 67009371c9d4SSatish Balay do { \ 6701274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 6702274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 6703274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 6704274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 6705ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 6706ef3a5affSJacob Faibussowitsch } else { \ 6707274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 6708ef3a5affSJacob Faibussowitsch } \ 6709ef3a5affSJacob Faibussowitsch } while (0) 6710ef3a5affSJacob Faibussowitsch 6711ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 6712ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 6713ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 6714ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 6715ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 6716ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 6717ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 6718ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 6719ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 6720ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 67215552b385SBrandon CheckExtension(extEGADSlite, isEGADSlite); 6722ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 6723ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 67245552b385SBrandon CheckExtension(extIGES2, isIGES2); 6725ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 67265552b385SBrandon CheckExtension(extSTEP2, isSTEP2); 67275552b385SBrandon CheckExtension(extBREP, isBREP); 6728ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 67296f2c871aSStefano Zampini CheckExtension(extXDMFHDF5, isXDMFHDF5); 6730ef3a5affSJacob Faibussowitsch 6731ef3a5affSJacob Faibussowitsch #undef CheckExtension 6732ef3a5affSJacob Faibussowitsch 6733de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 67349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 6735ca522641SMatthew G. Knepley } else if (isCGNS) { 67369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 673790c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 67389566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 67392f0bd6dcSMichael Lange } else if (isFluent) { 67409566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 6741cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 6742cc2f8f65SMatthew G. Knepley PetscViewer viewer; 6743cc2f8f65SMatthew G. Knepley 674443b242b4SVaclav 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 */ 67456f2c871aSStefano Zampini PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &isXDMFHDF5, NULL)); 67469566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 67479566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 67489566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 67499566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 67509566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 67519566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 6752cd7e8a5eSksagiyam 67539566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 6754f4f49eeaSPierre Jolivet PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 67559566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 67566f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 67579566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 67586f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPopFormat(viewer)); 67599566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 67605fd9971aSMatthew G. Knepley 67615fd9971aSMatthew G. Knepley if (interpolate) { 67625fd9971aSMatthew G. Knepley DM idm; 67635fd9971aSMatthew G. Knepley 67649566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 67659566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 67665fd9971aSMatthew G. Knepley *dm = idm; 67675fd9971aSMatthew G. Knepley } 6768f2801cd6SMatthew G. Knepley } else if (isPLY) { 67699566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 67705552b385SBrandon } else if (isEGADSlite || isEGADS || isIGES || isIGES2 || isSTEP || isSTEP2 || isBREP) { 67715552b385SBrandon PetscCall(DMPlexCreateGeomFromFile(comm, filename, dm, isEGADSlite)); 67725552b385SBrandon 67737bee2925SMatthew Knepley if (!interpolate) { 67747bee2925SMatthew Knepley DM udm; 67757bee2925SMatthew Knepley 67769566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 67779566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 67787bee2925SMatthew Knepley *dm = udm; 67797bee2925SMatthew Knepley } 67808ca92349SMatthew G. Knepley } else if (isCV) { 67819566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 678298921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 67839566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 6784f4f49eeaSPierre Jolivet if (len) PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 67859566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 67863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6787ca522641SMatthew G. Knepley } 678812b8a6daSStefano Zampini 6789cc4c1da9SBarry Smith /*@ 67909f6c5813SMatthew 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. 67919f6c5813SMatthew G. Knepley 67920528010dSStefano Zampini Input Parameters: 67930528010dSStefano Zampini + tr - The `DMPlexTransform` 67940528010dSStefano Zampini - prefix - An options prefix, or NULL 67959f6c5813SMatthew G. Knepley 67969f6c5813SMatthew G. Knepley Output Parameter: 67979f6c5813SMatthew G. Knepley . dm - The `DM` 67989f6c5813SMatthew G. Knepley 67999f6c5813SMatthew G. Knepley Level: beginner 68009f6c5813SMatthew G. Knepley 680120f4b53cSBarry Smith Notes: 680220f4b53cSBarry 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. 680320f4b53cSBarry Smith 68049f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 68059f6c5813SMatthew G. Knepley @*/ 68060528010dSStefano Zampini PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, const char prefix[], DM *dm) 68079f6c5813SMatthew G. Knepley { 68080528010dSStefano Zampini DM bdm, bcdm, cdm; 68090528010dSStefano Zampini Vec coordinates, coordinatesNew; 68100528010dSStefano Zampini PetscSection cs; 6811817b2c36SMatthew G. Knepley PetscInt cdim, Nl; 68129f6c5813SMatthew G. Knepley 68139f6c5813SMatthew G. Knepley PetscFunctionBegin; 68149f6c5813SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm)); 68159f6c5813SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 68160528010dSStefano Zampini ((DM_Plex *)(*dm)->data)->interpolated = DMPLEX_INTERPOLATED_FULL; 68170528010dSStefano Zampini // Handle coordinates 68180528010dSStefano Zampini PetscCall(DMPlexTransformGetDM(tr, &bdm)); 6819817b2c36SMatthew G. Knepley PetscCall(DMPlexTransformSetDimensions(tr, bdm, *dm)); 6820817b2c36SMatthew G. Knepley PetscCall(DMGetCoordinateDim(*dm, &cdim)); 68210528010dSStefano Zampini PetscCall(DMGetCoordinateDM(bdm, &bcdm)); 68220528010dSStefano Zampini PetscCall(DMGetCoordinateDM(*dm, &cdm)); 68230528010dSStefano Zampini PetscCall(DMCopyDisc(bcdm, cdm)); 68240528010dSStefano Zampini PetscCall(DMGetLocalSection(cdm, &cs)); 68250528010dSStefano Zampini PetscCall(PetscSectionSetNumFields(cs, 1)); 68260528010dSStefano Zampini PetscCall(PetscSectionSetFieldComponents(cs, 0, cdim)); 68270528010dSStefano Zampini PetscCall(DMGetCoordinatesLocal(bdm, &coordinates)); 68280528010dSStefano Zampini PetscCall(VecDuplicate(coordinates, &coordinatesNew)); 68290528010dSStefano Zampini PetscCall(VecCopy(coordinates, coordinatesNew)); 68300528010dSStefano Zampini PetscCall(DMSetCoordinatesLocal(*dm, coordinatesNew)); 68310528010dSStefano Zampini PetscCall(VecDestroy(&coordinatesNew)); 68329f6c5813SMatthew G. Knepley 68339f6c5813SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)tr)); 68349f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr)); 68359f6c5813SMatthew G. Knepley ((DM_Plex *)(*dm)->data)->tr = tr; 68360528010dSStefano Zampini PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE)); 68370528010dSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix)); 68380528010dSStefano Zampini PetscCall(DMSetFromOptions(*dm)); 68399f6c5813SMatthew G. Knepley 68409f6c5813SMatthew G. Knepley PetscCall(DMGetNumLabels(bdm, &Nl)); 68419f6c5813SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 68429f6c5813SMatthew G. Knepley DMLabel label, labelNew; 68439f6c5813SMatthew G. Knepley const char *lname; 68449f6c5813SMatthew G. Knepley PetscBool isDepth, isCellType; 68459f6c5813SMatthew G. Knepley 68469f6c5813SMatthew G. Knepley PetscCall(DMGetLabelName(bdm, l, &lname)); 68479f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 68489f6c5813SMatthew G. Knepley if (isDepth) continue; 68499f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "celltype", &isCellType)); 68509f6c5813SMatthew G. Knepley if (isCellType) continue; 68519f6c5813SMatthew G. Knepley PetscCall(DMCreateLabel(*dm, lname)); 68529f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(bdm, lname, &label)); 68539f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(*dm, lname, &labelNew)); 68549f6c5813SMatthew G. Knepley PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL)); 68559f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetLabel(labelNew, label)); 68569f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetTransform(labelNew, tr)); 68579f6c5813SMatthew G. Knepley PetscCall(DMLabelSetUp(labelNew)); 68589f6c5813SMatthew G. Knepley } 68593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68609f6c5813SMatthew G. Knepley } 6861