1af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2cc4c1da9SBarry Smith #include <petsc/private/hashseti.h> 30c312b8eSJed Brown #include <petscsf.h> 4cc4c1da9SBarry Smith #include <petscdmplextransform.h> /*I "petscdmplextransform.h" I*/ 59f6c5813SMatthew G. Knepley #include <petscdmlabelephemeral.h> 6b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h> 7b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h> 8552f7358SJed Brown 9d0812dedSMatthew G. Knepley #ifdef PETSC_HAVE_UNISTD_H 10d0812dedSMatthew G. Knepley #include <unistd.h> 11d0812dedSMatthew G. Knepley #endif 12d0812dedSMatthew G. Knepley #include <errno.h> 13d0812dedSMatthew G. Knepley 14708be2fdSJed Brown PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_CreateFromOptions, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList; 1558cd63d5SVaclav Hapla 169318fe57SMatthew G. Knepley /* External function declarations here */ 179318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm); 189318fe57SMatthew G. Knepley 195552b385SBrandon PETSC_EXTERN PetscErrorCode DMPlexCheckEGADS_Private(DM dm) 205552b385SBrandon { 215552b385SBrandon PetscObject modelObj; 225552b385SBrandon 235552b385SBrandon PetscFunctionBegin; 245552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", &modelObj)); 255552b385SBrandon PetscCheck(modelObj, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Input DM must have attached EGADS Geometry Model"); 265552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 275552b385SBrandon } 285552b385SBrandon 295552b385SBrandon static PetscErrorCode DMPlexCopyContext_Private(DM dmin, const char name[], DM dmout) 305552b385SBrandon { 315552b385SBrandon PetscObject obj; 325552b385SBrandon 335552b385SBrandon PetscFunctionBegin; 345552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmin, name, &obj)); 355552b385SBrandon if (obj) PetscCall(PetscObjectCompose((PetscObject)dmout, name, obj)); 365552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 375552b385SBrandon } 385552b385SBrandon 395552b385SBrandon static PetscErrorCode DMPlexSwapContext_Private(DM dmA, const char name[], DM dmB) 405552b385SBrandon { 415552b385SBrandon PetscObject objA, objB; 425552b385SBrandon 435552b385SBrandon PetscFunctionBegin; 445552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmA, name, &objA)); 455552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmB, name, &objB)); 465552b385SBrandon PetscCall(PetscObjectReference(objA)); 475552b385SBrandon PetscCall(PetscObjectReference(objB)); 485552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dmA, name, objB)); 495552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dmB, name, objA)); 505552b385SBrandon PetscCall(PetscObjectDereference(objA)); 515552b385SBrandon PetscCall(PetscObjectDereference(objB)); 525552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 535552b385SBrandon } 545552b385SBrandon 555552b385SBrandon PetscErrorCode DMPlexCopyEGADSInfo_Internal(DM dmin, DM dmout) 565552b385SBrandon { 575552b385SBrandon PetscFunctionBegin; 585552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Model", dmout)); 595552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Context", dmout)); 605552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Model", dmout)); 615552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Context", dmout)); 625552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 635552b385SBrandon } 645552b385SBrandon 655552b385SBrandon static PetscErrorCode DMPlexSwapEGADSInfo_Private(DM dmA, DM dmB) 665552b385SBrandon { 675552b385SBrandon PetscFunctionBegin; 685552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Model", dmB)); 695552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Context", dmB)); 705552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Model", dmB)); 715552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Context", dmB)); 725552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 735552b385SBrandon } 745552b385SBrandon 75e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */ 76d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout) 77d71ae5a4SJacob Faibussowitsch { 784fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 7912a88998SMatthew G. Knepley VecType vecType; 8012a88998SMatthew G. Knepley MatType matType; 81129f447cSJames Wright PetscBool dist, useCeed, balance_partition; 82adc21957SMatthew G. Knepley DMReorderDefaultFlag reorder; 83e600fa54SMatthew G. Knepley 84e600fa54SMatthew G. Knepley PetscFunctionBegin; 85835f2295SStefano Zampini if (dmin == dmout) PetscFunctionReturn(PETSC_SUCCESS); 8612a88998SMatthew G. Knepley PetscCall(DMGetVecType(dmin, &vecType)); 8712a88998SMatthew G. Knepley PetscCall(DMSetVecType(dmout, vecType)); 8812a88998SMatthew G. Knepley PetscCall(DMGetMatType(dmin, &matType)); 8912a88998SMatthew G. Knepley PetscCall(DMSetMatType(dmout, matType)); 90e600fa54SMatthew G. Knepley if (copyPeriodicity) { 914fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L)); 924fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L)); 933d0e8ed9SDavid Salac PetscCall(DMLocalizeCoordinates(dmout)); 94e600fa54SMatthew G. Knepley } 959566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dmin, &dist)); 969566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dmout, dist)); 976bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dmin, &reorder)); 986bc1bd01Sksagiyam PetscCall(DMPlexReorderSetDefault(dmout, reorder)); 995962854dSMatthew G. Knepley PetscCall(DMPlexGetUseCeed(dmin, &useCeed)); 1005962854dSMatthew G. Knepley PetscCall(DMPlexSetUseCeed(dmout, useCeed)); 101129f447cSJames Wright PetscCall(DMPlexGetPartitionBalance(dmin, &balance_partition)); 102129f447cSJames Wright PetscCall(DMPlexSetPartitionBalance(dmout, balance_partition)); 103e600fa54SMatthew G. Knepley ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation; 1045962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printSetValues = ((DM_Plex *)dmin->data)->printSetValues; 1055962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printFEM = ((DM_Plex *)dmin->data)->printFEM; 1065962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printFVM = ((DM_Plex *)dmin->data)->printFVM; 1075962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printL2 = ((DM_Plex *)dmin->data)->printL2; 1085962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printLocate = ((DM_Plex *)dmin->data)->printLocate; 109a77a5016SMatthew G. Knepley ((DM_Plex *)dmout->data)->printProject = ((DM_Plex *)dmin->data)->printProject; 1105962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printTol = ((DM_Plex *)dmin->data)->printTol; 1111baa6e33SBarry Smith if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0)); 1125552b385SBrandon PetscCall(DMPlexCopyEGADSInfo_Internal(dmin, dmout)); 1133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 114e600fa54SMatthew G. Knepley } 115e600fa54SMatthew G. Knepley 1169318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 1179318fe57SMatthew G. Knepley - Share the DM_Plex structure 1189318fe57SMatthew G. Knepley - Share the coordinates 1199318fe57SMatthew G. Knepley - Share the SF 1209318fe57SMatthew G. Knepley */ 121d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm) 122d71ae5a4SJacob Faibussowitsch { 1239318fe57SMatthew G. Knepley PetscSF sf; 1249318fe57SMatthew G. Knepley DM dmNew = *ndm, coordDM, coarseDM; 1259318fe57SMatthew G. Knepley Vec coords; 1262192575eSBarry Smith PetscPointFn *coordFunc; 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 } 1433674be70SMatthew G. Knepley { 1443674be70SMatthew G. Knepley PetscInt ndim; 1453674be70SMatthew G. Knepley 1463674be70SMatthew G. Knepley // If topological dimensions are the same, we retain the old coordinate map, 1473674be70SMatthew G. Knepley // otherwise we overwrite with the new one 1483674be70SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 1493674be70SMatthew G. Knepley PetscCall(DMGetDimension(dmNew, &ndim)); 1503674be70SMatthew G. Knepley PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc)); 1513674be70SMatthew G. Knepley if (dim == ndim) PetscCall(DMPlexSetCoordinateMap(dmNew, coordFunc)); 1523674be70SMatthew G. Knepley } 1539566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dmNew, &dim)); 1549566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 1559566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmNew, &cdim)); 1569566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 1579566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmNew, &sf)); 1589566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sf)); 1599566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmNew, &coordDM)); 1609566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmNew, &coords)); 1619566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dm, coordDM)); 1629566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 1636858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM)); 1646858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords)); 1656858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dm, coordDM)); 1666858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 1679318fe57SMatthew G. Knepley /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */ 1686858538eSMatthew G. Knepley PetscCall(DMFieldDestroy(&dm->coordinates[0].field)); 1696858538eSMatthew G. Knepley dm->coordinates[0].field = dmNew->coordinates[0].field; 1704fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L)); 1714fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 172e535cce4SJames Wright PetscCall(DMGetNaturalSF(dmNew, &sf)); 173e535cce4SJames Wright PetscCall(DMSetNaturalSF(dm, sf)); 174e535cce4SJames Wright PetscCall(DMGetUseNatural(dmNew, &use_natural)); 175e535cce4SJames Wright PetscCall(DMSetUseNatural(dm, use_natural)); 1769566063dSJacob Faibussowitsch PetscCall(DMDestroy_Plex(dm)); 1779566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 1789318fe57SMatthew G. Knepley dm->data = dmNew->data; 1799318fe57SMatthew G. Knepley ((DM_Plex *)dmNew->data)->refct++; 1801fca310dSJames Wright { 1811fca310dSJames Wright PetscInt num_face_sfs; 1821fca310dSJames Wright const PetscSF *sfs; 1831fca310dSJames Wright PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &sfs)); 1841fca310dSJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(dm, num_face_sfs, (PetscSF *)sfs)); // for the compose function effect on dm 1851fca310dSJames Wright } 1869566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 1879566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 1889566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmNew, &coarseDM)); 1899566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 1905552b385SBrandon PetscCall(DMPlexCopyEGADSInfo_Internal(dmNew, dm)); 1919566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 1923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1939318fe57SMatthew G. Knepley } 1949318fe57SMatthew G. Knepley 1959318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew 1969318fe57SMatthew G. Knepley - Swap the DM_Plex structure 1979318fe57SMatthew G. Knepley - Swap the coordinates 1989318fe57SMatthew G. Knepley - Swap the point PetscSF 1999318fe57SMatthew G. Knepley */ 200d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) 201d71ae5a4SJacob Faibussowitsch { 2029318fe57SMatthew G. Knepley DM coordDMA, coordDMB; 2039318fe57SMatthew G. Knepley Vec coordsA, coordsB; 2049318fe57SMatthew G. Knepley PetscSF sfA, sfB; 2059318fe57SMatthew G. Knepley DMField fieldTmp; 2069318fe57SMatthew G. Knepley void *tmp; 2079318fe57SMatthew G. Knepley DMLabelLink listTmp; 2089318fe57SMatthew G. Knepley DMLabel depthTmp; 2099318fe57SMatthew G. Knepley PetscInt tmpI; 2109318fe57SMatthew G. Knepley 2119318fe57SMatthew G. Knepley PetscFunctionBegin; 2123ba16761SJacob Faibussowitsch if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS); 2139566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmA, &sfA)); 2149566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmB, &sfB)); 2159566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sfA)); 2169566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmA, sfB)); 2179566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmB, sfA)); 2189566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)sfA)); 2199318fe57SMatthew G. Knepley 2209566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &coordDMA)); 2219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &coordDMB)); 2229566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordDMA)); 2239566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmA, coordDMB)); 2249566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmB, coordDMA)); 2259566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 2269318fe57SMatthew G. Knepley 2279566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordsA)); 2289566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmB, &coordsB)); 2299566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordsA)); 2309566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmA, coordsB)); 2319566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordsA)); 2329566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordsA)); 2339318fe57SMatthew G. Knepley 2346858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA)); 2356858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB)); 2366858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordDMA)); 2376858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmA, coordDMB)); 2386858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmB, coordDMA)); 2396858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 2406858538eSMatthew G. Knepley 2416858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA)); 2426858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB)); 2436858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordsA)); 2446858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB)); 2456858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA)); 2466858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordsA)); 2476858538eSMatthew G. Knepley 2485552b385SBrandon PetscCall(DMPlexSwapEGADSInfo_Private(dmA, dmB)); 2495552b385SBrandon 2506858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[0].field; 2516858538eSMatthew G. Knepley dmA->coordinates[0].field = dmB->coordinates[0].field; 2526858538eSMatthew G. Knepley dmB->coordinates[0].field = fieldTmp; 2536858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[1].field; 2546858538eSMatthew G. Knepley dmA->coordinates[1].field = dmB->coordinates[1].field; 2556858538eSMatthew G. Knepley dmB->coordinates[1].field = fieldTmp; 2569318fe57SMatthew G. Knepley tmp = dmA->data; 2579318fe57SMatthew G. Knepley dmA->data = dmB->data; 2589318fe57SMatthew G. Knepley dmB->data = tmp; 2599318fe57SMatthew G. Knepley listTmp = dmA->labels; 2609318fe57SMatthew G. Knepley dmA->labels = dmB->labels; 2619318fe57SMatthew G. Knepley dmB->labels = listTmp; 2629318fe57SMatthew G. Knepley depthTmp = dmA->depthLabel; 2639318fe57SMatthew G. Knepley dmA->depthLabel = dmB->depthLabel; 2649318fe57SMatthew G. Knepley dmB->depthLabel = depthTmp; 2659318fe57SMatthew G. Knepley depthTmp = dmA->celltypeLabel; 2669318fe57SMatthew G. Knepley dmA->celltypeLabel = dmB->celltypeLabel; 2679318fe57SMatthew G. Knepley dmB->celltypeLabel = depthTmp; 2689318fe57SMatthew G. Knepley tmpI = dmA->levelup; 2699318fe57SMatthew G. Knepley dmA->levelup = dmB->levelup; 2709318fe57SMatthew G. Knepley dmB->levelup = tmpI; 2713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2729318fe57SMatthew G. Knepley } 2739318fe57SMatthew G. Knepley 2743431e603SJed Brown PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm) 275d71ae5a4SJacob Faibussowitsch { 2769318fe57SMatthew G. Knepley DM idm; 2779318fe57SMatthew G. Knepley 2789318fe57SMatthew G. Knepley PetscFunctionBegin; 2799566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 2809566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 28169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 2823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2839318fe57SMatthew G. Knepley } 2849318fe57SMatthew G. Knepley 2859318fe57SMatthew G. Knepley /*@C 2869318fe57SMatthew G. Knepley DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates 2879318fe57SMatthew G. Knepley 28820f4b53cSBarry Smith Collective 2899318fe57SMatthew G. Knepley 2909318fe57SMatthew G. Knepley Input Parameters: 29160225df5SJacob Faibussowitsch + dm - The `DMPLEX` 29220f4b53cSBarry Smith . degree - The degree of the finite element or `PETSC_DECIDE` 2934c712d99Sksagiyam . localized - Flag to create a localized (DG) coordinate space 294e65c294aSksagiyam - project - Flag to project current coordinates into the space 2959318fe57SMatthew G. Knepley 2969318fe57SMatthew G. Knepley Level: advanced 2979318fe57SMatthew G. Knepley 298e65c294aSksagiyam .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPointFn`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()`, `DMPlexSetCoordinateMap()` 2999318fe57SMatthew G. Knepley @*/ 300e65c294aSksagiyam PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscBool localized, PetscBool project) 301d71ae5a4SJacob Faibussowitsch { 302e44f6aebSMatthew G. Knepley PetscFE fe = NULL; 3039318fe57SMatthew G. Knepley DM cdm; 304ac9d17c7SMatthew G. Knepley PetscInt dim, cdim, dE, qorder, height; 3059318fe57SMatthew G. Knepley 306e44f6aebSMatthew G. Knepley PetscFunctionBegin; 3079566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 308ac9d17c7SMatthew G. Knepley cdim = dim; 3099566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 3109318fe57SMatthew G. Knepley qorder = degree; 311e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 312d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)cdm); 313dc431b0cSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0)); 314ac9d17c7SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_coordinate_dim", "Set the coordinate dimension", "DMPlexCreateCoordinateSpace", cdim, &cdim, NULL, dim)); 315d0609cedSBarry Smith PetscOptionsEnd(); 3161df12153SMatthew G. Knepley PetscCall(DMPlexGetVTKCellHeight(dm, &height)); 317ac9d17c7SMatthew G. Knepley if (cdim > dim) { 318ac9d17c7SMatthew G. Knepley DM cdm; 319ac9d17c7SMatthew G. Knepley PetscSection cs, csNew; 320ac9d17c7SMatthew G. Knepley Vec coordinates, coordinatesNew; 321ac9d17c7SMatthew G. Knepley VecType vectype; 322ac9d17c7SMatthew G. Knepley IS idx; 323ac9d17c7SMatthew G. Knepley PetscInt *indices; 324ac9d17c7SMatthew G. Knepley PetscInt bs, n; 325ac9d17c7SMatthew G. Knepley 326ac9d17c7SMatthew G. Knepley // Recreate coordinate section 327ac9d17c7SMatthew G. Knepley { 328ac9d17c7SMatthew G. Knepley const char *fieldName = NULL, *compName = NULL; 329ac9d17c7SMatthew G. Knepley PetscInt Nc, pStart, pEnd; 330ac9d17c7SMatthew G. Knepley 331ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 332ac9d17c7SMatthew G. Knepley PetscCall(DMGetLocalSection(cdm, &cs)); 333ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cs), &csNew)); 334ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetNumFields(csNew, 1)); 335ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetFieldName(cs, 0, &fieldName)); 336ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldName(csNew, 0, fieldName)); 337ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetFieldComponents(cs, 0, &Nc)); 338ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(csNew, 0, cdim)); 339ac9d17c7SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 340ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetComponentName(cs, 0, c, &compName)); 341ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetComponentName(csNew, 0, c, compName)); 342ac9d17c7SMatthew G. Knepley } 343ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetChart(cs, &pStart, &pEnd)); 344ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetChart(csNew, pStart, pEnd)); 345ac9d17c7SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 346530e699aSMatthew G. Knepley PetscInt dof; 347530e699aSMatthew G. Knepley 348530e699aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cs, p, &dof)); 349530e699aSMatthew G. Knepley if (dof) { 350ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetDof(csNew, p, cdim)); 351ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csNew, p, 0, cdim)); 352ac9d17c7SMatthew G. Knepley } 353530e699aSMatthew G. Knepley } 354ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetUp(csNew)); 355ac9d17c7SMatthew G. Knepley } 356ac9d17c7SMatthew G. Knepley PetscCall(DMSetLocalSection(cdm, csNew)); 357ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionDestroy(&csNew)); 358530e699aSMatthew G. Knepley // Reset coordinate dimension for coordinate DM 359530e699aSMatthew G. Knepley PetscCall(DMSetCoordinateDim(cdm, cdim)); 360530e699aSMatthew G. Knepley PetscCall(DMSetCoordinateField(cdm, NULL)); 361ac9d17c7SMatthew G. Knepley // Inject coordinates into higher dimension 362ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 363ac9d17c7SMatthew G. Knepley PetscCall(VecGetBlockSize(coordinates, &bs)); 364ac9d17c7SMatthew G. Knepley PetscCheck(bs == dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension"); 365ac9d17c7SMatthew G. Knepley PetscCall(VecCreate(PetscObjectComm((PetscObject)coordinates), &coordinatesNew)); 366ac9d17c7SMatthew G. Knepley PetscCall(VecGetType(coordinates, &vectype)); 367ac9d17c7SMatthew G. Knepley PetscCall(VecSetType(coordinatesNew, vectype)); 368ac9d17c7SMatthew G. Knepley PetscCall(VecGetLocalSize(coordinates, &n)); 369ac9d17c7SMatthew G. Knepley PetscCheck(!(n % bs), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension"); 370ac9d17c7SMatthew G. Knepley n /= bs; 371ac9d17c7SMatthew G. Knepley PetscCall(VecSetSizes(coordinatesNew, n * cdim, PETSC_DETERMINE)); 372ac9d17c7SMatthew G. Knepley PetscCall(VecSetUp(coordinatesNew)); 373ac9d17c7SMatthew G. Knepley PetscCall(PetscMalloc1(n * bs, &indices)); 374ac9d17c7SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) 375ac9d17c7SMatthew G. Knepley for (PetscInt b = 0; b < bs; ++b) indices[i * bs + b] = i * cdim + b; 376ac9d17c7SMatthew G. Knepley PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n * bs, indices, PETSC_OWN_POINTER, &idx)); 377ac9d17c7SMatthew G. Knepley PetscCall(VecISCopy(coordinatesNew, idx, SCATTER_FORWARD, coordinates)); 378ac9d17c7SMatthew G. Knepley PetscCall(ISDestroy(&idx)); 379ac9d17c7SMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinatesNew)); 380ac9d17c7SMatthew G. Knepley PetscCall(VecDestroy(&coordinatesNew)); 381ac9d17c7SMatthew G. Knepley PetscCall(DMSetCoordinateDim(dm, cdim)); 382ac9d17c7SMatthew G. Knepley { 383ac9d17c7SMatthew G. Knepley PetscInt gn; 384ac9d17c7SMatthew G. Knepley 385ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinates(dm, &coordinatesNew)); 386ac9d17c7SMatthew G. Knepley PetscCall(VecGetLocalSize(coordinatesNew, &gn)); 387ac9d17c7SMatthew 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); 388ac9d17c7SMatthew G. Knepley } 389ac9d17c7SMatthew G. Knepley dE = cdim; 390530e699aSMatthew G. Knepley project = PETSC_FALSE; 391ac9d17c7SMatthew G. Knepley } 392e44f6aebSMatthew G. Knepley if (degree >= 0) { 393e44f6aebSMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 394e44f6aebSMatthew G. Knepley PetscInt cStart, cEnd, gct; 395dc431b0cSMatthew G. Knepley 3961df12153SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd)); 397dc431b0cSMatthew G. Knepley if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 398e44f6aebSMatthew G. Knepley gct = (PetscInt)ct; 399462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &gct, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm))); 400e44f6aebSMatthew G. Knepley ct = (DMPolytopeType)gct; 401e44f6aebSMatthew G. Knepley // Work around current bug in PetscDualSpaceSetUp_Lagrange() 402e44f6aebSMatthew G. Knepley // Can be seen in plex_tutorials-ex10_1 4034c712d99Sksagiyam if (ct != DM_POLYTOPE_SEG_PRISM_TENSOR && ct != DM_POLYTOPE_TRI_PRISM_TENSOR && ct != DM_POLYTOPE_QUAD_PRISM_TENSOR) { 4044c712d99Sksagiyam PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe)); 4054c712d99Sksagiyam if (localized) { 4064c712d99Sksagiyam PetscFE dgfe = NULL; 4074c712d99Sksagiyam 4084c712d99Sksagiyam PetscCall(PetscFECreateBrokenElement(fe, &dgfe)); 4094c712d99Sksagiyam PetscCall(PetscFEDestroy(&fe)); 4104c712d99Sksagiyam fe = dgfe; 4114f9ab2b4SJed Brown } 4124c712d99Sksagiyam } 4134c712d99Sksagiyam } 4144c712d99Sksagiyam PetscCall(DMSetCoordinateDisc(dm, fe, localized, project)); 4159566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 4163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4179318fe57SMatthew G. Knepley } 4189318fe57SMatthew G. Knepley 4191df5d5c5SMatthew G. Knepley /*@ 4201df5d5c5SMatthew G. Knepley DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 4211df5d5c5SMatthew G. Knepley 422d083f849SBarry Smith Collective 4231df5d5c5SMatthew G. Knepley 4241df5d5c5SMatthew G. Knepley Input Parameters: 425a1cb98faSBarry Smith + comm - The communicator for the `DM` object 4261df5d5c5SMatthew G. Knepley . dim - The spatial dimension 4271df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells 4281df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces) 4291df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 4301df5d5c5SMatthew G. Knepley 4311df5d5c5SMatthew G. Knepley Output Parameter: 43260225df5SJacob Faibussowitsch . newdm - The `DM` object 4331df5d5c5SMatthew G. Knepley 4341df5d5c5SMatthew G. Knepley Level: beginner 4351df5d5c5SMatthew G. Knepley 4361cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()` 4371df5d5c5SMatthew G. Knepley @*/ 438d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) 439d71ae5a4SJacob Faibussowitsch { 4401df5d5c5SMatthew G. Knepley DM dm; 4411df5d5c5SMatthew G. Knepley PetscMPIInt rank; 4421df5d5c5SMatthew G. Knepley 4431df5d5c5SMatthew G. Knepley PetscFunctionBegin; 4449566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &dm)); 4459566063dSJacob Faibussowitsch PetscCall(DMSetType(dm, DMPLEX)); 4469566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 44746139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 4489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 449ce78fa2fSMatthew G. Knepley switch (dim) { 450ce78fa2fSMatthew G. Knepley case 2: 4519566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular")); 4529566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral")); 453ce78fa2fSMatthew G. Knepley break; 454ce78fa2fSMatthew G. Knepley case 3: 4559566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral")); 4569566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral")); 457ce78fa2fSMatthew G. Knepley break; 458d71ae5a4SJacob Faibussowitsch default: 459d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 460ce78fa2fSMatthew G. Knepley } 4611df5d5c5SMatthew G. Knepley if (rank) { 4621df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {0, 0}; 4639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL)); 4641df5d5c5SMatthew G. Knepley } else { 4651df5d5c5SMatthew G. Knepley switch (dim) { 4661df5d5c5SMatthew G. Knepley case 2: 4671df5d5c5SMatthew G. Knepley if (simplex) { 4681df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {4, 2}; 4691df5d5c5SMatthew G. Knepley PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 4701df5d5c5SMatthew G. Knepley PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 4711df5d5c5SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 4721df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 4731df5d5c5SMatthew G. Knepley 4749566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4751df5d5c5SMatthew G. Knepley } else { 4761df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {6, 2}; 4771df5d5c5SMatthew G. Knepley PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 4781df5d5c5SMatthew G. Knepley PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 4791df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 4801df5d5c5SMatthew 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}; 4811df5d5c5SMatthew G. Knepley 4829566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4831df5d5c5SMatthew G. Knepley } 4841df5d5c5SMatthew G. Knepley break; 4851df5d5c5SMatthew G. Knepley case 3: 4861df5d5c5SMatthew G. Knepley if (simplex) { 4871df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {5, 2}; 4881df5d5c5SMatthew G. Knepley PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 4891df5d5c5SMatthew G. Knepley PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 4901df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 4911df5d5c5SMatthew 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}; 4921df5d5c5SMatthew G. Knepley 4939566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4941df5d5c5SMatthew G. Knepley } else { 4951df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {12, 2}; 4961df5d5c5SMatthew G. Knepley PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 4971df5d5c5SMatthew G. Knepley PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 4981df5d5c5SMatthew G. Knepley PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 4999371c9d4SSatish 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}; 5001df5d5c5SMatthew G. Knepley 5019566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 5021df5d5c5SMatthew G. Knepley } 5031df5d5c5SMatthew G. Knepley break; 504d71ae5a4SJacob Faibussowitsch default: 505d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 5061df5d5c5SMatthew G. Knepley } 5071df5d5c5SMatthew G. Knepley } 50846139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 5091df5d5c5SMatthew G. Knepley *newdm = dm; 5101df5d5c5SMatthew G. Knepley if (refinementLimit > 0.0) { 5111df5d5c5SMatthew G. Knepley DM rdm; 5121df5d5c5SMatthew G. Knepley const char *name; 5131df5d5c5SMatthew G. Knepley 5149566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 5159566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 5169566063dSJacob Faibussowitsch PetscCall(DMRefine(*newdm, comm, &rdm)); 5179566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)*newdm, &name)); 5189566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, name)); 5199566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 5201df5d5c5SMatthew G. Knepley *newdm = rdm; 5211df5d5c5SMatthew G. Knepley } 5221df5d5c5SMatthew G. Knepley if (interpolate) { 5235fd9971aSMatthew G. Knepley DM idm; 5241df5d5c5SMatthew G. Knepley 5259566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*newdm, &idm)); 5269566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 5271df5d5c5SMatthew G. Knepley *newdm = idm; 5281df5d5c5SMatthew G. Knepley } 5293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5301df5d5c5SMatthew G. Knepley } 5311df5d5c5SMatthew G. Knepley 532d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 533d71ae5a4SJacob Faibussowitsch { 5349318fe57SMatthew G. Knepley const PetscInt numVertices = 2; 5359318fe57SMatthew G. Knepley PetscInt markerRight = 1; 5369318fe57SMatthew G. Knepley PetscInt markerLeft = 1; 5379318fe57SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 5389318fe57SMatthew G. Knepley Vec coordinates; 5399318fe57SMatthew G. Knepley PetscSection coordSection; 5409318fe57SMatthew G. Knepley PetscScalar *coords; 5419318fe57SMatthew G. Knepley PetscInt coordSize; 5429318fe57SMatthew G. Knepley PetscMPIInt rank; 5439318fe57SMatthew G. Knepley PetscInt cdim = 1, v; 544552f7358SJed Brown 5459318fe57SMatthew G. Knepley PetscFunctionBegin; 5469566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 5479318fe57SMatthew G. Knepley if (markerSeparate) { 5489318fe57SMatthew G. Knepley markerRight = 2; 5499318fe57SMatthew G. Knepley markerLeft = 1; 5509318fe57SMatthew G. Knepley } 5519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 552c5853193SPierre Jolivet if (rank == 0) { 5539566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numVertices)); 5549566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 5559566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft)); 5569566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight)); 5579318fe57SMatthew G. Knepley } 5589566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 5599566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 5609318fe57SMatthew G. Knepley /* Build coordinates */ 5619566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 5629566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 5639566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 5649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, 0, numVertices)); 5659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 5669318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 5679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 5689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 5699318fe57SMatthew G. Knepley } 5709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 5719566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 5729566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 5739566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 5749566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 5759566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 5769566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 5779566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5789318fe57SMatthew G. Knepley coords[0] = lower[0]; 5799318fe57SMatthew G. Knepley coords[1] = upper[0]; 5809566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 5819566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 5829566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 5833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5849318fe57SMatthew G. Knepley } 58526492d91SMatthew G. Knepley 586d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 587d71ae5a4SJacob Faibussowitsch { 5881df21d24SMatthew G. Knepley const PetscInt numVertices = (edges[0] + 1) * (edges[1] + 1); 5891df21d24SMatthew G. Knepley const PetscInt numEdges = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1]; 590552f7358SJed Brown PetscInt markerTop = 1; 591552f7358SJed Brown PetscInt markerBottom = 1; 592552f7358SJed Brown PetscInt markerRight = 1; 593552f7358SJed Brown PetscInt markerLeft = 1; 594552f7358SJed Brown PetscBool markerSeparate = PETSC_FALSE; 595552f7358SJed Brown Vec coordinates; 596552f7358SJed Brown PetscSection coordSection; 597552f7358SJed Brown PetscScalar *coords; 598552f7358SJed Brown PetscInt coordSize; 599552f7358SJed Brown PetscMPIInt rank; 600552f7358SJed Brown PetscInt v, vx, vy; 601552f7358SJed Brown 602552f7358SJed Brown PetscFunctionBegin; 6039566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 604552f7358SJed Brown if (markerSeparate) { 6051df21d24SMatthew G. Knepley markerTop = 3; 6061df21d24SMatthew G. Knepley markerBottom = 1; 6071df21d24SMatthew G. Knepley markerRight = 2; 6081df21d24SMatthew G. Knepley markerLeft = 4; 609552f7358SJed Brown } 6109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 611dd400576SPatrick Sanan if (rank == 0) { 612552f7358SJed Brown PetscInt e, ex, ey; 613552f7358SJed Brown 6149566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices)); 61548a46eb9SPierre Jolivet for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 6169566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 617552f7358SJed Brown for (vx = 0; vx <= edges[0]; vx++) { 618552f7358SJed Brown for (ey = 0; ey < edges[1]; ey++) { 619552f7358SJed Brown PetscInt edge = vx * edges[1] + ey + edges[0] * (edges[1] + 1); 620552f7358SJed Brown PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges; 621da80777bSKarl Rupp PetscInt cone[2]; 622552f7358SJed Brown 6239371c9d4SSatish Balay cone[0] = vertex; 6249371c9d4SSatish Balay cone[1] = vertex + edges[0] + 1; 6259566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 626552f7358SJed Brown if (vx == edges[0]) { 6279566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 6289566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 629552f7358SJed Brown if (ey == edges[1] - 1) { 6309566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 6319566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 632552f7358SJed Brown } 633552f7358SJed Brown } else if (vx == 0) { 6349566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 6359566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 636552f7358SJed Brown if (ey == edges[1] - 1) { 6379566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 6389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft)); 639552f7358SJed Brown } 640552f7358SJed Brown } 641552f7358SJed Brown } 642552f7358SJed Brown } 643552f7358SJed Brown for (vy = 0; vy <= edges[1]; vy++) { 644552f7358SJed Brown for (ex = 0; ex < edges[0]; ex++) { 645552f7358SJed Brown PetscInt edge = vy * edges[0] + ex; 646552f7358SJed Brown PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges; 647da80777bSKarl Rupp PetscInt cone[2]; 648552f7358SJed Brown 6499371c9d4SSatish Balay cone[0] = vertex; 6509371c9d4SSatish Balay cone[1] = vertex + 1; 6519566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 652552f7358SJed Brown if (vy == edges[1]) { 6539566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 6549566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 655552f7358SJed Brown if (ex == edges[0] - 1) { 6569566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 6579566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 658552f7358SJed Brown } 659552f7358SJed Brown } else if (vy == 0) { 6609566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 6619566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 662552f7358SJed Brown if (ex == edges[0] - 1) { 6639566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 6649566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 665552f7358SJed Brown } 666552f7358SJed Brown } 667552f7358SJed Brown } 668552f7358SJed Brown } 669552f7358SJed Brown } 6709566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 6719566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 672552f7358SJed Brown /* Build coordinates */ 6739566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 2)); 6749566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 6759566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 6769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 6779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 678552f7358SJed Brown for (v = numEdges; v < numEdges + numVertices; ++v) { 6799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 2)); 6809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 681552f7358SJed Brown } 6829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6839566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 6849566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 6859566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 6869566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 6879566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 2)); 6889566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 6899566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 690552f7358SJed Brown for (vy = 0; vy <= edges[1]; ++vy) { 691552f7358SJed Brown for (vx = 0; vx <= edges[0]; ++vx) { 692552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx; 693552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy; 694552f7358SJed Brown } 695552f7358SJed Brown } 6969566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 6979566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 6989566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 6993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 700552f7358SJed Brown } 701552f7358SJed Brown 702d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 703d71ae5a4SJacob Faibussowitsch { 7049e8abbc3SMichael Lange PetscInt vertices[3], numVertices; 7057b59f5a9SMichael Lange PetscInt numFaces = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2]; 706c2df9bbfSMatthew G. Knepley PetscInt markerTop = 1; 707c2df9bbfSMatthew G. Knepley PetscInt markerBottom = 1; 708c2df9bbfSMatthew G. Knepley PetscInt markerFront = 1; 709c2df9bbfSMatthew G. Knepley PetscInt markerBack = 1; 710c2df9bbfSMatthew G. Knepley PetscInt markerRight = 1; 711c2df9bbfSMatthew G. Knepley PetscInt markerLeft = 1; 712c2df9bbfSMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 713552f7358SJed Brown Vec coordinates; 714552f7358SJed Brown PetscSection coordSection; 715552f7358SJed Brown PetscScalar *coords; 716552f7358SJed Brown PetscInt coordSize; 717552f7358SJed Brown PetscMPIInt rank; 718552f7358SJed Brown PetscInt v, vx, vy, vz; 7197b59f5a9SMichael Lange PetscInt voffset, iface = 0, cone[4]; 720552f7358SJed Brown 721552f7358SJed Brown PetscFunctionBegin; 7221dca8a05SBarry 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"); 7239566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 724c2df9bbfSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 725c2df9bbfSMatthew G. Knepley if (markerSeparate) { 726c2df9bbfSMatthew G. Knepley markerBottom = 1; 727c2df9bbfSMatthew G. Knepley markerTop = 2; 728c2df9bbfSMatthew G. Knepley markerFront = 3; 729c2df9bbfSMatthew G. Knepley markerBack = 4; 730c2df9bbfSMatthew G. Knepley markerRight = 5; 731c2df9bbfSMatthew G. Knepley markerLeft = 6; 732c2df9bbfSMatthew G. Knepley } 7339371c9d4SSatish Balay vertices[0] = faces[0] + 1; 7349371c9d4SSatish Balay vertices[1] = faces[1] + 1; 7359371c9d4SSatish Balay vertices[2] = faces[2] + 1; 7369e8abbc3SMichael Lange numVertices = vertices[0] * vertices[1] * vertices[2]; 737dd400576SPatrick Sanan if (rank == 0) { 738552f7358SJed Brown PetscInt f; 739552f7358SJed Brown 7409566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices)); 74148a46eb9SPierre Jolivet for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 7429566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 7437b59f5a9SMichael Lange 7447b59f5a9SMichael Lange /* Side 0 (Top) */ 7457b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7467b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7477b59f5a9SMichael Lange voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx; 7489371c9d4SSatish Balay cone[0] = voffset; 7499371c9d4SSatish Balay cone[1] = voffset + 1; 7509371c9d4SSatish Balay cone[2] = voffset + vertices[0] + 1; 7519371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 7529566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 753c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop)); 754c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop)); 755c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop)); 756c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop)); 757c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop)); 7587b59f5a9SMichael Lange iface++; 759552f7358SJed Brown } 760552f7358SJed Brown } 7617b59f5a9SMichael Lange 7627b59f5a9SMichael Lange /* Side 1 (Bottom) */ 7637b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7647b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7657b59f5a9SMichael Lange voffset = numFaces + vy * (faces[0] + 1) + vx; 7669371c9d4SSatish Balay cone[0] = voffset + 1; 7679371c9d4SSatish Balay cone[1] = voffset; 7689371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 7699371c9d4SSatish Balay cone[3] = voffset + vertices[0] + 1; 7709566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 771c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom)); 772c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom)); 773c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom)); 774c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom)); 775c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom)); 7767b59f5a9SMichael Lange iface++; 777552f7358SJed Brown } 778552f7358SJed Brown } 7797b59f5a9SMichael Lange 7807b59f5a9SMichael Lange /* Side 2 (Front) */ 7817b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 7827b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7837b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vx; 7849371c9d4SSatish Balay cone[0] = voffset; 7859371c9d4SSatish Balay cone[1] = voffset + 1; 7869371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + 1; 7879371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1]; 7889566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 789c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront)); 790c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront)); 791c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront)); 792c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront)); 793c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront)); 7947b59f5a9SMichael Lange iface++; 795552f7358SJed Brown } 7967b59f5a9SMichael Lange } 7977b59f5a9SMichael Lange 7987b59f5a9SMichael Lange /* Side 3 (Back) */ 7997b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8007b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 8017b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx; 8029371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 8039371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1] + 1; 8049371c9d4SSatish Balay cone[2] = voffset + 1; 8059371c9d4SSatish Balay cone[3] = voffset; 8069566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 807c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack)); 808c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack)); 809c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack)); 810c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack)); 811c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack)); 8127b59f5a9SMichael Lange iface++; 8137b59f5a9SMichael Lange } 8147b59f5a9SMichael Lange } 8157b59f5a9SMichael Lange 8167b59f5a9SMichael Lange /* Side 4 (Left) */ 8177b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8187b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 8197b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0]; 8209371c9d4SSatish Balay cone[0] = voffset; 8219371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1]; 8229371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + vertices[0]; 8239371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 8249566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 825c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft)); 826c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft)); 827c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft)); 828c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft)); 829c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft)); 8307b59f5a9SMichael Lange iface++; 8317b59f5a9SMichael Lange } 8327b59f5a9SMichael Lange } 8337b59f5a9SMichael Lange 8347b59f5a9SMichael Lange /* Side 5 (Right) */ 8357b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8367b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 837aab5bcd8SJed Brown voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0]; 8389371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 8399371c9d4SSatish Balay cone[1] = voffset; 8409371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 8419371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1] + vertices[0]; 8429566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 843c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight)); 844c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight)); 845c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight)); 846c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight)); 847c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight)); 8487b59f5a9SMichael Lange iface++; 8497b59f5a9SMichael Lange } 850552f7358SJed Brown } 851552f7358SJed Brown } 8529566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 8539566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 854552f7358SJed Brown /* Build coordinates */ 8559566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 3)); 8569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8579566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 8589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 8599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 860552f7358SJed Brown for (v = numFaces; v < numFaces + numVertices; ++v) { 8619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 3)); 8629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 863552f7358SJed Brown } 8649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 8659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 8669566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 8679566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 8689566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 8699566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 3)); 8709566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 8719566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 872552f7358SJed Brown for (vz = 0; vz <= faces[2]; ++vz) { 873552f7358SJed Brown for (vy = 0; vy <= faces[1]; ++vy) { 874552f7358SJed Brown for (vx = 0; vx <= faces[0]; ++vx) { 875552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx; 876552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy; 877552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz; 878552f7358SJed Brown } 879552f7358SJed Brown } 880552f7358SJed Brown } 8819566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 8829566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 8839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 8843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 885552f7358SJed Brown } 886552f7358SJed Brown 887d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) 888d71ae5a4SJacob Faibussowitsch { 8899318fe57SMatthew G. Knepley PetscFunctionBegin; 8909318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 89146139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 8929566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim - 1)); 8939566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim)); 8949318fe57SMatthew G. Knepley switch (dim) { 895d71ae5a4SJacob Faibussowitsch case 1: 896d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces)); 897d71ae5a4SJacob Faibussowitsch break; 898d71ae5a4SJacob Faibussowitsch case 2: 899d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces)); 900d71ae5a4SJacob Faibussowitsch break; 901d71ae5a4SJacob Faibussowitsch case 3: 902d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces)); 903d71ae5a4SJacob Faibussowitsch break; 904d71ae5a4SJacob Faibussowitsch default: 905d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim); 9069318fe57SMatthew G. Knepley } 90746139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 9089566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 9093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9109318fe57SMatthew G. Knepley } 9119318fe57SMatthew G. Knepley 9129318fe57SMatthew G. Knepley /*@C 9139318fe57SMatthew G. Knepley DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra). 9149318fe57SMatthew G. Knepley 9159318fe57SMatthew G. Knepley Collective 9169318fe57SMatthew G. Knepley 9179318fe57SMatthew G. Knepley Input Parameters: 918a1cb98faSBarry Smith + comm - The communicator for the `DM` object 91920f4b53cSBarry Smith . dim - The spatial dimension of the box, so the resulting mesh is has dimension `dim`-1 92020f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 92120f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 92220f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 9239318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 9249318fe57SMatthew G. Knepley 9259318fe57SMatthew G. Knepley Output Parameter: 926a1cb98faSBarry Smith . dm - The `DM` object 9279318fe57SMatthew G. Knepley 9289318fe57SMatthew G. Knepley Level: beginner 9299318fe57SMatthew G. Knepley 9301cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()` 9319318fe57SMatthew G. Knepley @*/ 932d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) 933d71ae5a4SJacob Faibussowitsch { 9349318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 9359318fe57SMatthew G. Knepley PetscReal low[3] = {0, 0, 0}; 9369318fe57SMatthew G. Knepley PetscReal upp[3] = {1, 1, 1}; 9379318fe57SMatthew G. Knepley 9389318fe57SMatthew G. Knepley PetscFunctionBegin; 9399566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 9409566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 9419566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate)); 9423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9439318fe57SMatthew G. Knepley } 9449318fe57SMatthew G. Knepley 945d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd) 946d71ae5a4SJacob Faibussowitsch { 947fdbf62faSLisandro Dalcin PetscInt i, fStart, fEnd, numCells = 0, numVerts = 0; 948fdbf62faSLisandro Dalcin PetscInt numPoints[2], *coneSize, *cones, *coneOrientations; 949fdbf62faSLisandro Dalcin PetscScalar *vertexCoords; 950fdbf62faSLisandro Dalcin PetscReal L, maxCell; 951fdbf62faSLisandro Dalcin PetscBool markerSeparate = PETSC_FALSE; 952fdbf62faSLisandro Dalcin PetscInt markerLeft = 1, faceMarkerLeft = 1; 953fdbf62faSLisandro Dalcin PetscInt markerRight = 1, faceMarkerRight = 2; 954fdbf62faSLisandro Dalcin PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 955fdbf62faSLisandro Dalcin PetscMPIInt rank; 956fdbf62faSLisandro Dalcin 957fdbf62faSLisandro Dalcin PetscFunctionBegin; 9584f572ea9SToby Isaac PetscAssertPointer(dm, 1); 959fdbf62faSLisandro Dalcin 9609566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, 1)); 9619566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 9629566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 963fdbf62faSLisandro Dalcin 9649566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 965dd400576SPatrick Sanan if (rank == 0) numCells = segments; 966dd400576SPatrick Sanan if (rank == 0) numVerts = segments + (wrap ? 0 : 1); 967fdbf62faSLisandro Dalcin 9689371c9d4SSatish Balay numPoints[0] = numVerts; 9699371c9d4SSatish Balay numPoints[1] = numCells; 9709566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords)); 9719566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts)); 972ad540459SPierre Jolivet for (i = 0; i < numCells; ++i) coneSize[i] = 2; 973ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0; 9749371c9d4SSatish Balay for (i = 0; i < numCells; ++i) { 9759371c9d4SSatish Balay cones[2 * i] = numCells + i % numVerts; 9769371c9d4SSatish Balay cones[2 * i + 1] = numCells + (i + 1) % numVerts; 9779371c9d4SSatish Balay } 978ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells); 9799566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 9809566063dSJacob Faibussowitsch PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords)); 981fdbf62faSLisandro Dalcin 9829566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 9839371c9d4SSatish Balay if (markerSeparate) { 9849371c9d4SSatish Balay markerLeft = faceMarkerLeft; 9859371c9d4SSatish Balay markerRight = faceMarkerRight; 9869371c9d4SSatish Balay } 987dd400576SPatrick Sanan if (!wrap && rank == 0) { 9889566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 9899566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft)); 9909566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight)); 9919566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft)); 9929566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight)); 993fdbf62faSLisandro Dalcin } 994fdbf62faSLisandro Dalcin if (wrap) { 995fdbf62faSLisandro Dalcin L = upper - lower; 996fdbf62faSLisandro Dalcin maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments)); 9974fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L)); 998fdbf62faSLisandro Dalcin } 9999566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 10003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1001fdbf62faSLisandro Dalcin } 1002fdbf62faSLisandro Dalcin 10034054ae39SJames Wright // Creates "Face Sets" label based on the standard box labeling conventions 1004d7d2d1d2SJames Wright static PetscErrorCode DMPlexSetBoxLabel_Internal(DM dm, const DMBoundaryType periodicity[]) 10054054ae39SJames Wright { 10066ff49feeSJames Wright DM cdm; 10076ff49feeSJames Wright PetscSection csection; 10086ff49feeSJames Wright Vec coordinates; 10094054ae39SJames Wright DMLabel label; 10106ff49feeSJames Wright IS faces_is; 10112b4f33d9SJames Wright PetscInt dim, num_face = 0; 10124054ae39SJames Wright const PetscInt *faces; 10134054ae39SJames Wright PetscInt faceMarkerBottom, faceMarkerTop, faceMarkerFront, faceMarkerBack, faceMarkerRight, faceMarkerLeft; 10144054ae39SJames Wright 10154054ae39SJames Wright PetscFunctionBeginUser; 10164054ae39SJames Wright PetscCall(DMGetDimension(dm, &dim)); 1017d7c1f440SPierre 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); 10184054ae39SJames Wright // Get Face Sets label 10194054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 10204054ae39SJames Wright if (label) { 10214054ae39SJames Wright PetscCall(DMLabelReset(label)); 10224054ae39SJames Wright } else { 10234054ae39SJames Wright PetscCall(DMCreateLabel(dm, "Face Sets")); 10244054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 10254054ae39SJames Wright } 10264054ae39SJames Wright PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label)); 10276ff49feeSJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", 1, &faces_is)); 10284054ae39SJames Wright 10294054ae39SJames Wright switch (dim) { 10304054ae39SJames Wright case 2: 10314054ae39SJames Wright faceMarkerTop = 3; 10324054ae39SJames Wright faceMarkerBottom = 1; 10334054ae39SJames Wright faceMarkerRight = 2; 10344054ae39SJames Wright faceMarkerLeft = 4; 10354054ae39SJames Wright break; 10364054ae39SJames Wright case 3: 10374054ae39SJames Wright faceMarkerBottom = 1; 10384054ae39SJames Wright faceMarkerTop = 2; 10394054ae39SJames Wright faceMarkerFront = 3; 10404054ae39SJames Wright faceMarkerBack = 4; 10414054ae39SJames Wright faceMarkerRight = 5; 10424054ae39SJames Wright faceMarkerLeft = 6; 10434054ae39SJames Wright break; 10444054ae39SJames Wright default: 10454054ae39SJames Wright SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 10464054ae39SJames Wright } 10474054ae39SJames Wright 10482b4f33d9SJames Wright if (faces_is) PetscCall(ISGetLocalSize(faces_is, &num_face)); 10492b4f33d9SJames Wright if (faces_is) PetscCall(ISGetIndices(faces_is, &faces)); 10506ff49feeSJames Wright PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 10516ff49feeSJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 10526ff49feeSJames Wright PetscCall(DMGetLocalSection(cdm, &csection)); 10534054ae39SJames Wright for (PetscInt f = 0; f < num_face; ++f) { 10546ff49feeSJames Wright PetscScalar *coords = NULL; 10556ff49feeSJames Wright PetscInt face = faces[f], flip = 1, label_value = -1, coords_size; 10564054ae39SJames Wright 10574054ae39SJames Wright { // Determine if orientation of face is flipped 10584054ae39SJames Wright PetscInt num_cells_support, num_faces, start = -1; 10594054ae39SJames Wright const PetscInt *orients, *cell_faces, *cells; 10604054ae39SJames Wright 10614054ae39SJames Wright PetscCall(DMPlexGetSupport(dm, face, &cells)); 10624054ae39SJames Wright PetscCall(DMPlexGetSupportSize(dm, face, &num_cells_support)); 10634054ae39SJames 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); 10644054ae39SJames Wright PetscCall(DMPlexGetCone(dm, cells[0], &cell_faces)); 10654054ae39SJames Wright PetscCall(DMPlexGetConeSize(dm, cells[0], &num_faces)); 10664054ae39SJames Wright for (PetscInt i = 0; i < num_faces; i++) { 10674054ae39SJames Wright if (cell_faces[i] == face) start = i; 10684054ae39SJames Wright } 10694054ae39SJames Wright PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Could not find face %" PetscInt_FMT " in cone of its support", face); 10704054ae39SJames Wright PetscCall(DMPlexGetConeOrientation(dm, cells[0], &orients)); 10714054ae39SJames Wright if (orients[start] < 0) flip = -1; 10724054ae39SJames Wright } 10734054ae39SJames Wright 10746ff49feeSJames Wright // Cannot use DMPlexComputeCellGeometryFVM() for high-order geometry, so must calculate normal vectors manually 10756ff49feeSJames Wright // Use the vertices (depth 0) of coordinate DM to calculate normal vector 1076*44a422c4SJames Wright PetscCall(DMPlexVecGetClosureAtDepth(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 10774054ae39SJames Wright switch (dim) { 10784054ae39SJames Wright case 2: { 10796ff49feeSJames Wright PetscScalar vec[2]; 10806ff49feeSJames Wright 10816ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) vec[d] = flip * (PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d])); 10826ff49feeSJames Wright PetscScalar normal[] = {vec[1], -vec[0]}; 10836ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 10846ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 10854054ae39SJames Wright } else { 10866ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerTop : faceMarkerBottom; 10874054ae39SJames Wright } 10884054ae39SJames Wright } break; 10894054ae39SJames Wright case 3: { 10906ff49feeSJames Wright PetscScalar vec1[3], vec2[3], normal[3]; 10916ff49feeSJames Wright 10926ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) { 10936ff49feeSJames Wright vec1[d] = PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]); 10946ff49feeSJames Wright vec2[d] = PetscRealPart(coords[2 * dim + d]) - PetscRealPart(coords[1 * dim + d]); 10956ff49feeSJames Wright } 10966ff49feeSJames Wright 10976ff49feeSJames Wright // Calculate normal vector via cross-product 10986ff49feeSJames Wright normal[0] = flip * ((vec1[1] * vec2[2]) - (vec1[2] * vec2[1])); 10996ff49feeSJames Wright normal[1] = flip * ((vec1[2] * vec2[0]) - (vec1[0] * vec2[2])); 11006ff49feeSJames Wright normal[2] = flip * ((vec1[0] * vec2[1]) - (vec1[1] * vec2[0])); 11016ff49feeSJames Wright 11026ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 11036ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[2])) { 11046ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 11054054ae39SJames Wright } else { 11066ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 11074054ae39SJames Wright } 11084054ae39SJames Wright } else { 11096ff49feeSJames Wright if (PetscAbsScalar(normal[1]) > PetscAbsScalar(normal[2])) { 11106ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerBack : faceMarkerFront; 11114054ae39SJames Wright } else { 11126ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 11134054ae39SJames Wright } 11144054ae39SJames Wright } 11154054ae39SJames Wright } break; 11164054ae39SJames Wright } 11174054ae39SJames Wright 11184054ae39SJames Wright PetscInt previous_label_value; // always 1 due to DMPlexMarkBoundaryFaces call above 11194054ae39SJames Wright PetscCall(DMGetLabelValue(dm, "Face Sets", face, &previous_label_value)); 11204054ae39SJames Wright PetscCall(DMClearLabelValue(dm, "Face Sets", face, previous_label_value)); 11214054ae39SJames Wright PetscCall(DMSetLabelValue(dm, "Face Sets", face, label_value)); 11226ff49feeSJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 11234054ae39SJames Wright } 11242b4f33d9SJames Wright if (faces_is) PetscCall(ISRestoreIndices(faces_is, &faces)); 11256ff49feeSJames Wright PetscCall(ISDestroy(&faces_is)); 1126d7d2d1d2SJames Wright 1127d7d2d1d2SJames Wright // Create Isoperiodic SF from newly-created face labels 1128d7d2d1d2SJames Wright PetscSF periodicsfs[3]; 1129d7d2d1d2SJames Wright PetscInt periodic_sf_index = 0; 1130d7d2d1d2SJames Wright PetscScalar transform[3][4][4] = {{{0.}}}; 1131d7d2d1d2SJames Wright for (PetscInt d = 0; d < dim; d++) { 1132d7d2d1d2SJames Wright IS donor_is, periodic_is; 1133d7d2d1d2SJames Wright const PetscInt *donor_faces = NULL, *periodic_faces = NULL; 1134d7d2d1d2SJames Wright PetscInt num_donor = 0, num_periodic = 0; 1135d7d2d1d2SJames Wright PetscSF centroidsf; 1136d7d2d1d2SJames Wright PetscReal donor_to_periodic_distance; 1137d7d2d1d2SJames Wright const PetscInt face_pairings[2][3][2] = { 1138d7d2d1d2SJames Wright // 2D face pairings, {donor, periodic} 1139d7d2d1d2SJames Wright {{4, 2}, {1, 3}}, 1140d7d2d1d2SJames Wright // 3D face pairings 1141d7d2d1d2SJames Wright {{5, 6}, {3, 4}, {1, 2}} 1142d7d2d1d2SJames Wright }; 1143d7d2d1d2SJames Wright 1144d7d2d1d2SJames Wright if (periodicity[d] != DM_BOUNDARY_PERIODIC) continue; 1145d7d2d1d2SJames Wright { 1146d7d2d1d2SJames Wright // Compute centroidsf, which is the mapping from donor faces to periodic faces 1147d7d2d1d2SJames Wright // Matches the centroid of the faces together, ignoring the periodic direction component (which should not match between donor and periodic face) 1148d7d2d1d2SJames Wright PetscInt coords_size, centroid_comps = dim - 1; 1149d7d2d1d2SJames Wright PetscScalar *coords = NULL; 1150d7d2d1d2SJames Wright PetscReal *donor_centroids, *periodic_centroids; 1151d7d2d1d2SJames 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 1152d7d2d1d2SJames Wright 1153d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][0], &donor_is)); 1154d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][1], &periodic_is)); 1155d7d2d1d2SJames Wright if (donor_is) { 1156d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(donor_is, &num_donor)); 1157d7d2d1d2SJames Wright PetscCall(ISGetIndices(donor_is, &donor_faces)); 1158d7d2d1d2SJames Wright } 1159d7d2d1d2SJames Wright if (periodic_is) { 1160d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(periodic_is, &num_periodic)); 1161d7d2d1d2SJames Wright PetscCall(ISGetIndices(periodic_is, &periodic_faces)); 1162d7d2d1d2SJames Wright } 1163d7d2d1d2SJames Wright PetscCall(PetscCalloc2(num_donor * centroid_comps, &donor_centroids, num_periodic * centroid_comps, &periodic_centroids)); 1164d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_donor; f++) { 1165d7d2d1d2SJames Wright PetscInt face = donor_faces[f], num_coords; 1166*44a422c4SJames Wright PetscCall(DMPlexVecGetClosureAtDepth(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[0] = 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 donor_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 1180d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_periodic; f++) { 1181d7d2d1d2SJames Wright PetscInt face = periodic_faces[f], num_coords; 1182*44a422c4SJames Wright PetscCall(DMPlexVecGetClosureAtDepth(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 1183d7d2d1d2SJames Wright num_coords = coords_size / dim; 1184d7d2d1d2SJames Wright for (PetscInt c = 0; c < num_coords; c++) { 1185d7d2d1d2SJames Wright PetscInt comp_index = 0; 1186d7d2d1d2SJames Wright loc_periodic[1] = PetscRealPart(coords[c * dim + d]); 1187d7d2d1d2SJames Wright for (PetscInt i = 0; i < dim; i++) { 1188d7d2d1d2SJames Wright if (i == d) continue; // Periodic direction not used for centroid calculation 1189d7d2d1d2SJames Wright periodic_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords; 1190d7d2d1d2SJames Wright comp_index++; 1191d7d2d1d2SJames Wright } 1192d7d2d1d2SJames Wright } 1193d7d2d1d2SJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 1194d7d2d1d2SJames Wright } 1195d7d2d1d2SJames Wright PetscCallMPI(MPIU_Allreduce(loc_periodic, loc_periodic_global, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm))); 1196d7d2d1d2SJames Wright donor_to_periodic_distance = loc_periodic_global[1] - loc_periodic_global[0]; 1197d7d2d1d2SJames Wright 1198d7d2d1d2SJames Wright PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), ¢roidsf)); 1199d7d2d1d2SJames Wright PetscCall(PetscSFSetGraphFromCoordinates(centroidsf, num_donor, num_periodic, centroid_comps, 1e-10, donor_centroids, periodic_centroids)); 1200d7d2d1d2SJames Wright PetscCall(PetscSFViewFromOptions(centroidsf, NULL, "-dm_plex_box_label_centroid_sf_view")); 1201d7d2d1d2SJames Wright PetscCall(PetscFree2(donor_centroids, periodic_centroids)); 1202d7d2d1d2SJames Wright } 1203d7d2d1d2SJames Wright 1204d7d2d1d2SJames Wright { // Create Isoperiodic SF using centroidsSF 1205d7d2d1d2SJames Wright PetscInt pStart, pEnd; 1206d7d2d1d2SJames Wright PetscInt *leaf_faces; 1207d7d2d1d2SJames Wright const PetscSFNode *firemote; 1208d7d2d1d2SJames Wright PetscSFNode *isoperiodic_leaves; 1209d7d2d1d2SJames Wright 1210d7d2d1d2SJames Wright PetscCall(PetscMalloc1(num_periodic, &leaf_faces)); 1211d7d2d1d2SJames Wright PetscCall(PetscSFBcastBegin(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE)); 1212d7d2d1d2SJames Wright PetscCall(PetscSFBcastEnd(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE)); 1213d7d2d1d2SJames Wright 1214d7d2d1d2SJames Wright PetscCall(PetscMalloc1(num_periodic, &isoperiodic_leaves)); 1215d7d2d1d2SJames Wright PetscCall(PetscSFGetGraph(centroidsf, NULL, NULL, NULL, &firemote)); 1216d7d2d1d2SJames Wright for (PetscInt l = 0; l < num_periodic; ++l) { 1217d7d2d1d2SJames Wright isoperiodic_leaves[l].index = leaf_faces[l]; 1218d7d2d1d2SJames Wright isoperiodic_leaves[l].rank = firemote[l].rank; 1219d7d2d1d2SJames Wright } 1220d7d2d1d2SJames Wright 1221d7d2d1d2SJames Wright PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 1222d7d2d1d2SJames Wright PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &periodicsfs[periodic_sf_index])); 1223d7d2d1d2SJames Wright PetscCall(PetscSFSetGraph(periodicsfs[periodic_sf_index], pEnd - pStart, num_periodic, (PetscInt *)periodic_faces, PETSC_COPY_VALUES, isoperiodic_leaves, PETSC_OWN_POINTER)); 1224d7d2d1d2SJames Wright PetscCall(PetscSFViewFromOptions(periodicsfs[periodic_sf_index], NULL, "-dm_plex_box_label_periodic_sf_view")); 1225d7d2d1d2SJames Wright PetscCall(PetscFree(leaf_faces)); 1226d7d2d1d2SJames Wright } 1227d7d2d1d2SJames Wright 1228d7d2d1d2SJames Wright transform[periodic_sf_index][0][0] = 1; 1229d7d2d1d2SJames Wright transform[periodic_sf_index][1][1] = 1; 1230d7d2d1d2SJames Wright transform[periodic_sf_index][2][2] = 1; 1231d7d2d1d2SJames Wright transform[periodic_sf_index][3][3] = 1; 1232d7d2d1d2SJames Wright transform[periodic_sf_index][d][3] = donor_to_periodic_distance; 1233d7d2d1d2SJames Wright 1234d7d2d1d2SJames Wright periodic_sf_index++; 1235d7d2d1d2SJames Wright PetscCall(PetscSFDestroy(¢roidsf)); 1236d7d2d1d2SJames Wright if (donor_is) { 1237d7d2d1d2SJames Wright PetscCall(ISRestoreIndices(donor_is, &donor_faces)); 1238d7d2d1d2SJames Wright PetscCall(ISDestroy(&donor_is)); 1239d7d2d1d2SJames Wright } 1240d7d2d1d2SJames Wright if (periodic_is) { 1241d7d2d1d2SJames Wright PetscCall(ISRestoreIndices(periodic_is, &periodic_faces)); 1242d7d2d1d2SJames Wright PetscCall(ISDestroy(&periodic_is)); 1243d7d2d1d2SJames Wright } 1244d7d2d1d2SJames Wright PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][0])); 1245d7d2d1d2SJames Wright PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][1])); 1246d7d2d1d2SJames Wright } 1247d7d2d1d2SJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(dm, periodic_sf_index, periodicsfs)); 1248d7d2d1d2SJames Wright PetscCall(DMPlexSetIsoperiodicFaceTransform(dm, periodic_sf_index, (const PetscScalar *)transform)); 1249d7d2d1d2SJames Wright for (PetscInt p = 0; p < periodic_sf_index; p++) PetscCall(PetscSFDestroy(&periodicsfs[p])); 1250d7d2d1d2SJames Wright 1251d7d2d1d2SJames Wright { // Update coordinate DM with new Face Sets label 1252d7d2d1d2SJames Wright DM cdm; 1253d7d2d1d2SJames Wright DMLabel oldFaceSets, newFaceSets; 1254d7d2d1d2SJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 1255d7d2d1d2SJames Wright PetscCall(DMGetLabel(cdm, "Face Sets", &oldFaceSets)); 1256d7d2d1d2SJames Wright if (oldFaceSets) PetscCall(DMRemoveLabelBySelf(cdm, &oldFaceSets, PETSC_FALSE)); 1257d7d2d1d2SJames Wright PetscCall(DMLabelDuplicate(label, &newFaceSets)); 1258d7d2d1d2SJames Wright PetscCall(DMAddLabel(cdm, newFaceSets)); 1259d7d2d1d2SJames Wright PetscCall(DMLabelDestroy(&newFaceSets)); 1260d7d2d1d2SJames Wright } 12614054ae39SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 12624054ae39SJames Wright } 12634054ae39SJames Wright 1264d698cf03SStefano Zampini static PetscErrorCode DMPlexCreateSquareMesh_Simplex_CrissCross(DM dm, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType bd[]) 1265d698cf03SStefano Zampini { 1266d698cf03SStefano Zampini PetscInt markerTop = 1, faceMarkerTop = 3; 1267d698cf03SStefano Zampini PetscInt markerBottom = 1, faceMarkerBottom = 1; 1268d698cf03SStefano Zampini PetscInt markerRight = 1, faceMarkerRight = 2; 1269d698cf03SStefano Zampini PetscInt markerLeft = 1, faceMarkerLeft = 4; 1270d698cf03SStefano Zampini PetscBool markerSeparate = PETSC_FALSE; 1271d698cf03SStefano Zampini DMBoundaryType bdX = bd[0], bdY = bd[1]; 1272d698cf03SStefano Zampini PetscMPIInt rank; 1273d698cf03SStefano Zampini 1274d698cf03SStefano Zampini PetscFunctionBegin; 1275d698cf03SStefano Zampini PetscCheck(bdX == DM_BOUNDARY_NONE || bdX == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdX]); 1276d698cf03SStefano Zampini PetscCheck(bdY == DM_BOUNDARY_NONE || bdY == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdY]); 1277d698cf03SStefano Zampini PetscCall(DMSetDimension(dm, 2)); 1278d698cf03SStefano Zampini PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1279d698cf03SStefano Zampini PetscCall(DMCreateLabel(dm, "marker")); 1280d698cf03SStefano Zampini PetscCall(DMCreateLabel(dm, "Face Sets")); 1281d698cf03SStefano Zampini PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 1282d698cf03SStefano Zampini if (markerSeparate) { 1283d698cf03SStefano Zampini markerBottom = faceMarkerBottom; 1284d698cf03SStefano Zampini markerTop = faceMarkerTop; 1285d698cf03SStefano Zampini markerRight = faceMarkerRight; 1286d698cf03SStefano Zampini markerLeft = faceMarkerLeft; 1287d698cf03SStefano Zampini } 1288d698cf03SStefano Zampini { 1289d698cf03SStefano Zampini const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 1290d698cf03SStefano Zampini const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 1291d698cf03SStefano Zampini const PetscInt numZEdges = rank == 0 ? 4 * edges[0] * edges[1] : 0; /* Z-edges are the 4 internal edges per cell */ 1292d698cf03SStefano Zampini const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC ? edges[0] : edges[0] + 1) : 0; 1293d698cf03SStefano Zampini const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC ? edges[1] : edges[1] + 1) : 0; 1294d698cf03SStefano Zampini const PetscInt numZVertices = rank == 0 ? edges[0] * edges[1] : 0; 1295d698cf03SStefano Zampini const PetscInt numCells = 4 * numXEdges * numYEdges; 1296d698cf03SStefano Zampini const PetscInt numTotXEdges = numXEdges * numYVertices; 1297d698cf03SStefano Zampini const PetscInt numTotYEdges = numYEdges * numXVertices; 1298d698cf03SStefano Zampini const PetscInt numVertices = numXVertices * numYVertices + numZVertices; 1299d698cf03SStefano Zampini const PetscInt numEdges = numTotXEdges + numTotYEdges + numZEdges; 1300d698cf03SStefano Zampini const PetscInt firstVertex = numCells; 1301d698cf03SStefano Zampini const PetscInt firstXEdge = numCells + numVertices; 1302d698cf03SStefano Zampini const PetscInt firstYEdge = firstXEdge + numTotXEdges; 1303d698cf03SStefano Zampini const PetscInt firstZEdge = firstYEdge + numTotYEdges; 1304d698cf03SStefano Zampini Vec coordinates; 1305d698cf03SStefano Zampini PetscSection coordSection; 1306d698cf03SStefano Zampini PetscScalar *coords; 1307d698cf03SStefano Zampini PetscInt coordSize; 1308d698cf03SStefano Zampini PetscInt v, vx, vy; 1309d698cf03SStefano Zampini PetscInt c, e, ex, ey; 1310d698cf03SStefano Zampini 1311d698cf03SStefano Zampini PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVertices)); 1312d698cf03SStefano Zampini for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 3)); 1313d698cf03SStefano Zampini for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 1314d698cf03SStefano Zampini PetscCall(DMSetUp(dm)); 1315d698cf03SStefano Zampini 1316d698cf03SStefano Zampini /* Build cells and Z-edges */ 1317d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ++ey) { 1318d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ++ex) { 1319d698cf03SStefano Zampini const PetscInt exp1 = (ex + 1) % numXVertices; 1320d698cf03SStefano Zampini const PetscInt eyp1 = (ey + 1) % numYVertices; 1321d698cf03SStefano Zampini const PetscInt ez = firstZEdge + 4 * (ey * numXEdges + ex); 1322d698cf03SStefano Zampini const PetscInt vc = firstVertex + numXVertices * numYVertices + ey * numXEdges + ex; 1323d698cf03SStefano Zampini const PetscInt v0 = firstVertex + ey * numXVertices + ex; 1324d698cf03SStefano Zampini const PetscInt v1 = firstVertex + ey * numXVertices + exp1; 1325d698cf03SStefano Zampini const PetscInt v2 = firstVertex + eyp1 * numXVertices + exp1; 1326d698cf03SStefano Zampini const PetscInt v3 = firstVertex + eyp1 * numXVertices + ex; 1327d698cf03SStefano Zampini const PetscInt e0 = firstXEdge + ey * numXEdges + ex; 1328d698cf03SStefano Zampini const PetscInt e1 = firstYEdge + exp1 * numYEdges + ey; 1329d698cf03SStefano Zampini const PetscInt e2 = firstXEdge + eyp1 * numXEdges + ex; 1330d698cf03SStefano Zampini const PetscInt e3 = firstYEdge + ex * numYEdges + ey; 1331d698cf03SStefano Zampini 1332d698cf03SStefano Zampini const PetscInt cones[] = {ez, e0, ez + 1, ez + 1, e1, ez + 2, ez + 2, e2, ez + 3, ez + 3, e3, ez}; 1333d698cf03SStefano Zampini const PetscInt ornts[] = {-1, 0, 0, -1, 0, 0, -1, -1, 0, -1, -1, 0}; 1334d698cf03SStefano Zampini const PetscInt verts[] = {v0, vc, v1, vc, v2, vc, v3, vc}; 1335d698cf03SStefano Zampini 1336d698cf03SStefano Zampini for (c = 0; c < 4; c++) { 1337d698cf03SStefano Zampini PetscInt cell = 4 * (ey * numXEdges + ex) + c; 1338d698cf03SStefano Zampini PetscInt edge = ez + c; 1339d698cf03SStefano Zampini 1340d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, cell, cones + 3 * c)); 1341d698cf03SStefano Zampini PetscCall(DMPlexSetConeOrientation(dm, cell, ornts + 3 * c)); 1342d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, verts + 2 * c)); 1343d698cf03SStefano Zampini } 1344d698cf03SStefano Zampini } 1345d698cf03SStefano Zampini } 1346d698cf03SStefano Zampini 1347d698cf03SStefano Zampini /* Build Y edges*/ 1348d698cf03SStefano Zampini for (vx = 0; vx < numXVertices; vx++) { 1349d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ey++) { 1350d698cf03SStefano Zampini const PetscInt edge = firstYEdge + vx * numYEdges + ey; 1351d698cf03SStefano Zampini const PetscInt v0 = firstVertex + ey * numXVertices + vx; 1352d698cf03SStefano Zampini const PetscInt v1 = firstVertex + ((ey + 1) % numYVertices) * numXVertices + vx; 1353d698cf03SStefano Zampini const PetscInt cone[] = {v0, v1}; 1354d698cf03SStefano Zampini 1355d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, cone)); 1356d698cf03SStefano Zampini if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 1357d698cf03SStefano Zampini if (vx == numXVertices - 1) { 1358d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 1359d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1360d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1361d698cf03SStefano Zampini if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1362d698cf03SStefano Zampini } else if (vx == 0) { 1363d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 1364d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1365d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1366d698cf03SStefano Zampini if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 1367d698cf03SStefano Zampini } 1368d698cf03SStefano Zampini } 1369d698cf03SStefano Zampini } 1370d698cf03SStefano Zampini } 1371d698cf03SStefano Zampini 1372d698cf03SStefano Zampini /* Build X edges*/ 1373d698cf03SStefano Zampini for (vy = 0; vy < numYVertices; vy++) { 1374d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ex++) { 1375d698cf03SStefano Zampini const PetscInt edge = firstXEdge + vy * numXEdges + ex; 1376d698cf03SStefano Zampini const PetscInt v0 = firstVertex + vy * numXVertices + ex; 1377d698cf03SStefano Zampini const PetscInt v1 = firstVertex + vy * numXVertices + (ex + 1) % numXVertices; 1378d698cf03SStefano Zampini const PetscInt cone[] = {v0, v1}; 1379d698cf03SStefano Zampini 1380d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, cone)); 1381d698cf03SStefano Zampini if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 1382d698cf03SStefano Zampini if (vy == numYVertices - 1) { 1383d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 1384d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1385d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1386d698cf03SStefano Zampini if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1387d698cf03SStefano Zampini } else if (vy == 0) { 1388d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 1389d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1390d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1391d698cf03SStefano Zampini if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 1392d698cf03SStefano Zampini } 1393d698cf03SStefano Zampini } 1394d698cf03SStefano Zampini } 1395d698cf03SStefano Zampini } 1396d698cf03SStefano Zampini 1397d698cf03SStefano Zampini /* Compute support, stratify, and celltype label */ 1398d698cf03SStefano Zampini PetscCall(DMPlexSymmetrize(dm)); 1399d698cf03SStefano Zampini PetscCall(DMPlexStratify(dm)); 1400d698cf03SStefano Zampini PetscCall(DMPlexComputeCellTypes(dm)); 1401d698cf03SStefano Zampini 1402d698cf03SStefano Zampini /* Build coordinates */ 1403d698cf03SStefano Zampini PetscCall(DMGetCoordinateSection(dm, &coordSection)); 1404d698cf03SStefano Zampini PetscCall(PetscSectionSetNumFields(coordSection, 1)); 1405d698cf03SStefano Zampini PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 1406d698cf03SStefano Zampini PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 1407d698cf03SStefano Zampini for (v = firstVertex; v < firstVertex + numVertices; ++v) { 1408d698cf03SStefano Zampini PetscCall(PetscSectionSetDof(coordSection, v, 2)); 1409d698cf03SStefano Zampini PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 1410d698cf03SStefano Zampini } 1411d698cf03SStefano Zampini PetscCall(PetscSectionSetUp(coordSection)); 1412d698cf03SStefano Zampini PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 1413d698cf03SStefano Zampini PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 1414d698cf03SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 1415d698cf03SStefano Zampini PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 1416d698cf03SStefano Zampini PetscCall(VecSetBlockSize(coordinates, 2)); 1417d698cf03SStefano Zampini PetscCall(VecSetType(coordinates, VECSTANDARD)); 1418d698cf03SStefano Zampini PetscCall(VecGetArray(coordinates, &coords)); 1419d698cf03SStefano Zampini for (vy = 0; vy < numYVertices; ++vy) { 1420d698cf03SStefano Zampini for (vx = 0; vx < numXVertices; ++vx) { 1421d698cf03SStefano Zampini coords[2 * (vy * numXVertices + vx) + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 1422d698cf03SStefano Zampini coords[2 * (vy * numXVertices + vx) + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1423d698cf03SStefano Zampini } 1424d698cf03SStefano Zampini } 1425d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ++ey) { 1426d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ++ex) { 1427d698cf03SStefano Zampini const PetscInt c = ey * numXEdges + ex + numYVertices * numXVertices; 1428d698cf03SStefano Zampini 1429d698cf03SStefano Zampini coords[2 * c + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * (ex + 0.5); 1430d698cf03SStefano Zampini coords[2 * c + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * (ey + 0.5); 1431d698cf03SStefano Zampini } 1432d698cf03SStefano Zampini } 1433d698cf03SStefano Zampini PetscCall(VecRestoreArray(coordinates, &coords)); 1434d698cf03SStefano Zampini PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 1435d698cf03SStefano Zampini PetscCall(VecDestroy(&coordinates)); 1436d698cf03SStefano Zampini 1437d698cf03SStefano Zampini /* handle periodic BC */ 1438d698cf03SStefano Zampini if (bdX == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_PERIODIC) { 1439d698cf03SStefano Zampini PetscReal L[2] = {-1., -1.}; 1440d698cf03SStefano Zampini PetscReal maxCell[2] = {-1., -1.}; 1441d698cf03SStefano Zampini 1442d698cf03SStefano Zampini for (PetscInt d = 0; d < 2; ++d) { 1443d698cf03SStefano Zampini if (bd[d] != DM_BOUNDARY_NONE) { 1444d698cf03SStefano Zampini L[d] = upper[d] - lower[d]; 1445d698cf03SStefano Zampini maxCell[d] = 1.1 * (L[d] / PetscMax(1, edges[d])); 1446d698cf03SStefano Zampini } 1447d698cf03SStefano Zampini } 1448d698cf03SStefano Zampini PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1449d698cf03SStefano Zampini } 1450d698cf03SStefano Zampini } 1451d698cf03SStefano Zampini PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 1452d698cf03SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1453d698cf03SStefano Zampini } 1454d698cf03SStefano Zampini 1455d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 1456d71ae5a4SJacob Faibussowitsch { 14579318fe57SMatthew G. Knepley DM boundary, vol; 1458c22d3578SMatthew G. Knepley DMLabel bdlabel; 1459d698cf03SStefano Zampini PetscBool crisscross = PETSC_FALSE; 1460d6218766SMatthew G. Knepley 1461d6218766SMatthew G. Knepley PetscFunctionBegin; 14624f572ea9SToby Isaac PetscAssertPointer(dm, 1); 1463d698cf03SStefano Zampini if (dim == 2) PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_box_crisscross", &crisscross, NULL)); 1464d698cf03SStefano Zampini if (crisscross) { 1465d698cf03SStefano Zampini PetscCall(DMPlexCreateSquareMesh_Simplex_CrissCross(dm, faces, lower, upper, periodicity)); 1466d698cf03SStefano Zampini } else { 1467c22d3578SMatthew 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"); 14689566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary)); 14699566063dSJacob Faibussowitsch PetscCall(DMSetType(boundary, DMPLEX)); 1470d698cf03SStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)boundary, ((PetscObject)dm)->prefix)); 14719566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 14729566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 1473c22d3578SMatthew G. Knepley PetscCall(DMGetLabel(vol, "marker", &bdlabel)); 1474c22d3578SMatthew G. Knepley if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel)); 14755de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol)); 147669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 1477d698cf03SStefano Zampini PetscCall(DMDestroy(&boundary)); 1478d698cf03SStefano Zampini } 14794054ae39SJames Wright if (interpolate) { 14804054ae39SJames Wright PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 1481d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, periodicity)); 14824054ae39SJames Wright } 14833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1484d6218766SMatthew G. Knepley } 1485d6218766SMatthew G. Knepley 1486d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 1487d71ae5a4SJacob Faibussowitsch { 1488ed0e4b50SMatthew G. Knepley DMLabel cutLabel = NULL; 1489f4eb4c5dSMatthew G. Knepley PetscInt markerTop = 1, faceMarkerTop = 1; 1490f4eb4c5dSMatthew G. Knepley PetscInt markerBottom = 1, faceMarkerBottom = 1; 1491f4eb4c5dSMatthew G. Knepley PetscInt markerFront = 1, faceMarkerFront = 1; 1492f4eb4c5dSMatthew G. Knepley PetscInt markerBack = 1, faceMarkerBack = 1; 1493f4eb4c5dSMatthew G. Knepley PetscInt markerRight = 1, faceMarkerRight = 1; 1494f4eb4c5dSMatthew G. Knepley PetscInt markerLeft = 1, faceMarkerLeft = 1; 14953dfda0b1SToby Isaac PetscInt dim; 1496d8211ee3SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 14973dfda0b1SToby Isaac PetscMPIInt rank; 14983dfda0b1SToby Isaac 14993dfda0b1SToby Isaac PetscFunctionBegin; 15009566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 15019566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15029566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 15039566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 15049566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 15059371c9d4SSatish 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) { 15069371c9d4SSatish Balay if (cutMarker) { 15079371c9d4SSatish Balay PetscCall(DMCreateLabel(dm, "periodic_cut")); 15089371c9d4SSatish Balay PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 15099371c9d4SSatish Balay } 1510d8211ee3SMatthew G. Knepley } 15113dfda0b1SToby Isaac switch (dim) { 15123dfda0b1SToby Isaac case 2: 1513f4eb4c5dSMatthew G. Knepley faceMarkerTop = 3; 1514f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1515f4eb4c5dSMatthew G. Knepley faceMarkerRight = 2; 1516f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 4; 15173dfda0b1SToby Isaac break; 15183dfda0b1SToby Isaac case 3: 1519f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1520f4eb4c5dSMatthew G. Knepley faceMarkerTop = 2; 1521f4eb4c5dSMatthew G. Knepley faceMarkerFront = 3; 1522f4eb4c5dSMatthew G. Knepley faceMarkerBack = 4; 1523f4eb4c5dSMatthew G. Knepley faceMarkerRight = 5; 1524f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 6; 15253dfda0b1SToby Isaac break; 1526d71ae5a4SJacob Faibussowitsch default: 1527d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 15283dfda0b1SToby Isaac } 15299566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 1530f4eb4c5dSMatthew G. Knepley if (markerSeparate) { 1531f4eb4c5dSMatthew G. Knepley markerBottom = faceMarkerBottom; 1532f4eb4c5dSMatthew G. Knepley markerTop = faceMarkerTop; 1533f4eb4c5dSMatthew G. Knepley markerFront = faceMarkerFront; 1534f4eb4c5dSMatthew G. Knepley markerBack = faceMarkerBack; 1535f4eb4c5dSMatthew G. Knepley markerRight = faceMarkerRight; 1536f4eb4c5dSMatthew G. Knepley markerLeft = faceMarkerLeft; 15373dfda0b1SToby Isaac } 15383dfda0b1SToby Isaac { 1539dd400576SPatrick Sanan const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 1540dd400576SPatrick Sanan const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 1541dd400576SPatrick Sanan const PetscInt numZEdges = rank == 0 ? edges[2] : 0; 1542dd400576SPatrick Sanan const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0; 1543dd400576SPatrick Sanan const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0; 1544dd400576SPatrick Sanan const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0; 15453dfda0b1SToby Isaac const PetscInt numCells = numXEdges * numYEdges * numZEdges; 15463dfda0b1SToby Isaac const PetscInt numXFaces = numYEdges * numZEdges; 15473dfda0b1SToby Isaac const PetscInt numYFaces = numXEdges * numZEdges; 15483dfda0b1SToby Isaac const PetscInt numZFaces = numXEdges * numYEdges; 15493dfda0b1SToby Isaac const PetscInt numTotXFaces = numXVertices * numXFaces; 15503dfda0b1SToby Isaac const PetscInt numTotYFaces = numYVertices * numYFaces; 15513dfda0b1SToby Isaac const PetscInt numTotZFaces = numZVertices * numZFaces; 15523dfda0b1SToby Isaac const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 15533dfda0b1SToby Isaac const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices; 15543dfda0b1SToby Isaac const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices; 15553dfda0b1SToby Isaac const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices; 15563dfda0b1SToby Isaac const PetscInt numVertices = numXVertices * numYVertices * numZVertices; 15573dfda0b1SToby Isaac const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 15583dfda0b1SToby Isaac const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 15593dfda0b1SToby Isaac const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 15603dfda0b1SToby Isaac const PetscInt firstYFace = firstXFace + numTotXFaces; 15613dfda0b1SToby Isaac const PetscInt firstZFace = firstYFace + numTotYFaces; 15623dfda0b1SToby Isaac const PetscInt firstXEdge = numCells + numFaces + numVertices; 15633dfda0b1SToby Isaac const PetscInt firstYEdge = firstXEdge + numTotXEdges; 15643dfda0b1SToby Isaac const PetscInt firstZEdge = firstYEdge + numTotYEdges; 15653dfda0b1SToby Isaac Vec coordinates; 15663dfda0b1SToby Isaac PetscSection coordSection; 15673dfda0b1SToby Isaac PetscScalar *coords; 15683dfda0b1SToby Isaac PetscInt coordSize; 15693dfda0b1SToby Isaac PetscInt v, vx, vy, vz; 15703dfda0b1SToby Isaac PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 15713dfda0b1SToby Isaac 15729566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices)); 157348a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 157448a46eb9SPierre Jolivet for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 157548a46eb9SPierre Jolivet for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 15769566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 15773dfda0b1SToby Isaac /* Build cells */ 15783dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 15793dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 15803dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 15813dfda0b1SToby Isaac PetscInt cell = (fz * numYEdges + fy) * numXEdges + fx; 15823dfda0b1SToby Isaac PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 15833dfda0b1SToby Isaac PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices); 15843dfda0b1SToby Isaac PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 15853dfda0b1SToby Isaac PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices); 15863dfda0b1SToby Isaac PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 15873dfda0b1SToby Isaac PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices); 15883dfda0b1SToby Isaac /* B, T, F, K, R, L */ 1589b5a892a1SMatthew G. Knepley PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */ 159042206facSLisandro Dalcin PetscInt cone[6]; 15913dfda0b1SToby Isaac 15923dfda0b1SToby Isaac /* no boundary twisting in 3D */ 15939371c9d4SSatish Balay cone[0] = faceB; 15949371c9d4SSatish Balay cone[1] = faceT; 15959371c9d4SSatish Balay cone[2] = faceF; 15969371c9d4SSatish Balay cone[3] = faceK; 15979371c9d4SSatish Balay cone[4] = faceR; 15989371c9d4SSatish Balay cone[5] = faceL; 15999566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, cell, cone)); 16009566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, cell, ornt)); 16019566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 16029566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 16039566063dSJacob Faibussowitsch if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 16043dfda0b1SToby Isaac } 16053dfda0b1SToby Isaac } 16063dfda0b1SToby Isaac } 16073dfda0b1SToby Isaac /* Build x faces */ 16083dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 16093dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 16103dfda0b1SToby Isaac for (fx = 0; fx < numXVertices; ++fx) { 16113dfda0b1SToby Isaac PetscInt face = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 16123dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 16133dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz; 16143dfda0b1SToby Isaac PetscInt edgeB = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 16153dfda0b1SToby Isaac PetscInt edgeT = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy; 1616b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16173dfda0b1SToby Isaac PetscInt cone[4]; 16183dfda0b1SToby Isaac 16193dfda0b1SToby Isaac if (dim == 3) { 16203dfda0b1SToby Isaac /* markers */ 16213dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 16223dfda0b1SToby Isaac if (fx == numXVertices - 1) { 16239566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 16249566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerRight)); 16259371c9d4SSatish Balay } else if (fx == 0) { 16269566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 16279566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft)); 16283dfda0b1SToby Isaac } 16293dfda0b1SToby Isaac } 16303dfda0b1SToby Isaac } 16319371c9d4SSatish Balay cone[0] = edgeB; 16329371c9d4SSatish Balay cone[1] = edgeR; 16339371c9d4SSatish Balay cone[2] = edgeT; 16349371c9d4SSatish Balay cone[3] = edgeL; 16359566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 16369566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 16373dfda0b1SToby Isaac } 16383dfda0b1SToby Isaac } 16393dfda0b1SToby Isaac } 16403dfda0b1SToby Isaac /* Build y faces */ 16413dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 164242206facSLisandro Dalcin for (fx = 0; fx < numXEdges; ++fx) { 16433dfda0b1SToby Isaac for (fy = 0; fy < numYVertices; ++fy) { 16443dfda0b1SToby Isaac PetscInt face = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 16453dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 16463dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz; 16473dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 16483dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx; 1649b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16503dfda0b1SToby Isaac PetscInt cone[4]; 16513dfda0b1SToby Isaac 16523dfda0b1SToby Isaac if (dim == 3) { 16533dfda0b1SToby Isaac /* markers */ 16543dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 16553dfda0b1SToby Isaac if (fy == numYVertices - 1) { 16569566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 16579566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBack)); 16589371c9d4SSatish Balay } else if (fy == 0) { 16599566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 16609566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerFront)); 16613dfda0b1SToby Isaac } 16623dfda0b1SToby Isaac } 16633dfda0b1SToby Isaac } 16649371c9d4SSatish Balay cone[0] = edgeB; 16659371c9d4SSatish Balay cone[1] = edgeR; 16669371c9d4SSatish Balay cone[2] = edgeT; 16679371c9d4SSatish Balay cone[3] = edgeL; 16689566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 16699566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 16703dfda0b1SToby Isaac } 16713dfda0b1SToby Isaac } 16723dfda0b1SToby Isaac } 16733dfda0b1SToby Isaac /* Build z faces */ 16743dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 16753dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 16763dfda0b1SToby Isaac for (fz = 0; fz < numZVertices; fz++) { 16773dfda0b1SToby Isaac PetscInt face = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 16783dfda0b1SToby Isaac PetscInt edgeL = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 16793dfda0b1SToby Isaac PetscInt edgeR = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy; 16803dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 16813dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx; 1682b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16833dfda0b1SToby Isaac PetscInt cone[4]; 16843dfda0b1SToby Isaac 16853dfda0b1SToby Isaac if (dim == 2) { 16869371c9d4SSatish Balay if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) { 16879371c9d4SSatish Balay edgeR += numYEdges - 1 - 2 * fy; 16889371c9d4SSatish Balay ornt[1] = -1; 16899371c9d4SSatish Balay } 16909371c9d4SSatish Balay if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) { 16919371c9d4SSatish Balay edgeT += numXEdges - 1 - 2 * fx; 16929371c9d4SSatish Balay ornt[2] = 0; 16939371c9d4SSatish Balay } 16949566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 16959566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 1696d1c88043SMatthew G. Knepley } else { 16973dfda0b1SToby Isaac /* markers */ 16983dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 16993dfda0b1SToby Isaac if (fz == numZVertices - 1) { 17009566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 17019566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerTop)); 17029371c9d4SSatish Balay } else if (fz == 0) { 17039566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 17049566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom)); 17053dfda0b1SToby Isaac } 17063dfda0b1SToby Isaac } 17073dfda0b1SToby Isaac } 17089371c9d4SSatish Balay cone[0] = edgeB; 17099371c9d4SSatish Balay cone[1] = edgeR; 17109371c9d4SSatish Balay cone[2] = edgeT; 17119371c9d4SSatish Balay cone[3] = edgeL; 17129566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 17139566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 17143dfda0b1SToby Isaac } 17153dfda0b1SToby Isaac } 17163dfda0b1SToby Isaac } 17173dfda0b1SToby Isaac /* Build Z edges*/ 17183dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 17193dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 17203dfda0b1SToby Isaac for (ez = 0; ez < numZEdges; ez++) { 17213dfda0b1SToby Isaac const PetscInt edge = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez; 17223dfda0b1SToby Isaac const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx; 17233dfda0b1SToby Isaac const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx; 17243dfda0b1SToby Isaac PetscInt cone[2]; 17253dfda0b1SToby Isaac 17269371c9d4SSatish Balay cone[0] = vertexB; 17279371c9d4SSatish Balay cone[1] = vertexT; 1728c2df9bbfSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, edge, cone)); 17293dfda0b1SToby Isaac if (dim == 3) { 17303dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 17313dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17329566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1733c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1734c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1735c2df9bbfSMatthew G. Knepley } else if (vx == 0) { 17369566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1737c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1738c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 17393dfda0b1SToby Isaac } 17403dfda0b1SToby Isaac } 17413dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 17423dfda0b1SToby Isaac if (vy == numYVertices - 1) { 17439566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1744c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1745c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1746c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 17479566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1748c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1749c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 17503dfda0b1SToby Isaac } 17513dfda0b1SToby Isaac } 17523dfda0b1SToby Isaac } 17533dfda0b1SToby Isaac } 17543dfda0b1SToby Isaac } 17553dfda0b1SToby Isaac } 17563dfda0b1SToby Isaac /* Build Y edges*/ 17573dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 17583dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 17593dfda0b1SToby Isaac for (ey = 0; ey < numYEdges; ey++) { 17603dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx; 17613dfda0b1SToby Isaac const PetscInt edge = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey; 17623dfda0b1SToby Isaac const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx; 17633dfda0b1SToby Isaac const PetscInt vertexK = firstVertex + nextv; 17643dfda0b1SToby Isaac PetscInt cone[2]; 17653dfda0b1SToby Isaac 17669371c9d4SSatish Balay cone[0] = vertexF; 17679371c9d4SSatish Balay cone[1] = vertexK; 17689566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 17693dfda0b1SToby Isaac if (dim == 2) { 17703dfda0b1SToby Isaac if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 17713dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17729566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 17739566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 17749566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1775c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1776d8211ee3SMatthew G. Knepley } else if (vx == 0) { 17779566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 17789566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 17799566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1780c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 17813dfda0b1SToby Isaac } 1782d8211ee3SMatthew G. Knepley } else { 17834c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 17849566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 17859566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1786c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 17873dfda0b1SToby Isaac } 1788d8211ee3SMatthew G. Knepley } 1789d8211ee3SMatthew G. Knepley } else { 17903dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 17913dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17929566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1793c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1794c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1795d8211ee3SMatthew G. Knepley } else if (vx == 0) { 17969566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1797c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1798c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 17993dfda0b1SToby Isaac } 18003dfda0b1SToby Isaac } 18013dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 18023dfda0b1SToby Isaac if (vz == numZVertices - 1) { 18039566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1804c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1805c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1806d8211ee3SMatthew G. Knepley } else if (vz == 0) { 18079566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1808c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1809c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 18103dfda0b1SToby Isaac } 18113dfda0b1SToby Isaac } 18123dfda0b1SToby Isaac } 18133dfda0b1SToby Isaac } 18143dfda0b1SToby Isaac } 18153dfda0b1SToby Isaac } 18163dfda0b1SToby Isaac /* Build X edges*/ 18173dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 18183dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 18193dfda0b1SToby Isaac for (ex = 0; ex < numXEdges; ex++) { 18203dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices; 18213dfda0b1SToby Isaac const PetscInt edge = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex; 18223dfda0b1SToby Isaac const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex; 18233dfda0b1SToby Isaac const PetscInt vertexR = firstVertex + nextv; 18243dfda0b1SToby Isaac PetscInt cone[2]; 18253dfda0b1SToby Isaac 18269371c9d4SSatish Balay cone[0] = vertexL; 18279371c9d4SSatish Balay cone[1] = vertexR; 18289566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 18293dfda0b1SToby Isaac if (dim == 2) { 18303dfda0b1SToby Isaac if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 18313dfda0b1SToby Isaac if (vy == numYVertices - 1) { 18329566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 18339566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 18349566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1835c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1836d8211ee3SMatthew G. Knepley } else if (vy == 0) { 18379566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 18389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 18399566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1840c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 18413dfda0b1SToby Isaac } 1842d8211ee3SMatthew G. Knepley } else { 18434c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 18449566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 18459566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1846c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 18473dfda0b1SToby Isaac } 1848d8211ee3SMatthew G. Knepley } 1849d8211ee3SMatthew G. Knepley } else { 18503dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 18513dfda0b1SToby Isaac if (vy == numYVertices - 1) { 18529566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1853c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1854c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1855c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 18569566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1857c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1858c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 18593dfda0b1SToby Isaac } 18603dfda0b1SToby Isaac } 18613dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 18623dfda0b1SToby Isaac if (vz == numZVertices - 1) { 18639566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1864c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1865c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1866c2df9bbfSMatthew G. Knepley } else if (vz == 0) { 18679566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1868c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1869c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 18703dfda0b1SToby Isaac } 18713dfda0b1SToby Isaac } 18723dfda0b1SToby Isaac } 18733dfda0b1SToby Isaac } 18743dfda0b1SToby Isaac } 18753dfda0b1SToby Isaac } 18769566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 18779566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 18783dfda0b1SToby Isaac /* Build coordinates */ 18799566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 18809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 18819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 18829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 18833dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex + numVertices; ++v) { 18849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 18859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 18863dfda0b1SToby Isaac } 18879566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 18889566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 18899566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 18909566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 18919566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 18929566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 18939566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 18949566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 18953dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; ++vz) { 18963dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; ++vy) { 18973dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; ++vx) { 18983dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 18993dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1900ad540459SPierre Jolivet if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz; 19013dfda0b1SToby Isaac } 19023dfda0b1SToby Isaac } 19033dfda0b1SToby Isaac } 19049566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 19059566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 19069566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 19073dfda0b1SToby Isaac } 19083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19093dfda0b1SToby Isaac } 19103dfda0b1SToby Isaac 1911d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1912d71ae5a4SJacob Faibussowitsch { 19139318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 19149318fe57SMatthew G. Knepley PetscInt fac[3] = {0, 0, 0}, d; 1915552f7358SJed Brown 1916552f7358SJed Brown PetscFunctionBegin; 19174f572ea9SToby Isaac PetscAssertPointer(dm, 1); 19189318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 19199566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 19209371c9d4SSatish Balay for (d = 0; d < dim; ++d) { 19219371c9d4SSatish Balay fac[d] = faces[d]; 19229371c9d4SSatish Balay bdt[d] = periodicity[d]; 19239371c9d4SSatish Balay } 19249566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2])); 19259371c9d4SSatish 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))) { 19266858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 19276858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1928552f7358SJed Brown 19299318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19306858538eSMatthew G. Knepley if (periodicity[d] != DM_BOUNDARY_NONE) { 19319318fe57SMatthew G. Knepley L[d] = upper[d] - lower[d]; 19329318fe57SMatthew G. Knepley maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d])); 1933768d5fceSMatthew G. Knepley } 19346858538eSMatthew G. Knepley } 19354fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1936768d5fceSMatthew G. Knepley } 19379566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 19383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19399318fe57SMatthew G. Knepley } 19409318fe57SMatthew G. Knepley 19415dca41c3SJed 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) 1942d71ae5a4SJacob Faibussowitsch { 19439318fe57SMatthew G. Knepley PetscFunctionBegin; 194446139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 19455dca41c3SJed Brown if (shape == DM_SHAPE_ZBOX) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 19466725e60dSJed Brown else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 19479566063dSJacob Faibussowitsch else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 19489566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity)); 19499318fe57SMatthew G. Knepley if (!interpolate && dim > 1 && !simplex) { 1950768d5fceSMatthew G. Knepley DM udm; 1951768d5fceSMatthew G. Knepley 19529566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 19539566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, udm)); 195469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 1955768d5fceSMatthew G. Knepley } 195646139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 19573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1958c8c68bd8SToby Isaac } 1959c8c68bd8SToby Isaac 19605d83a8b1SBarry Smith /*@ 1961768d5fceSMatthew G. Knepley DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 1962768d5fceSMatthew G. Knepley 1963d083f849SBarry Smith Collective 1964768d5fceSMatthew G. Knepley 1965768d5fceSMatthew G. Knepley Input Parameters: 1966a1cb98faSBarry Smith + comm - The communicator for the `DM` object 1967768d5fceSMatthew G. Knepley . dim - The spatial dimension 1968a1cb98faSBarry Smith . simplex - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells 196920f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 197020f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 197120f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 197220f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 197342108689Sksagiyam . interpolate - Flag to create intermediate mesh pieces (edges, faces) 197442108689Sksagiyam . localizationHeight - Flag to localize edges and faces in addition to cells; only significant for periodic meshes 197542108689Sksagiyam - sparseLocalize - Flag to localize coordinates only for cells near the periodic boundary; only significant for periodic meshes 1976768d5fceSMatthew G. Knepley 1977768d5fceSMatthew G. Knepley Output Parameter: 1978a1cb98faSBarry Smith . dm - The `DM` object 1979768d5fceSMatthew G. Knepley 1980768d5fceSMatthew G. Knepley Level: beginner 1981768d5fceSMatthew G. Knepley 1982a1cb98faSBarry Smith Note: 1983a1cb98faSBarry Smith To customize this mesh using options, use 1984a1cb98faSBarry Smith .vb 1985a1cb98faSBarry Smith DMCreate(comm, &dm); 1986a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 1987a1cb98faSBarry Smith DMSetFromOptions(dm); 1988a1cb98faSBarry Smith .ve 1989a1cb98faSBarry Smith and use the options in `DMSetFromOptions()`. 1990a1cb98faSBarry Smith 1991a4e35b19SJacob Faibussowitsch Here is the numbering returned for 2 faces in each direction for tensor cells\: 1992a1cb98faSBarry Smith .vb 1993a1cb98faSBarry Smith 10---17---11---18----12 1994a1cb98faSBarry Smith | | | 1995a1cb98faSBarry Smith | | | 1996a1cb98faSBarry Smith 20 2 22 3 24 1997a1cb98faSBarry Smith | | | 1998a1cb98faSBarry Smith | | | 1999a1cb98faSBarry Smith 7---15----8---16----9 2000a1cb98faSBarry Smith | | | 2001a1cb98faSBarry Smith | | | 2002a1cb98faSBarry Smith 19 0 21 1 23 2003a1cb98faSBarry Smith | | | 2004a1cb98faSBarry Smith | | | 2005a1cb98faSBarry Smith 4---13----5---14----6 2006a1cb98faSBarry Smith .ve 2007a1cb98faSBarry Smith and for simplicial cells 2008a1cb98faSBarry Smith .vb 2009a1cb98faSBarry Smith 14----8---15----9----16 2010a1cb98faSBarry Smith |\ 5 |\ 7 | 2011a1cb98faSBarry Smith | \ | \ | 2012a1cb98faSBarry Smith 13 2 14 3 15 2013a1cb98faSBarry Smith | 4 \ | 6 \ | 2014a1cb98faSBarry Smith | \ | \ | 2015a1cb98faSBarry Smith 11----6---12----7----13 2016a1cb98faSBarry Smith |\ |\ | 2017a1cb98faSBarry Smith | \ 1 | \ 3 | 2018a1cb98faSBarry Smith 10 0 11 1 12 2019a1cb98faSBarry Smith | 0 \ | 2 \ | 2020a1cb98faSBarry Smith | \ | \ | 2021a1cb98faSBarry Smith 8----4----9----5----10 2022a1cb98faSBarry Smith .ve 2023a1cb98faSBarry Smith 20241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 2025768d5fceSMatthew G. Knepley @*/ 202642108689Sksagiyam 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) 2027d71ae5a4SJacob Faibussowitsch { 20289318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 2029fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 2030fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 2031fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 2032552f7358SJed Brown 2033768d5fceSMatthew G. Knepley PetscFunctionBegin; 20349566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 20359566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 20365dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(*dm, DM_SHAPE_BOX, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 203742108689Sksagiyam if (periodicity) { 203842108689Sksagiyam DM cdm; 203942108689Sksagiyam 204042108689Sksagiyam PetscCall(DMGetCoordinateDM(*dm, &cdm)); 204142108689Sksagiyam PetscCall(DMPlexSetMaxProjectionHeight(cdm, localizationHeight)); 204242108689Sksagiyam PetscCall(DMSetSparseLocalize(*dm, sparseLocalize)); 204342108689Sksagiyam PetscCall(DMLocalizeCoordinates(*dm)); 204442108689Sksagiyam } 20453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20469318fe57SMatthew G. Knepley } 2047fdbf62faSLisandro Dalcin 2048d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 2049d71ae5a4SJacob Faibussowitsch { 20509318fe57SMatthew G. Knepley DM bdm, vol; 20519318fe57SMatthew G. Knepley PetscInt i; 20529318fe57SMatthew G. Knepley 20539318fe57SMatthew G. Knepley PetscFunctionBegin; 20541fcf445aSMatthew G. Knepley // TODO Now we can support periodicity 205508401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 20569566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 20579566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 20589566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 205946139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, bdm, 0, 0, 0)); 20609566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 2061658b9581SMatthew G. Knepley PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, NULL, NULL, NULL, &vol)); 206246139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, bdm, 0, 0, 0)); 20639566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 206469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 20659318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 20669318fe57SMatthew G. Knepley Vec v; 20679318fe57SMatthew G. Knepley PetscScalar *x; 20689318fe57SMatthew G. Knepley PetscInt cDim, n; 20699318fe57SMatthew G. Knepley 20709566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 20719566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 20729566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 20739566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 20749318fe57SMatthew G. Knepley x += cDim; 20759318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 20769566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 20779566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 20789318fe57SMatthew G. Knepley } 20793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2080552f7358SJed Brown } 2081552f7358SJed Brown 208200dabe28SStefano Zampini /*@ 208339f4f5dbSPierre Jolivet DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tessellating the (x,y) plane and extruding in the third direction using wedge cells. 208400dabe28SStefano Zampini 2085d083f849SBarry Smith Collective 208600dabe28SStefano Zampini 208700dabe28SStefano Zampini Input Parameters: 2088a1cb98faSBarry Smith + comm - The communicator for the `DM` object 208920f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1, 1, 1) 209020f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 209120f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 209220f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 2093a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 209400dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 209500dabe28SStefano Zampini 209600dabe28SStefano Zampini Output Parameter: 2097a1cb98faSBarry Smith . dm - The `DM` object 209800dabe28SStefano Zampini 209900dabe28SStefano Zampini Level: beginner 210000dabe28SStefano Zampini 21011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 210200dabe28SStefano Zampini @*/ 2103d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 2104d71ae5a4SJacob Faibussowitsch { 21059318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 210600dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 210700dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 210800dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 210900dabe28SStefano Zampini 211000dabe28SStefano Zampini PetscFunctionBegin; 21119566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 21129566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 21139566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 2114d410b0cfSMatthew G. Knepley if (!interpolate) { 2115d410b0cfSMatthew G. Knepley DM udm; 211600dabe28SStefano Zampini 21179566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 211869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 211900dabe28SStefano Zampini } 21207ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 21213ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 212200dabe28SStefano Zampini } 212300dabe28SStefano Zampini 2124cfb853baSMatthew G. Knepley /* 2125cfb853baSMatthew 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. 2126cfb853baSMatthew G. Knepley 2127cfb853baSMatthew G. Knepley Input Parameters: 2128cfb853baSMatthew G. Knepley + len - The length of the tuple 2129cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max) 2130cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition 2131cfb853baSMatthew G. Knepley 2132cfb853baSMatthew G. Knepley Output Parameter: 213320f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max` 2134cfb853baSMatthew G. Knepley 2135cfb853baSMatthew G. Knepley Level: developer 2136cfb853baSMatthew G. Knepley 213720f4b53cSBarry Smith Note: 213820f4b53cSBarry Smith Ordering is lexicographic with lowest index as least significant in ordering. 213920f4b53cSBarry 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}. 214020f4b53cSBarry Smith 2141cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal() 2142cfb853baSMatthew G. Knepley */ 2143cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[]) 2144cfb853baSMatthew G. Knepley { 2145cfb853baSMatthew G. Knepley PetscInt i; 2146cfb853baSMatthew G. Knepley 2147cfb853baSMatthew G. Knepley PetscFunctionBegin; 2148cfb853baSMatthew G. Knepley for (i = 0; i < len; ++i) { 2149cfb853baSMatthew G. Knepley if (tup[i] < max[i] - 1) { 2150cfb853baSMatthew G. Knepley break; 2151cfb853baSMatthew G. Knepley } else { 2152cfb853baSMatthew G. Knepley tup[i] = 0; 2153cfb853baSMatthew G. Knepley } 2154cfb853baSMatthew G. Knepley } 2155cfb853baSMatthew G. Knepley if (i == len) tup[i - 1] = max[i - 1]; 2156cfb853baSMatthew G. Knepley else ++tup[i]; 21573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2158cfb853baSMatthew G. Knepley } 2159cfb853baSMatthew G. Knepley 2160cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[]) 2161cfb853baSMatthew G. Knepley { 21628d2ec52aSSatish Balay PetscInt idx = tup[len - 1]; 2163cfb853baSMatthew G. Knepley 21648d2ec52aSSatish Balay for (PetscInt i = len - 2; i >= 0; --i) { 2165cfb853baSMatthew G. Knepley idx *= max[i]; 2166cfb853baSMatthew G. Knepley idx += tup[i]; 2167cfb853baSMatthew G. Knepley } 2168cfb853baSMatthew G. Knepley return idx; 2169cfb853baSMatthew G. Knepley } 2170cfb853baSMatthew G. Knepley 21718d2ec52aSSatish Balay static void IndexToTuple_Private(PetscInt len, const PetscInt max[], PetscInt idx, PetscInt tup[]) 2172cfb853baSMatthew G. Knepley { 21738d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21748d2ec52aSSatish Balay tup[i] = idx % max[i]; 21758d2ec52aSSatish Balay idx = (idx - tup[i]) / max[i]; 21768d2ec52aSSatish Balay } 21778d2ec52aSSatish Balay } 21788d2ec52aSSatish Balay 21798d2ec52aSSatish Balay static void TupleToRanks_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt tup[], PetscInt ranks[]) 21808d2ec52aSSatish Balay { 21818d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21828d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 21838d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 21848d2ec52aSSatish Balay const PetscInt idx = (tup[i] < 0 ? max[i] + tup[i] : tup[i]) % max[i]; 21858d2ec52aSSatish Balay 21868d2ec52aSSatish Balay if (idx < rem * (div + 1)) ranks[i] = idx / (div + 1); 21878d2ec52aSSatish Balay else ranks[i] = rem + (idx - rem * (div + 1)) / div; 21888d2ec52aSSatish Balay } 21898d2ec52aSSatish Balay } 21908d2ec52aSSatish Balay 21918d2ec52aSSatish Balay static void RanksToSizes_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt ranks[], PetscInt sizes[]) 21928d2ec52aSSatish Balay { 21938d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21948d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 21958d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 21968d2ec52aSSatish Balay 21978d2ec52aSSatish Balay sizes[i] = ranks[i] < rem ? div + 1 : div; 21988d2ec52aSSatish Balay } 21998d2ec52aSSatish Balay } 22008d2ec52aSSatish Balay 22018d2ec52aSSatish Balay /* 22028d2ec52aSSatish 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. 22038d2ec52aSSatish Balay 22048d2ec52aSSatish 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. 22058d2ec52aSSatish Balay 22068d2ec52aSSatish 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. 2207dfe9cfe5SMatthew Knepley 2208dfe9cfe5SMatthew Knepley Parallel Layout: 2209dfe9cfe5SMatthew Knepley 2210dfe9cfe5SMatthew 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. 22118d2ec52aSSatish Balay */ 22128d2ec52aSSatish Balay static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], PetscInt overlap, const DMBoundaryType bd[]) 22138d2ec52aSSatish Balay { 22148d2ec52aSSatish Balay const PetscInt debug = ((DM_Plex *)dm->data)->printAdj; 22158d2ec52aSSatish Balay PetscSF sf; 2216cfb853baSMatthew G. Knepley Vec coordinates; 2217cfb853baSMatthew G. Knepley PetscSection coordSection; 2218cfb853baSMatthew G. Knepley DMLabel cutLabel = NULL; 2219cfb853baSMatthew G. Knepley PetscBool cutMarker = PETSC_FALSE; 2220cfb853baSMatthew G. Knepley PetscBool periodic = PETSC_FALSE; 22218d2ec52aSSatish Balay PetscInt numCells = 1; 22228d2ec52aSSatish Balay PetscInt numVertices = 1; 22238d2ec52aSSatish Balay PetscSFNode *remotes; 2224cfb853baSMatthew G. Knepley PetscScalar *coords; 22258d2ec52aSSatish Balay PetscInt *procs; // The number of processes along each dimension 22268d2ec52aSSatish Balay PetscInt *lrank; // Rank in each dimension, lrank[d] \in [0, procs[d]) 22278d2ec52aSSatish Balay PetscInt *ledges; // The number of edges along each dimension for this process 22288d2ec52aSSatish Balay PetscInt *vstart; // The first vertex along each dimension on this processes 22298d2ec52aSSatish Balay PetscInt *vertices; // The number of vertices along each dimension on this process 22308d2ec52aSSatish Balay PetscInt *rvert; // The global (not local) vertex number along each dimension 22318d2ec52aSSatish Balay PetscInt *rrank; // The rank along each dimension for the process owning rvert[] 22328d2ec52aSSatish Balay PetscInt *rvertices; // The number of vertices along each dimension for the process rrank[] 22338d2ec52aSSatish Balay PetscInt *vert, *vtmp, *supp, cone[2], *leaves; 22348d2ec52aSSatish Balay PetscInt cell = 0, coordSize, Nl = 0, Nl2 = 0; 22358d2ec52aSSatish Balay PetscMPIInt rank, size; 22368d2ec52aSSatish Balay MPI_Comm comm; 2237cfb853baSMatthew G. Knepley 2238cfb853baSMatthew G. Knepley PetscFunctionBegin; 22398d2ec52aSSatish Balay PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 22408d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_rank(comm, &rank)); 22418d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_size(comm, &size)); 2242cfb853baSMatthew G. Knepley PetscCall(DMSetDimension(dm, dim)); 22438d2ec52aSSatish Balay PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 22448d2ec52aSSatish Balay PetscCall(PetscCalloc4(dim, &procs, dim, &lrank, dim, &rrank, 2 * dim, &supp)); 22458d2ec52aSSatish Balay PetscCall(PetscCalloc7(dim, &ledges, dim, &vertices, dim, &rvertices, dim, &vert, dim, &rvert, dim, &vstart, dim, &vtmp)); 2246cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 2247cfb853baSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 22488d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE; 2249cfb853baSMatthew G. Knepley if (periodic && cutMarker) { 2250cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "periodic_cut")); 2251cfb853baSMatthew G. Knepley PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 2252cfb853baSMatthew G. Knepley } 22538d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, comm, PETSC_ERR_SUP, "Hypercubic mesh must be periodic now"); 22548d2ec52aSSatish Balay overlap = overlap == PETSC_DETERMINE ? 1 : overlap; 22558d2ec52aSSatish Balay PetscCheck(overlap >= 1, comm, PETSC_ERR_SUP, "Overlap %" PetscInt_FMT " must be greater than 0", overlap); 22568d2ec52aSSatish Balay if (size > 1) { 22578d2ec52aSSatish Balay PetscInt Npr = 1; 22588d2ec52aSSatish Balay 22598d2ec52aSSatish Balay // Make process grid 22608d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "Process grid:")); 22618d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22628d2ec52aSSatish Balay procs[d] = PetscRintReal(PetscPowReal(size, 1. / dim)); 22638d2ec52aSSatish Balay Npr *= procs[d]; 22648d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, " %" PetscInt_FMT, procs[d])); 22658d2ec52aSSatish Balay } 22668d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "\n")); 22678d2ec52aSSatish Balay PetscCheck(Npr == size, comm, PETSC_ERR_PLIB, "Process grid size %" PetscInt_FMT " != %d comm size", Npr, size); 22688d2ec52aSSatish Balay IndexToTuple_Private(dim, procs, rank, lrank); 22698d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22708d2ec52aSSatish Balay ledges[d] = edges[d] / procs[d] + (edges[d] % procs[d] > lrank[d] ? 1 : 0); 22718d2ec52aSSatish Balay vstart[d] = 0; 22728d2ec52aSSatish Balay for (PetscInt r = 0; r < lrank[d]; ++r) vstart[d] += edges[d] / procs[d] + (edges[d] % procs[d] > r ? 1 : 0); 22738d2ec52aSSatish Balay vstart[d] -= overlap; // For halo 22748d2ec52aSSatish Balay } 22758d2ec52aSSatish Balay } else { 22768d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22778d2ec52aSSatish Balay procs[d] = 1; 22788d2ec52aSSatish Balay ledges[d] = edges[d]; 22798d2ec52aSSatish Balay } 22808d2ec52aSSatish Balay } 22818d2ec52aSSatish Balay // Calculate local patch size 22828d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22838d2ec52aSSatish Balay vertices[d] = ledges[d] + (procs[d] > 1 ? 2 * overlap : 0); 2284cfb853baSMatthew G. Knepley numVertices *= vertices[d]; 2285cfb853baSMatthew G. Knepley } 2286cfb853baSMatthew G. Knepley numCells = numVertices * dim; 2287cfb853baSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 22888d2ec52aSSatish Balay for (PetscInt c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2)); 22898d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim)); 2290cfb853baSMatthew G. Knepley PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */ 2291cfb853baSMatthew G. Knepley /* Build cell cones and vertex supports */ 2292cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "celltype")); 22938d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Topology for rank %d:\n", rank)); 2294cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2295cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells; 2296cfb853baSMatthew G. Knepley PetscInt s = 0; 22978d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2298cfb853baSMatthew G. Knepley 22998d2ec52aSSatish Balay if (debug) { 23008d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 23018d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d])); 23028d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 23038d2ec52aSSatish Balay } 2304cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT)); 23058d2ec52aSSatish Balay // Define edge cones 23068d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23078d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2308cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + 1) % vertices[d]; 2309cfb853baSMatthew G. Knepley cone[0] = vertex; 2310cfb853baSMatthew G. Knepley cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells; 23118d2ec52aSSatish Balay if (debug) { 23128d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ":", cone[1])); 23138d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vtmp[e])); 23148d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 23158d2ec52aSSatish Balay } 2316cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, cell, cone)); 2317cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT)); 23188d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1])); 2319cfb853baSMatthew G. Knepley ++cell; 23208d2ec52aSSatish Balay // Shared vertices are any in the first or last overlap layers 23218d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 2322cfb853baSMatthew G. Knepley } 23238d2ec52aSSatish Balay if (size > 1 && leaf) ++Nl; 23248d2ec52aSSatish Balay // Define vertex supports 23258d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23268d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2327cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + vertices[d] - 1) % vertices[d]; 2328cfb853baSMatthew G. Knepley supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d; 2329cfb853baSMatthew G. Knepley supp[s++] = (vertex - numCells) * dim + d; 2330cfb853baSMatthew G. Knepley PetscCall(DMPlexSetSupport(dm, vertex, supp)); 2331cfb853baSMatthew G. Knepley } 2332cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2333cfb853baSMatthew G. Knepley } 23348d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2335cfb853baSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 23368d2ec52aSSatish Balay // Allocate for SF 23378d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &leaves)); 23388d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &remotes)); 23398d2ec52aSSatish Balay // Build coordinates 2340cfb853baSMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 2341cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(coordSection, 1)); 2342cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 2343cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 23448d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) { 2345cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetDof(coordSection, v, dim)); 2346cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 2347cfb853baSMatthew G. Knepley } 2348cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetUp(coordSection)); 2349cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 23508d2ec52aSSatish Balay PetscCall(VecCreate(comm, &coordinates)); 2351cfb853baSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 2352cfb853baSMatthew G. Knepley PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 2353cfb853baSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinates, dim)); 2354cfb853baSMatthew G. Knepley PetscCall(VecSetType(coordinates, VECSTANDARD)); 2355cfb853baSMatthew G. Knepley PetscCall(VecGetArray(coordinates, &coords)); 23568d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Geometry for rank %d:\n", rank)); 23578d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) vert[d] = 0; 2358cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2359cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert); 23608d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2361cfb853baSMatthew G. Knepley 23628d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23638d2ec52aSSatish Balay coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / edges[d]) * (vert[d] + vstart[d]); 23648d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 23658d2ec52aSSatish Balay } 23668d2ec52aSSatish Balay if (size > 1 && leaf) { 23678d2ec52aSSatish Balay PetscInt rnumCells = 1; 23688d2ec52aSSatish Balay 23698d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) rvert[d] = vert[d] + vstart[d]; 23708d2ec52aSSatish Balay TupleToRanks_Private(dim, edges, procs, rvert, rrank); 23718d2ec52aSSatish Balay leaves[Nl2] = vertex + numCells; 23728d2ec52aSSatish Balay remotes[Nl2].rank = TupleToIndex_Private(dim, procs, rrank); 23738d2ec52aSSatish Balay RanksToSizes_Private(dim, edges, procs, rrank, rvertices); 23748d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23758d2ec52aSSatish Balay rvertices[d] += 2 * overlap; // Add halo 23768d2ec52aSSatish Balay rnumCells *= rvertices[d]; 23778d2ec52aSSatish Balay } 23788d2ec52aSSatish Balay rnumCells *= dim; 23798d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23808d2ec52aSSatish Balay const PetscInt diff = rrank[d] - lrank[d]; 23818d2ec52aSSatish Balay 23828d2ec52aSSatish Balay if (!diff) rvert[d] = vert[d]; // Vertex is local 23838d2ec52aSSatish Balay else if (rvert[d] < 0) rvert[d] = rvertices[d] - 1 + rvert[d]; // Wrap around at the bottom 23848d2ec52aSSatish Balay else if (rvert[d] >= edges[d]) rvert[d] = rvert[d] - edges[d] + 1; // Wrap around at the top 23858d2ec52aSSatish Balay else if (diff == -1) rvert[d] = rvertices[d] - 1 + (vert[d] - overlap); 23868d2ec52aSSatish Balay else if (diff == 1) rvert[d] = (vertices[d] - vert[d] - 1) + overlap; 23878d2ec52aSSatish Balay else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Process distance %" PetscInt_FMT " in direction %" PetscInt_FMT " should not be possible", diff, d); 23888d2ec52aSSatish Balay } 23898d2ec52aSSatish Balay remotes[Nl2].index = TupleToIndex_Private(dim, rvertices, rvert) + rnumCells; 23908d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Shared Vertex %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", leaves[Nl2], remotes[Nl2].rank, remotes[Nl2].index)); 23918d2ec52aSSatish Balay ++Nl2; 23928d2ec52aSSatish Balay } 23938d2ec52aSSatish Balay if (debug) { 23948d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 23958d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d] + vstart[d])); 23968d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %g", (double)PetscRealPart(coords[vertex * dim + d]))); 23978d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 23988d2ec52aSSatish Balay } 2399cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2400cfb853baSMatthew G. Knepley } 24018d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2402cfb853baSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &coords)); 2403cfb853baSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 2404cfb853baSMatthew G. Knepley PetscCall(VecDestroy(&coordinates)); 24058d2ec52aSSatish Balay // Build SF 24068d2ec52aSSatish Balay PetscCheck(Nl == Nl2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Initial number of leaves %" PetscInt_FMT " != %" PetscInt_FMT " final number", Nl, Nl2); 24078d2ec52aSSatish Balay PetscCall(DMGetPointSF(dm, &sf)); 24088d2ec52aSSatish Balay PetscCall(PetscSFSetGraph(sf, numCells + numVertices, Nl, leaves, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 24098d2ec52aSSatish Balay if (debug) PetscCall(PetscSFView(sf, PETSC_VIEWER_STDOUT_WORLD)); 2410cfb853baSMatthew G. Knepley //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper)); 2411cfb853baSMatthew G. Knepley // Attach the extent 2412cfb853baSMatthew G. Knepley { 2413cfb853baSMatthew G. Knepley PetscContainer c; 24148d2ec52aSSatish Balay PetscInt *extent, *lextent; 2415cfb853baSMatthew G. Knepley 2416cfb853baSMatthew G. Knepley PetscCall(PetscMalloc1(dim, &extent)); 24178d2ec52aSSatish Balay PetscCall(PetscMalloc1(dim, &lextent)); 24188d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 24198d2ec52aSSatish Balay extent[d] = edges[d]; 24208d2ec52aSSatish Balay lextent[d] = ledges[d]; 24218d2ec52aSSatish Balay } 2422cfb853baSMatthew G. Knepley PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 242349abdd8aSBarry Smith PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 2424cfb853baSMatthew G. Knepley PetscCall(PetscContainerSetPointer(c, extent)); 2425cfb853baSMatthew G. Knepley PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c)); 2426cfb853baSMatthew G. Knepley PetscCall(PetscContainerDestroy(&c)); 24278d2ec52aSSatish Balay PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 24288d2ec52aSSatish Balay PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 24298d2ec52aSSatish Balay PetscCall(PetscContainerSetPointer(c, lextent)); 24308d2ec52aSSatish Balay PetscCall(PetscObjectCompose((PetscObject)dm, "_lextent", (PetscObject)c)); 24318d2ec52aSSatish Balay PetscCall(PetscContainerDestroy(&c)); 2432cfb853baSMatthew G. Knepley } 24338d2ec52aSSatish Balay PetscCall(PetscFree4(procs, lrank, rrank, supp)); 24348d2ec52aSSatish Balay PetscCall(PetscFree7(ledges, vertices, rvertices, vert, rvert, vstart, vtmp)); 24353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2436cfb853baSMatthew G. Knepley } 2437cfb853baSMatthew G. Knepley 2438cfb853baSMatthew G. Knepley /*@C 2439aaa8cc7dSPierre Jolivet DMPlexCreateHypercubicMesh - Creates a periodic mesh on the tensor product of unit intervals using only vertices and edges. 2440cfb853baSMatthew G. Knepley 2441cfb853baSMatthew G. Knepley Collective 2442cfb853baSMatthew G. Knepley 2443cfb853baSMatthew G. Knepley Input Parameters: 24448d2ec52aSSatish Balay + comm - The communicator for the `DM` object 2445cfb853baSMatthew G. Knepley . dim - The spatial dimension 244620f4b53cSBarry Smith . edges - Number of edges per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 244720f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 24488d2ec52aSSatish Balay . upper - The upper right corner, or `NULL` for (1, 1, 1) 24498d2ec52aSSatish Balay - overlap - The number of vertices in each direction to include in the overlap (default is 1) 2450cfb853baSMatthew G. Knepley 2451cfb853baSMatthew G. Knepley Output Parameter: 2452cfb853baSMatthew G. Knepley . dm - The DM object 2453cfb853baSMatthew G. Knepley 245420f4b53cSBarry Smith Level: beginner 245520f4b53cSBarry Smith 245620f4b53cSBarry Smith Note: 245720f4b53cSBarry Smith If you want to customize this mesh using options, you just need to 245820f4b53cSBarry Smith .vb 245920f4b53cSBarry Smith DMCreate(comm, &dm); 246020f4b53cSBarry Smith DMSetType(dm, DMPLEX); 246120f4b53cSBarry Smith DMSetFromOptions(dm); 246220f4b53cSBarry Smith .ve 246320f4b53cSBarry Smith and use the options on the `DMSetFromOptions()` page. 2464cfb853baSMatthew G. Knepley 2465cfb853baSMatthew G. Knepley The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively, 246620f4b53cSBarry Smith .vb 246720f4b53cSBarry Smith 18--0-19--2-20--4-18 246820f4b53cSBarry Smith | | | | 246920f4b53cSBarry Smith 13 15 17 13 247020f4b53cSBarry Smith | | | | 247120f4b53cSBarry Smith 24-12-25-14-26-16-24 247220f4b53cSBarry Smith | | | | 247320f4b53cSBarry Smith 7 9 11 7 247420f4b53cSBarry Smith | | | | 247520f4b53cSBarry Smith 21--6-22--8-23-10-21 247620f4b53cSBarry Smith | | | | 247720f4b53cSBarry Smith 1 3 5 1 247820f4b53cSBarry Smith | | | | 247920f4b53cSBarry Smith 18--0-19--2-20--4-18 248020f4b53cSBarry Smith .ve 2481cfb853baSMatthew G. Knepley 248276fbde31SPierre Jolivet .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 2483cfb853baSMatthew G. Knepley @*/ 24848d2ec52aSSatish Balay PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], PetscInt overlap, DM *dm) 2485cfb853baSMatthew G. Knepley { 2486cfb853baSMatthew G. Knepley PetscInt *edg; 2487cfb853baSMatthew G. Knepley PetscReal *low, *upp; 2488cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 2489cfb853baSMatthew G. Knepley PetscInt d; 2490cfb853baSMatthew G. Knepley 2491cfb853baSMatthew G. Knepley PetscFunctionBegin; 2492cfb853baSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 2493cfb853baSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 2494cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt)); 2495cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 2496cfb853baSMatthew G. Knepley edg[d] = edges ? edges[d] : 1; 2497cfb853baSMatthew G. Knepley low[d] = lower ? lower[d] : 0.; 2498cfb853baSMatthew G. Knepley upp[d] = upper ? upper[d] : 1.; 2499cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 2500cfb853baSMatthew G. Knepley } 25018d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, overlap, bdt)); 2502cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edg, low, upp, bdt)); 25033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2504cfb853baSMatthew G. Knepley } 2505cfb853baSMatthew G. Knepley 2506cc4c1da9SBarry Smith /*@ 2507a1cb98faSBarry Smith DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database. 2508a9074c1eSMatthew G. Knepley 250920f4b53cSBarry Smith Logically Collective 2510a9074c1eSMatthew G. Knepley 2511a9074c1eSMatthew G. Knepley Input Parameters: 251220f4b53cSBarry Smith + dm - the `DM` context 2513a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 2514a9074c1eSMatthew G. Knepley 2515a1cb98faSBarry Smith Level: advanced 2516a1cb98faSBarry Smith 2517a1cb98faSBarry Smith Note: 2518a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 2519a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 2520a9074c1eSMatthew G. Knepley 25211cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()` 2522a9074c1eSMatthew G. Knepley @*/ 2523d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 2524d71ae5a4SJacob Faibussowitsch { 2525a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2526a9074c1eSMatthew G. Knepley 2527a9074c1eSMatthew G. Knepley PetscFunctionBegin; 2528a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25299566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 25309566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 25313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2532a9074c1eSMatthew G. Knepley } 2533a9074c1eSMatthew G. Knepley 25349318fe57SMatthew G. Knepley /* Remap geometry to cylinder 253561a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 253661a622f3SMatthew G. Knepley 25379318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 25389318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 25399318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 25400510c589SMatthew G. Knepley 25419318fe57SMatthew G. Knepley phi = arctan(y/x) 25429318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 25439318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 25440510c589SMatthew G. Knepley 25459318fe57SMatthew G. Knepley so we remap them using 25460510c589SMatthew G. Knepley 25479318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 25489318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 25490510c589SMatthew G. Knepley 25509318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 25519318fe57SMatthew G. Knepley */ 2552d71ae5a4SJacob 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[]) 2553d71ae5a4SJacob Faibussowitsch { 25549318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 25559318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 255622cc497dSMatthew G. Knepley 25579318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 25589318fe57SMatthew G. Knepley f0[0] = u[0]; 25599318fe57SMatthew G. Knepley f0[1] = u[1]; 25609318fe57SMatthew G. Knepley } else { 25619318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 25620510c589SMatthew G. Knepley 25639318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 25649318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 25659318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 25669318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 25679318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 25689318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 25699318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 25709318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 25719318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 25729318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 25739318fe57SMatthew G. Knepley } else { 25749318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 25759318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 25769318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 25779318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 25789318fe57SMatthew G. Knepley } 25799318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 25809318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 25819318fe57SMatthew G. Knepley } 25829318fe57SMatthew G. Knepley f0[2] = u[2]; 25839318fe57SMatthew G. Knepley } 25840510c589SMatthew G. Knepley 258549704ca5SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ, PetscInt Nr) 2586d71ae5a4SJacob Faibussowitsch { 25870510c589SMatthew G. Knepley const PetscInt dim = 3; 25889318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 2589d8c47e87SMatthew G. Knepley PetscMPIInt rank; 25900510c589SMatthew G. Knepley 25910510c589SMatthew G. Knepley PetscFunctionBegin; 259246139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 25939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 25949566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 25950510c589SMatthew G. Knepley /* Create topology */ 25960510c589SMatthew G. Knepley { 25970510c589SMatthew G. Knepley PetscInt cone[8], c; 25980510c589SMatthew G. Knepley 2599dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 2600dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 2601006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 2602ae8bcbbbSMatthew G. Knepley numCells *= 3; 2603dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 2604006a8963SMatthew G. Knepley } 26059566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 26069566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 26079566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 2608dd400576SPatrick Sanan if (rank == 0) { 2609006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 26109371c9d4SSatish Balay cone[0] = 15; 26119371c9d4SSatish Balay cone[1] = 18; 26129371c9d4SSatish Balay cone[2] = 17; 26139371c9d4SSatish Balay cone[3] = 16; 26149371c9d4SSatish Balay cone[4] = 31; 26159371c9d4SSatish Balay cone[5] = 32; 26169371c9d4SSatish Balay cone[6] = 33; 26179371c9d4SSatish Balay cone[7] = 34; 26189566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 26199371c9d4SSatish Balay cone[0] = 16; 26209371c9d4SSatish Balay cone[1] = 17; 26219371c9d4SSatish Balay cone[2] = 24; 26229371c9d4SSatish Balay cone[3] = 23; 26239371c9d4SSatish Balay cone[4] = 32; 26249371c9d4SSatish Balay cone[5] = 36; 26259371c9d4SSatish Balay cone[6] = 37; 26269371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 26279566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 26289371c9d4SSatish Balay cone[0] = 18; 26299371c9d4SSatish Balay cone[1] = 27; 26309371c9d4SSatish Balay cone[2] = 24; 26319371c9d4SSatish Balay cone[3] = 17; 26329371c9d4SSatish Balay cone[4] = 34; 26339371c9d4SSatish Balay cone[5] = 33; 26349371c9d4SSatish Balay cone[6] = 37; 26359371c9d4SSatish Balay cone[7] = 38; 26369566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 26379371c9d4SSatish Balay cone[0] = 29; 26389371c9d4SSatish Balay cone[1] = 27; 26399371c9d4SSatish Balay cone[2] = 18; 26409371c9d4SSatish Balay cone[3] = 15; 26419371c9d4SSatish Balay cone[4] = 35; 26429371c9d4SSatish Balay cone[5] = 31; 26439371c9d4SSatish Balay cone[6] = 34; 26449371c9d4SSatish Balay cone[7] = 38; 26459566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 26469371c9d4SSatish Balay cone[0] = 29; 26479371c9d4SSatish Balay cone[1] = 15; 26489371c9d4SSatish Balay cone[2] = 16; 26499371c9d4SSatish Balay cone[3] = 23; 26509371c9d4SSatish Balay cone[4] = 35; 26519371c9d4SSatish Balay cone[5] = 36; 26529371c9d4SSatish Balay cone[6] = 32; 26539371c9d4SSatish Balay cone[7] = 31; 26549566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2655006a8963SMatthew G. Knepley 26569371c9d4SSatish Balay cone[0] = 31; 26579371c9d4SSatish Balay cone[1] = 34; 26589371c9d4SSatish Balay cone[2] = 33; 26599371c9d4SSatish Balay cone[3] = 32; 26609371c9d4SSatish Balay cone[4] = 19; 26619371c9d4SSatish Balay cone[5] = 22; 26629371c9d4SSatish Balay cone[6] = 21; 26639371c9d4SSatish Balay cone[7] = 20; 26649566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 26659371c9d4SSatish Balay cone[0] = 32; 26669371c9d4SSatish Balay cone[1] = 33; 26679371c9d4SSatish Balay cone[2] = 37; 26689371c9d4SSatish Balay cone[3] = 36; 26699371c9d4SSatish Balay cone[4] = 22; 26709371c9d4SSatish Balay cone[5] = 25; 26719371c9d4SSatish Balay cone[6] = 26; 26729371c9d4SSatish Balay cone[7] = 21; 26739566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 26749371c9d4SSatish Balay cone[0] = 34; 26759371c9d4SSatish Balay cone[1] = 38; 26769371c9d4SSatish Balay cone[2] = 37; 26779371c9d4SSatish Balay cone[3] = 33; 26789371c9d4SSatish Balay cone[4] = 20; 26799371c9d4SSatish Balay cone[5] = 21; 26809371c9d4SSatish Balay cone[6] = 26; 26819371c9d4SSatish Balay cone[7] = 28; 26829566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 26839371c9d4SSatish Balay cone[0] = 35; 26849371c9d4SSatish Balay cone[1] = 38; 26859371c9d4SSatish Balay cone[2] = 34; 26869371c9d4SSatish Balay cone[3] = 31; 26879371c9d4SSatish Balay cone[4] = 30; 26889371c9d4SSatish Balay cone[5] = 19; 26899371c9d4SSatish Balay cone[6] = 20; 26909371c9d4SSatish Balay cone[7] = 28; 26919566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 26929371c9d4SSatish Balay cone[0] = 35; 26939371c9d4SSatish Balay cone[1] = 31; 26949371c9d4SSatish Balay cone[2] = 32; 26959371c9d4SSatish Balay cone[3] = 36; 26969371c9d4SSatish Balay cone[4] = 30; 26979371c9d4SSatish Balay cone[5] = 25; 26989371c9d4SSatish Balay cone[6] = 22; 26999371c9d4SSatish Balay cone[7] = 19; 27009566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 2701ae8bcbbbSMatthew G. Knepley 27029371c9d4SSatish Balay cone[0] = 19; 27039371c9d4SSatish Balay cone[1] = 20; 27049371c9d4SSatish Balay cone[2] = 21; 27059371c9d4SSatish Balay cone[3] = 22; 27069371c9d4SSatish Balay cone[4] = 15; 27079371c9d4SSatish Balay cone[5] = 16; 27089371c9d4SSatish Balay cone[6] = 17; 27099371c9d4SSatish Balay cone[7] = 18; 27109566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 27119371c9d4SSatish Balay cone[0] = 22; 27129371c9d4SSatish Balay cone[1] = 21; 27139371c9d4SSatish Balay cone[2] = 26; 27149371c9d4SSatish Balay cone[3] = 25; 27159371c9d4SSatish Balay cone[4] = 16; 27169371c9d4SSatish Balay cone[5] = 23; 27179371c9d4SSatish Balay cone[6] = 24; 27189371c9d4SSatish Balay cone[7] = 17; 27199566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 27209371c9d4SSatish Balay cone[0] = 20; 27219371c9d4SSatish Balay cone[1] = 28; 27229371c9d4SSatish Balay cone[2] = 26; 27239371c9d4SSatish Balay cone[3] = 21; 27249371c9d4SSatish Balay cone[4] = 18; 27259371c9d4SSatish Balay cone[5] = 17; 27269371c9d4SSatish Balay cone[6] = 24; 27279371c9d4SSatish Balay cone[7] = 27; 27289566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 27299371c9d4SSatish Balay cone[0] = 30; 27309371c9d4SSatish Balay cone[1] = 28; 27319371c9d4SSatish Balay cone[2] = 20; 27329371c9d4SSatish Balay cone[3] = 19; 27339371c9d4SSatish Balay cone[4] = 29; 27349371c9d4SSatish Balay cone[5] = 15; 27359371c9d4SSatish Balay cone[6] = 18; 27369371c9d4SSatish Balay cone[7] = 27; 27379566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 27389371c9d4SSatish Balay cone[0] = 30; 27399371c9d4SSatish Balay cone[1] = 19; 27409371c9d4SSatish Balay cone[2] = 22; 27419371c9d4SSatish Balay cone[3] = 25; 27429371c9d4SSatish Balay cone[4] = 29; 27439371c9d4SSatish Balay cone[5] = 23; 27449371c9d4SSatish Balay cone[6] = 16; 27459371c9d4SSatish Balay cone[7] = 15; 27469566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 2747006a8963SMatthew G. Knepley } else { 27489371c9d4SSatish Balay cone[0] = 5; 27499371c9d4SSatish Balay cone[1] = 8; 27509371c9d4SSatish Balay cone[2] = 7; 27519371c9d4SSatish Balay cone[3] = 6; 27529371c9d4SSatish Balay cone[4] = 9; 27539371c9d4SSatish Balay cone[5] = 12; 27549371c9d4SSatish Balay cone[6] = 11; 27559371c9d4SSatish Balay cone[7] = 10; 27569566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 27579371c9d4SSatish Balay cone[0] = 6; 27589371c9d4SSatish Balay cone[1] = 7; 27599371c9d4SSatish Balay cone[2] = 14; 27609371c9d4SSatish Balay cone[3] = 13; 27619371c9d4SSatish Balay cone[4] = 12; 27629371c9d4SSatish Balay cone[5] = 15; 27639371c9d4SSatish Balay cone[6] = 16; 27649371c9d4SSatish Balay cone[7] = 11; 27659566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 27669371c9d4SSatish Balay cone[0] = 8; 27679371c9d4SSatish Balay cone[1] = 17; 27689371c9d4SSatish Balay cone[2] = 14; 27699371c9d4SSatish Balay cone[3] = 7; 27709371c9d4SSatish Balay cone[4] = 10; 27719371c9d4SSatish Balay cone[5] = 11; 27729371c9d4SSatish Balay cone[6] = 16; 27739371c9d4SSatish Balay cone[7] = 18; 27749566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 27759371c9d4SSatish Balay cone[0] = 19; 27769371c9d4SSatish Balay cone[1] = 17; 27779371c9d4SSatish Balay cone[2] = 8; 27789371c9d4SSatish Balay cone[3] = 5; 27799371c9d4SSatish Balay cone[4] = 20; 27809371c9d4SSatish Balay cone[5] = 9; 27819371c9d4SSatish Balay cone[6] = 10; 27829371c9d4SSatish Balay cone[7] = 18; 27839566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 27849371c9d4SSatish Balay cone[0] = 19; 27859371c9d4SSatish Balay cone[1] = 5; 27869371c9d4SSatish Balay cone[2] = 6; 27879371c9d4SSatish Balay cone[3] = 13; 27889371c9d4SSatish Balay cone[4] = 20; 27899371c9d4SSatish Balay cone[5] = 15; 27909371c9d4SSatish Balay cone[6] = 12; 27919371c9d4SSatish Balay cone[7] = 9; 27929566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2793006a8963SMatthew G. Knepley } 2794d8c47e87SMatthew G. Knepley } 27959566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 27969566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 27970510c589SMatthew G. Knepley } 2798dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 27990510c589SMatthew G. Knepley { 28000510c589SMatthew G. Knepley Vec coordinates; 28010510c589SMatthew G. Knepley PetscSection coordSection; 28020510c589SMatthew G. Knepley PetscScalar *coords; 28030510c589SMatthew G. Knepley PetscInt coordSize, v; 28040510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 28050510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 28060510c589SMatthew G. Knepley 28070510c589SMatthew G. Knepley /* Build coordinates */ 28089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 28099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 28109566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 28119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 28120510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 28139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 28149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 28150510c589SMatthew G. Knepley } 28169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 28179566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 28189566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 28199566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 28209566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 28219566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 28229566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 28239566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 2824dd400576SPatrick Sanan if (rank == 0) { 28259371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 28269371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 28279371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 28289371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 28299371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 28309371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 28319371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 28329371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 28339371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 28349371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 28359371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 28369371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 28379371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 28389371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 28399371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 28409371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 28419371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 28429371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 28439371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 28449371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 28459371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 28469371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 28479371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 28489371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 28499371c9d4SSatish Balay coords[8 * dim + 0] = dis; 28509371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 28519371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 28529371c9d4SSatish Balay coords[9 * dim + 0] = dis; 28539371c9d4SSatish Balay coords[9 * dim + 1] = dis; 28549371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 28559371c9d4SSatish Balay coords[10 * dim + 0] = dis; 28569371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 28579371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 28589371c9d4SSatish Balay coords[11 * dim + 0] = dis; 28599371c9d4SSatish Balay coords[11 * dim + 1] = dis; 28609371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 28619371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 28629371c9d4SSatish Balay coords[12 * dim + 1] = dis; 28639371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 28649371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 28659371c9d4SSatish Balay coords[13 * dim + 1] = dis; 28669371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 28679371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 28689371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 28699371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 28709371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 28719371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 28729371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 2873ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 28749371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 28759371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 28769371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 28779371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 28789371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 28799371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 28809371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 28819371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 28829371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 28839371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 28849371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 28859371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 28869371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 28879371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 28889371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 28899371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 28909371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 28919371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 28929371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 28939371c9d4SSatish Balay coords[22 * dim + 1] = dis; 28949371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 28959371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 28969371c9d4SSatish Balay coords[23 * dim + 1] = dis; 28979371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 2898ae8bcbbbSMatthew G. Knepley } 2899d8c47e87SMatthew G. Knepley } 29009566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 29019566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 29029566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 29030510c589SMatthew G. Knepley } 2904006a8963SMatthew G. Knepley /* Create periodicity */ 2905006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 29066858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 29076858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 2908006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 2909ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 29106858538eSMatthew G. Knepley PetscInt numZCells = 3; 2911006a8963SMatthew G. Knepley 29126858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 29136858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 29144fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 2915006a8963SMatthew G. Knepley } 2916dbc1dc17SMatthew G. Knepley { 29179318fe57SMatthew G. Knepley DM cdm; 29189318fe57SMatthew G. Knepley PetscDS cds; 29199318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 2920dbc1dc17SMatthew G. Knepley 2921e65c294aSksagiyam PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE)); 29229566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 29239566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 29249566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 2925dbc1dc17SMatthew G. Knepley } 292646139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 292746139095SJed Brown 29289318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 29299566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 293049704ca5SMatthew G. Knepley 293149704ca5SMatthew G. Knepley char oldprefix[PETSC_MAX_PATH_LEN]; 293249704ca5SMatthew G. Knepley const char *prefix; 293349704ca5SMatthew G. Knepley 293449704ca5SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 293549704ca5SMatthew G. Knepley PetscCall(PetscStrncpy(oldprefix, prefix, PETSC_MAX_PATH_LEN)); 293649704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, "petsc_cyl_ref_")); 293749704ca5SMatthew G. Knepley for (PetscInt r = 0; r < PetscMax(0, Nr); ++r) { 293849704ca5SMatthew G. Knepley DM rdm; 293949704ca5SMatthew G. Knepley 294049704ca5SMatthew G. Knepley PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 294149704ca5SMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &rdm)); 294249704ca5SMatthew G. Knepley } 294349704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldprefix)); 294449704ca5SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, snapToCylinder)); 294549704ca5SMatthew G. Knepley 294649704ca5SMatthew G. Knepley DMLabel bdlabel, edgelabel; 294749704ca5SMatthew G. Knepley IS faceIS; 294849704ca5SMatthew G. Knepley const PetscInt *faces; 294949704ca5SMatthew G. Knepley PetscInt Nf; 295049704ca5SMatthew G. Knepley 295149704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 295249704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 295349704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "generatrix")); 295449704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "generatrix", &edgelabel)); 295549704ca5SMatthew G. Knepley PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 295649704ca5SMatthew G. Knepley // Remove faces on top and bottom 295749704ca5SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(bdlabel, 1, &faceIS)); 2958ba1b3593SJeremy L Thompson if (faceIS) { 295949704ca5SMatthew G. Knepley PetscCall(ISGetLocalSize(faceIS, &Nf)); 296049704ca5SMatthew G. Knepley PetscCall(ISGetIndices(faceIS, &faces)); 296149704ca5SMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 296249704ca5SMatthew G. Knepley PetscReal vol, normal[3]; 296349704ca5SMatthew G. Knepley 296449704ca5SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFVM(dm, faces[f], &vol, NULL, normal)); 296549704ca5SMatthew G. Knepley if (PetscAbsReal(normal[2]) < PETSC_SMALL) PetscCall(DMLabelSetValue(edgelabel, faces[f], 1)); 296649704ca5SMatthew G. Knepley } 296749704ca5SMatthew G. Knepley PetscCall(ISRestoreIndices(faceIS, &faces)); 296849704ca5SMatthew G. Knepley PetscCall(ISDestroy(&faceIS)); 2969ba1b3593SJeremy L Thompson } 297049704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, bdlabel)); 297149704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, edgelabel)); 29723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29730510c589SMatthew G. Knepley } 29740510c589SMatthew G. Knepley 297524119c2aSMatthew G. Knepley /*@ 29769318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 297724119c2aSMatthew G. Knepley 2978d083f849SBarry Smith Collective 297924119c2aSMatthew G. Knepley 298024119c2aSMatthew G. Knepley Input Parameters: 2981a1cb98faSBarry Smith + comm - The communicator for the `DM` object 298249704ca5SMatthew G. Knepley . periodicZ - The boundary type for the Z direction 298349704ca5SMatthew G. Knepley - Nr - The number of refinements to carry out 298424119c2aSMatthew G. Knepley 298524119c2aSMatthew G. Knepley Output Parameter: 298620f4b53cSBarry Smith . dm - The `DM` object 298724119c2aSMatthew G. Knepley 298824119c2aSMatthew G. Knepley Level: beginner 298924119c2aSMatthew G. Knepley 2990a1cb98faSBarry Smith Note: 2991a4e35b19SJacob Faibussowitsch Here is the output numbering looking from the bottom of the cylinder\: 2992a1cb98faSBarry Smith .vb 2993a1cb98faSBarry Smith 17-----14 2994a1cb98faSBarry Smith | | 2995a1cb98faSBarry Smith | 2 | 2996a1cb98faSBarry Smith | | 2997a1cb98faSBarry Smith 17-----8-----7-----14 2998a1cb98faSBarry Smith | | | | 2999a1cb98faSBarry Smith | 3 | 0 | 1 | 3000a1cb98faSBarry Smith | | | | 3001a1cb98faSBarry Smith 19-----5-----6-----13 3002a1cb98faSBarry Smith | | 3003a1cb98faSBarry Smith | 4 | 3004a1cb98faSBarry Smith | | 3005a1cb98faSBarry Smith 19-----13 3006a1cb98faSBarry Smith 3007a1cb98faSBarry Smith and up through the top 3008a1cb98faSBarry Smith 3009a1cb98faSBarry Smith 18-----16 3010a1cb98faSBarry Smith | | 3011a1cb98faSBarry Smith | 2 | 3012a1cb98faSBarry Smith | | 3013a1cb98faSBarry Smith 18----10----11-----16 3014a1cb98faSBarry Smith | | | | 3015a1cb98faSBarry Smith | 3 | 0 | 1 | 3016a1cb98faSBarry Smith | | | | 3017a1cb98faSBarry Smith 20-----9----12-----15 3018a1cb98faSBarry Smith | | 3019a1cb98faSBarry Smith | 4 | 3020a1cb98faSBarry Smith | | 3021a1cb98faSBarry Smith 20-----15 3022a1cb98faSBarry Smith .ve 3023a1cb98faSBarry Smith 30241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 302524119c2aSMatthew G. Knepley @*/ 302649704ca5SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, PetscInt Nr, DM *dm) 3027d71ae5a4SJacob Faibussowitsch { 30289318fe57SMatthew G. Knepley PetscFunctionBegin; 302949704ca5SMatthew G. Knepley PetscAssertPointer(dm, 4); 30309566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 30319566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 303249704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ, Nr)); 30333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30349318fe57SMatthew G. Knepley } 30359318fe57SMatthew G. Knepley 3036d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 3037d71ae5a4SJacob Faibussowitsch { 303824119c2aSMatthew G. Knepley const PetscInt dim = 3; 3039412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 30409fe9f049SMatthew G. Knepley PetscMPIInt rank; 304124119c2aSMatthew G. Knepley 304224119c2aSMatthew G. Knepley PetscFunctionBegin; 304363a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 304446139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 30459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 30469566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 3047412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 30489566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 304924119c2aSMatthew G. Knepley /* Create topology */ 305024119c2aSMatthew G. Knepley { 305124119c2aSMatthew G. Knepley PetscInt cone[6], c; 305224119c2aSMatthew G. Knepley 3053dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 3054dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 30559566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 30569566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 30579566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 305824119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 30599371c9d4SSatish Balay cone[0] = c + n * 1; 30609371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 30619371c9d4SSatish Balay cone[2] = 0 + 3 * n; 30629371c9d4SSatish Balay cone[3] = c + n * 2; 30639371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 30649371c9d4SSatish Balay cone[5] = 1 + 3 * n; 30659566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 30669566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 306724119c2aSMatthew G. Knepley } 30689566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 30699566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 307024119c2aSMatthew G. Knepley } 307148a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 307224119c2aSMatthew G. Knepley /* Create cylinder geometry */ 307324119c2aSMatthew G. Knepley { 307424119c2aSMatthew G. Knepley Vec coordinates; 307524119c2aSMatthew G. Knepley PetscSection coordSection; 307624119c2aSMatthew G. Knepley PetscScalar *coords; 3077412e9a14SMatthew G. Knepley PetscInt coordSize, c; 307824119c2aSMatthew G. Knepley 307924119c2aSMatthew G. Knepley /* Build coordinates */ 30809566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 30819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 30829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 30839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 308424119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 30859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 30869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 308724119c2aSMatthew G. Knepley } 30889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 30899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 30909566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 30919566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 30929566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 30939566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 30949566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 30959566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 309624119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 30979371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 30989371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 30999371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 31009371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 31019371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 31029371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 310324119c2aSMatthew G. Knepley } 3104dd400576SPatrick Sanan if (rank == 0) { 31059371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 31069371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 31079371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 31089371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 31099371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 31109371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 31119fe9f049SMatthew G. Knepley } 31129566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 31139566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 31149566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 311524119c2aSMatthew G. Knepley } 311646139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 31179318fe57SMatthew G. Knepley /* Interpolate */ 31189566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 31193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31209318fe57SMatthew G. Knepley } 31219318fe57SMatthew G. Knepley 31229318fe57SMatthew G. Knepley /*@ 31239318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 31249318fe57SMatthew G. Knepley 31259318fe57SMatthew G. Knepley Collective 31269318fe57SMatthew G. Knepley 31279318fe57SMatthew G. Knepley Input Parameters: 3128a1cb98faSBarry Smith + comm - The communicator for the `DM` object 31299318fe57SMatthew G. Knepley . n - The number of wedges around the origin 31309318fe57SMatthew G. Knepley - interpolate - Create edges and faces 31319318fe57SMatthew G. Knepley 31329318fe57SMatthew G. Knepley Output Parameter: 3133a1cb98faSBarry Smith . dm - The `DM` object 31349318fe57SMatthew G. Knepley 31359318fe57SMatthew G. Knepley Level: beginner 31369318fe57SMatthew G. Knepley 31371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 31389318fe57SMatthew G. Knepley @*/ 3139d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 3140d71ae5a4SJacob Faibussowitsch { 31419318fe57SMatthew G. Knepley PetscFunctionBegin; 31424f572ea9SToby Isaac PetscAssertPointer(dm, 4); 31439566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 31449566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 31459566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 31463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 314724119c2aSMatthew G. Knepley } 314824119c2aSMatthew G. Knepley 3149d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 3150d71ae5a4SJacob Faibussowitsch { 315165a81367SMatthew G. Knepley PetscReal prod = 0.0; 315265a81367SMatthew G. Knepley PetscInt i; 315365a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 315465a81367SMatthew G. Knepley return PetscSqrtReal(prod); 315565a81367SMatthew G. Knepley } 3156dd2b43ebSStefano Zampini 3157d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 3158d71ae5a4SJacob Faibussowitsch { 315965a81367SMatthew G. Knepley PetscReal prod = 0.0; 316065a81367SMatthew G. Knepley PetscInt i; 316165a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += x[i] * y[i]; 316265a81367SMatthew G. Knepley return prod; 316365a81367SMatthew G. Knepley } 316465a81367SMatthew G. Knepley 316551a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 3166d71ae5a4SJacob 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[]) 3167d71ae5a4SJacob Faibussowitsch { 316851a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 316951a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 317051a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 317151a74b61SMatthew G. Knepley 317251a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 317351a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 317451a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 317551a74b61SMatthew G. Knepley } 317651a74b61SMatthew G. Knepley 3177d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 3178d71ae5a4SJacob Faibussowitsch { 317965a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 318065a81367SMatthew G. Knepley PetscSection coordSection; 318165a81367SMatthew G. Knepley Vec coordinates; 318265a81367SMatthew G. Knepley PetscScalar *coords; 318365a81367SMatthew G. Knepley PetscReal *coordsIn; 318407c565c5SJose E. Roman PetscInt numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, e; 318565a81367SMatthew G. Knepley PetscMPIInt rank; 318665a81367SMatthew G. Knepley 318765a81367SMatthew G. Knepley PetscFunctionBegin; 31889318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 318946139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 31909566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 31919566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 31929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 319365a81367SMatthew G. Knepley switch (dim) { 31945c344501SMatthew G. Knepley case 1: 31955c344501SMatthew G. Knepley numCells = 16; 31965c344501SMatthew G. Knepley numVerts = numCells; 31975c344501SMatthew G. Knepley 31985c344501SMatthew G. Knepley // Build Topology 31995c344501SMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 32005c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 32015c344501SMatthew G. Knepley PetscCall(DMSetUp(dm)); 32025c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 32035c344501SMatthew G. Knepley PetscInt cone[2]; 32045c344501SMatthew G. Knepley 32055c344501SMatthew G. Knepley cone[0] = c + numCells; 32065c344501SMatthew G. Knepley cone[1] = (c + 1) % numVerts + numCells; 32075c344501SMatthew G. Knepley PetscCall(DMPlexSetCone(dm, c, cone)); 32085c344501SMatthew G. Knepley } 32095c344501SMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 32105c344501SMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 32115c344501SMatthew G. Knepley PetscCall(PetscMalloc1(numVerts * embedDim, &coordsIn)); 32125c344501SMatthew G. Knepley for (PetscInt v = 0; v < numVerts; ++v) { 32135c344501SMatthew G. Knepley const PetscReal rad = 2. * PETSC_PI * v / numVerts; 32145c344501SMatthew G. Knepley 32155c344501SMatthew G. Knepley coordsIn[v * embedDim + 0] = PetscCosReal(rad); 32165c344501SMatthew G. Knepley coordsIn[v * embedDim + 1] = PetscSinReal(rad); 32175c344501SMatthew G. Knepley } 32185c344501SMatthew G. Knepley break; 321965a81367SMatthew G. Knepley case 2: 322065a81367SMatthew G. Knepley if (simplex) { 322151a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 322251a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 322365a81367SMatthew G. Knepley const PetscInt degree = 5; 322451a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 322565a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 322665a81367SMatthew G. Knepley PetscInt cone[3]; 322707c565c5SJose E. Roman PetscInt *graph; 322865a81367SMatthew G. Knepley 32299371c9d4SSatish Balay vertex[0] *= R / radius; 32309371c9d4SSatish Balay vertex[1] *= R / radius; 32319371c9d4SSatish Balay vertex[2] *= R / radius; 3232dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 3233dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 323465a81367SMatthew G. Knepley firstVertex = numCells; 323551a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 323665a81367SMatthew G. Knepley 323765a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 323865a81367SMatthew G. Knepley 323965a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 324051a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 324165a81367SMatthew G. Knepley */ 324265a81367SMatthew G. Knepley /* Construct vertices */ 32439566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3244dd400576SPatrick Sanan if (rank == 0) { 324507c565c5SJose E. Roman for (PetscInt p = 0, i = 0; p < embedDim; ++p) { 324665a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 324765a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 324865a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 324965a81367SMatthew G. Knepley ++i; 325065a81367SMatthew G. Knepley } 325165a81367SMatthew G. Knepley } 325265a81367SMatthew G. Knepley } 325345da822fSValeria Barra } 325465a81367SMatthew G. Knepley /* Construct graph */ 32559566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 325607c565c5SJose E. Roman for (PetscInt i = 0; i < numVerts; ++i) { 325707c565c5SJose E. Roman PetscInt k = 0; 325807c565c5SJose E. Roman for (PetscInt j = 0; j < numVerts; ++j) { 32599371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 32609371c9d4SSatish Balay graph[i * numVerts + j] = 1; 32619371c9d4SSatish Balay ++k; 32629371c9d4SSatish Balay } 326365a81367SMatthew G. Knepley } 326463a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 326565a81367SMatthew G. Knepley } 326665a81367SMatthew G. Knepley /* Build Topology */ 32679566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 326807c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 32699566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 327065a81367SMatthew G. Knepley /* Cells */ 327107c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 327207c565c5SJose E. Roman for (PetscInt j = 0; j < i; ++j) { 327307c565c5SJose E. Roman for (PetscInt k = 0; k < j; ++k) { 327465a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 32759371c9d4SSatish Balay cone[0] = firstVertex + i; 32769371c9d4SSatish Balay cone[1] = firstVertex + j; 32779371c9d4SSatish Balay cone[2] = firstVertex + k; 327865a81367SMatthew G. Knepley /* Check orientation */ 327965a81367SMatthew G. Knepley { 32809371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 32819371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 32829371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 32839371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 32849371c9d4SSatish Balay }; 328565a81367SMatthew G. Knepley PetscReal normal[3]; 328665a81367SMatthew G. Knepley PetscInt e, f; 328765a81367SMatthew G. Knepley 328865a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 328965a81367SMatthew G. Knepley normal[d] = 0.0; 329065a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3291ad540459SPierre 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]); 329265a81367SMatthew G. Knepley } 329365a81367SMatthew G. Knepley } 32949371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 32959371c9d4SSatish Balay PetscInt tmp = cone[1]; 32969371c9d4SSatish Balay cone[1] = cone[2]; 32979371c9d4SSatish Balay cone[2] = tmp; 329865a81367SMatthew G. Knepley } 329965a81367SMatthew G. Knepley } 33009566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 330165a81367SMatthew G. Knepley } 330265a81367SMatthew G. Knepley } 330365a81367SMatthew G. Knepley } 330465a81367SMatthew G. Knepley } 33059566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 33069566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 33079566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 330865a81367SMatthew G. Knepley } else { 33092829fed8SMatthew G. Knepley /* 33102829fed8SMatthew G. Knepley 12-21--13 33112829fed8SMatthew G. Knepley | | 33122829fed8SMatthew G. Knepley 25 4 24 33132829fed8SMatthew G. Knepley | | 33142829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 33152829fed8SMatthew G. Knepley | | | | 33162829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 33172829fed8SMatthew G. Knepley | | | | 33182829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 33192829fed8SMatthew G. Knepley | | 33202829fed8SMatthew G. Knepley 20 1 19 33212829fed8SMatthew G. Knepley | | 33222829fed8SMatthew G. Knepley 10-18--11 33232829fed8SMatthew G. Knepley | | 33242829fed8SMatthew G. Knepley 23 2 22 33252829fed8SMatthew G. Knepley | | 33262829fed8SMatthew G. Knepley 12-21--13 33272829fed8SMatthew G. Knepley */ 33282829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 33292829fed8SMatthew G. Knepley 3330dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 3331dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 3332dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 333365a81367SMatthew G. Knepley firstVertex = numCells; 333465a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 33352829fed8SMatthew G. Knepley /* Build Topology */ 33369566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 333707c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 333848a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 33399566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3340dd400576SPatrick Sanan if (rank == 0) { 33412829fed8SMatthew G. Knepley /* Cell 0 */ 33429371c9d4SSatish Balay cone[0] = 14; 33439371c9d4SSatish Balay cone[1] = 15; 33449371c9d4SSatish Balay cone[2] = 16; 33459371c9d4SSatish Balay cone[3] = 17; 33469566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 33479371c9d4SSatish Balay ornt[0] = 0; 33489371c9d4SSatish Balay ornt[1] = 0; 33499371c9d4SSatish Balay ornt[2] = 0; 33509371c9d4SSatish Balay ornt[3] = 0; 33519566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 33522829fed8SMatthew G. Knepley /* Cell 1 */ 33539371c9d4SSatish Balay cone[0] = 18; 33549371c9d4SSatish Balay cone[1] = 19; 33559371c9d4SSatish Balay cone[2] = 14; 33569371c9d4SSatish Balay cone[3] = 20; 33579566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 33589371c9d4SSatish Balay ornt[0] = 0; 33599371c9d4SSatish Balay ornt[1] = 0; 33609371c9d4SSatish Balay ornt[2] = -1; 33619371c9d4SSatish Balay ornt[3] = 0; 33629566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 33632829fed8SMatthew G. Knepley /* Cell 2 */ 33649371c9d4SSatish Balay cone[0] = 21; 33659371c9d4SSatish Balay cone[1] = 22; 33669371c9d4SSatish Balay cone[2] = 18; 33679371c9d4SSatish Balay cone[3] = 23; 33689566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 33699371c9d4SSatish Balay ornt[0] = 0; 33709371c9d4SSatish Balay ornt[1] = 0; 33719371c9d4SSatish Balay ornt[2] = -1; 33729371c9d4SSatish Balay ornt[3] = 0; 33739566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 33742829fed8SMatthew G. Knepley /* Cell 3 */ 33759371c9d4SSatish Balay cone[0] = 19; 33769371c9d4SSatish Balay cone[1] = 22; 33779371c9d4SSatish Balay cone[2] = 24; 33789371c9d4SSatish Balay cone[3] = 15; 33799566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 33809371c9d4SSatish Balay ornt[0] = -1; 33819371c9d4SSatish Balay ornt[1] = -1; 33829371c9d4SSatish Balay ornt[2] = 0; 33839371c9d4SSatish Balay ornt[3] = -1; 33849566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 33852829fed8SMatthew G. Knepley /* Cell 4 */ 33869371c9d4SSatish Balay cone[0] = 16; 33879371c9d4SSatish Balay cone[1] = 24; 33889371c9d4SSatish Balay cone[2] = 21; 33899371c9d4SSatish Balay cone[3] = 25; 33909566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 33919371c9d4SSatish Balay ornt[0] = -1; 33929371c9d4SSatish Balay ornt[1] = -1; 33939371c9d4SSatish Balay ornt[2] = -1; 33949371c9d4SSatish Balay ornt[3] = 0; 33959566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 33962829fed8SMatthew G. Knepley /* Cell 5 */ 33979371c9d4SSatish Balay cone[0] = 20; 33989371c9d4SSatish Balay cone[1] = 17; 33999371c9d4SSatish Balay cone[2] = 25; 34009371c9d4SSatish Balay cone[3] = 23; 34019566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 34029371c9d4SSatish Balay ornt[0] = -1; 34039371c9d4SSatish Balay ornt[1] = -1; 34049371c9d4SSatish Balay ornt[2] = -1; 34059371c9d4SSatish Balay ornt[3] = -1; 34069566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 34072829fed8SMatthew G. Knepley /* Edges */ 34089371c9d4SSatish Balay cone[0] = 6; 34099371c9d4SSatish Balay cone[1] = 7; 34109566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 34119371c9d4SSatish Balay cone[0] = 7; 34129371c9d4SSatish Balay cone[1] = 8; 34139566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 34149371c9d4SSatish Balay cone[0] = 8; 34159371c9d4SSatish Balay cone[1] = 9; 34169566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 34179371c9d4SSatish Balay cone[0] = 9; 34189371c9d4SSatish Balay cone[1] = 6; 34199566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 34209371c9d4SSatish Balay cone[0] = 10; 34219371c9d4SSatish Balay cone[1] = 11; 34229566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 34239371c9d4SSatish Balay cone[0] = 11; 34249371c9d4SSatish Balay cone[1] = 7; 34259566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 34269371c9d4SSatish Balay cone[0] = 6; 34279371c9d4SSatish Balay cone[1] = 10; 34289566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 34299371c9d4SSatish Balay cone[0] = 12; 34309371c9d4SSatish Balay cone[1] = 13; 34319566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 34329371c9d4SSatish Balay cone[0] = 13; 34339371c9d4SSatish Balay cone[1] = 11; 34349566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 34359371c9d4SSatish Balay cone[0] = 10; 34369371c9d4SSatish Balay cone[1] = 12; 34379566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 34389371c9d4SSatish Balay cone[0] = 13; 34399371c9d4SSatish Balay cone[1] = 8; 34409566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 34419371c9d4SSatish Balay cone[0] = 12; 34429371c9d4SSatish Balay cone[1] = 9; 34439566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 344445da822fSValeria Barra } 34459566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 34469566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 34472829fed8SMatthew G. Knepley /* Build coordinates */ 34489566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3449dd400576SPatrick Sanan if (rank == 0) { 34509371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 34519371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 34529371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 34539371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 34549371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 34559371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 34569371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 34579371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 34589371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 34599371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 34609371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 34619371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 34629371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 34639371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 34649371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 34659371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 34669371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 34679371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 34689371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 34699371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 34709371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 34719371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 34729371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 34739371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 347465a81367SMatthew G. Knepley } 347545da822fSValeria Barra } 347665a81367SMatthew G. Knepley break; 347765a81367SMatthew G. Knepley case 3: 3478116ded15SMatthew G. Knepley if (simplex) { 3479116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 348051a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 348151a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 348251a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 3483116ded15SMatthew G. Knepley const PetscInt degree = 12; 3484116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 34859371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 34869371c9d4SSatish Balay {0, 1, 2, 3}, 34879371c9d4SSatish Balay {0, 2, 3, 1}, 34889371c9d4SSatish Balay {0, 3, 1, 2}, 34899371c9d4SSatish Balay {1, 0, 3, 2}, 34909371c9d4SSatish Balay {1, 2, 0, 3}, 34919371c9d4SSatish Balay {1, 3, 2, 0}, 34929371c9d4SSatish Balay {2, 0, 1, 3}, 34939371c9d4SSatish Balay {2, 1, 3, 0}, 34949371c9d4SSatish Balay {2, 3, 0, 1}, 34959371c9d4SSatish Balay {3, 0, 2, 1}, 34969371c9d4SSatish Balay {3, 1, 0, 2}, 34979371c9d4SSatish Balay {3, 2, 1, 0} 34989371c9d4SSatish Balay }; 3499116ded15SMatthew G. Knepley PetscInt cone[4]; 3500116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 3501116ded15SMatthew G. Knepley 35029371c9d4SSatish Balay vertexA[0] *= R; 35039371c9d4SSatish Balay vertexA[1] *= R; 35049371c9d4SSatish Balay vertexA[2] *= R; 35059371c9d4SSatish Balay vertexA[3] *= R; 35069371c9d4SSatish Balay vertexB[0] *= R; 35079371c9d4SSatish Balay vertexB[1] *= R; 35089371c9d4SSatish Balay vertexB[2] *= R; 35099371c9d4SSatish Balay vertexB[3] *= R; 35109371c9d4SSatish Balay vertexC[0] *= R; 35119371c9d4SSatish Balay vertexC[1] *= R; 35129371c9d4SSatish Balay vertexC[2] *= R; 35139371c9d4SSatish Balay vertexC[3] *= R; 3514dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 3515dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 3516116ded15SMatthew G. Knepley firstVertex = numCells; 3517116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 3518116ded15SMatthew G. Knepley 3519116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 3520116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 3521116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 3522116ded15SMatthew G. Knepley 3523116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 35246333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 3525116ded15SMatthew G. Knepley 3526116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 3527116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 3528116ded15SMatthew G. Knepley */ 3529116ded15SMatthew G. Knepley /* Construct vertices */ 35309566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3531116ded15SMatthew G. Knepley i = 0; 3532dd400576SPatrick Sanan if (rank == 0) { 3533116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3534116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3535116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3536116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 3537116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 3538116ded15SMatthew G. Knepley ++i; 3539116ded15SMatthew G. Knepley } 3540116ded15SMatthew G. Knepley } 3541116ded15SMatthew G. Knepley } 3542116ded15SMatthew G. Knepley } 3543116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 3544116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 3545116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3546116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 3547116ded15SMatthew G. Knepley ++i; 3548116ded15SMatthew G. Knepley } 3549116ded15SMatthew G. Knepley } 3550116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 3551116ded15SMatthew G. Knepley s[3] = 1; 3552116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3553116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3554116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3555116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 3556116ded15SMatthew G. Knepley ++i; 3557116ded15SMatthew G. Knepley } 3558116ded15SMatthew G. Knepley } 3559116ded15SMatthew G. Knepley } 3560116ded15SMatthew G. Knepley } 356145da822fSValeria Barra } 356263a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 3563116ded15SMatthew G. Knepley /* Construct graph */ 35649566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 3565116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 3566116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 35679371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 35689371c9d4SSatish Balay graph[i * numVerts + j] = 1; 35699371c9d4SSatish Balay ++k; 35709371c9d4SSatish Balay } 3571116ded15SMatthew G. Knepley } 357263a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 3573116ded15SMatthew G. Knepley } 3574116ded15SMatthew G. Knepley /* Build Topology */ 35759566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 357607c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 35779566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3578116ded15SMatthew G. Knepley /* Cells */ 3579dd400576SPatrick Sanan if (rank == 0) { 358007c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 3581116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 3582116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 3583116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 35849371c9d4SSatish 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]) { 35859371c9d4SSatish Balay cone[0] = firstVertex + i; 35869371c9d4SSatish Balay cone[1] = firstVertex + j; 35879371c9d4SSatish Balay cone[2] = firstVertex + k; 35889371c9d4SSatish Balay cone[3] = firstVertex + l; 3589116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 3590116ded15SMatthew G. Knepley { 35919371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 35929371c9d4SSatish 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}}}, 3593116ded15SMatthew G. Knepley 35949371c9d4SSatish 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}}}, 3595116ded15SMatthew G. Knepley 35969371c9d4SSatish 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}}}, 3597116ded15SMatthew G. Knepley 35989371c9d4SSatish 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}} } 35999371c9d4SSatish Balay }; 3600116ded15SMatthew G. Knepley PetscReal normal[4]; 3601116ded15SMatthew G. Knepley PetscInt e, f, g; 3602116ded15SMatthew G. Knepley 3603116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 3604116ded15SMatthew G. Knepley normal[d] = 0.0; 3605116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3606116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 3607116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 3608116ded15SMatthew 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]); 3609116ded15SMatthew G. Knepley } 3610116ded15SMatthew G. Knepley } 3611116ded15SMatthew G. Knepley } 3612116ded15SMatthew G. Knepley } 36139371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 36149371c9d4SSatish Balay PetscInt tmp = cone[1]; 36159371c9d4SSatish Balay cone[1] = cone[2]; 36169371c9d4SSatish Balay cone[2] = tmp; 36179371c9d4SSatish Balay } 3618116ded15SMatthew G. Knepley } 36199566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 3620116ded15SMatthew G. Knepley } 3621116ded15SMatthew G. Knepley } 3622116ded15SMatthew G. Knepley } 3623116ded15SMatthew G. Knepley } 3624116ded15SMatthew G. Knepley } 362545da822fSValeria Barra } 36269566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 36279566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 36289566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 3629116ded15SMatthew G. Knepley } 3630f4d061e9SPierre Jolivet break; 3631d71ae5a4SJacob Faibussowitsch default: 3632d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 363365a81367SMatthew G. Knepley } 363465a81367SMatthew G. Knepley /* Create coordinates */ 36359566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 36369566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 36379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 36389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 36392829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 36409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 36419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 36422829fed8SMatthew G. Knepley } 36439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 36449566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 36459566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 36469566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 36479566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 36489566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 36499566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 36509566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 36519371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 3652ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 36539566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 36549566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 36559566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 36569566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 365751a74b61SMatthew G. Knepley { 365851a74b61SMatthew G. Knepley DM cdm; 365951a74b61SMatthew G. Knepley PetscDS cds; 36609318fe57SMatthew G. Knepley PetscScalar c = R; 366151a74b61SMatthew G. Knepley 3662509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, snapToSphere)); 3663e65c294aSksagiyam PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE)); 36649566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 36659566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 36669566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 366751a74b61SMatthew G. Knepley } 366846139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 36699318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 36709566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 36713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36729318fe57SMatthew G. Knepley } 36739318fe57SMatthew G. Knepley 3674b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 3675b7f5c055SJed Brown 3676b7f5c055SJed Brown /* 3677b7f5c055SJed Brown The Schwarz P implicit surface is 3678b7f5c055SJed Brown 3679b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 3680b7f5c055SJed Brown */ 3681d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3682d71ae5a4SJacob Faibussowitsch { 3683b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 3684b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 3685b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 3686b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3687b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 3688ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 3689b7f5c055SJed Brown } 3690b7f5c055SJed Brown } 3691b7f5c055SJed Brown 36924663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3693d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3694d71ae5a4SJacob Faibussowitsch { 3695ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 36963ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 36974663dae6SJed Brown } 36984663dae6SJed Brown 3699b7f5c055SJed Brown /* 3700b7f5c055SJed Brown The Gyroid implicit surface is 3701b7f5c055SJed Brown 3702b7f5c055SJed 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) 3703b7f5c055SJed Brown 3704b7f5c055SJed Brown */ 3705d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3706d71ae5a4SJacob Faibussowitsch { 3707b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 3708b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 3709b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 3710b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 3711b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 3712b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 3713b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 3714b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3715b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3716b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 3717b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3718b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3719b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 3720b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3721b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3722b7f5c055SJed Brown } 3723b7f5c055SJed Brown 37244663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3725d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3726d71ae5a4SJacob Faibussowitsch { 37274663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 37284663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 37294663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 37304663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 37314663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 37323ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 37334663dae6SJed Brown } 37344663dae6SJed Brown 3735b7f5c055SJed Brown /* 3736b7f5c055SJed Brown We wish to solve 3737b7f5c055SJed Brown 3738b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 3739b7f5c055SJed Brown 3740b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 3741b7f5c055SJed 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 3742b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 3743b7f5c055SJed Brown 3744b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 3745b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 3746b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 3747b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 3748da81f932SPierre Jolivet Since Q is symmetric, this is equivalent to multiplying by Q and taking the last two entries. 3749b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 3750b7f5c055SJed Brown 3751b7f5c055SJed Brown f(y) = 0 1 equation 3752b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 3753b7f5c055SJed Brown 3754b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 3755b7f5c055SJed Brown */ 3756d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 3757d71ae5a4SJacob Faibussowitsch { 3758b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 3759b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 37602f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 37619371c9d4SSatish Balay PetscReal n_y[3][3] = { 37629371c9d4SSatish Balay {0, 0, 0}, 37639371c9d4SSatish Balay {0, 0, 0}, 37649371c9d4SSatish Balay {0, 0, 0} 37659371c9d4SSatish Balay }; 3766b7f5c055SJed Brown 3767b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 3768b7f5c055SJed Brown 3769b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 3770b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3771ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 3772b7f5c055SJed Brown 3773b7f5c055SJed Brown // Define the Householder reflector 3774b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 3775b7f5c055SJed Brown n[0] += norm * sign; 3776b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 3777b7f5c055SJed Brown 3778b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3779b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 3780b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 3781b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 3782b7f5c055SJed Brown 3783b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3784b7f5c055SJed Brown n[i] /= norm; 3785b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3786b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 3787b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 3788b7f5c055SJed Brown } 3789b7f5c055SJed Brown } 3790b7f5c055SJed Brown 3791b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 3792b7f5c055SJed 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]; 3793b7f5c055SJed Brown 3794b7f5c055SJed Brown res[0] = f; 3795b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 3796b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 3797b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 3798b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3799b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 3800b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 3801b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 3802b7f5c055SJed Brown } 3803b7f5c055SJed Brown } 3804b7f5c055SJed Brown 3805b7f5c055SJed Brown /* 3806b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 3807b7f5c055SJed Brown */ 3808d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 3809d71ae5a4SJacob Faibussowitsch { 3810b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 3811b7f5c055SJed Brown 3812b7f5c055SJed Brown PetscFunctionBegin; 3813b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 3814b7f5c055SJed Brown PetscScalar res[3], J[9]; 3815b7f5c055SJed Brown PetscReal resnorm; 3816b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 3817b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 3818b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 381963a3b9bcSJacob 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]))); 3820b7f5c055SJed Brown } 3821b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 3822b7f5c055SJed Brown 3823b7f5c055SJed Brown // Take the Newton step 38249566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 3825b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 3826b7f5c055SJed Brown } 3827b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 38283ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3829b7f5c055SJed Brown } 3830b7f5c055SJed Brown 3831b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 3832b7f5c055SJed Brown 3833d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 3834d71ae5a4SJacob Faibussowitsch { 3835b7f5c055SJed Brown PetscMPIInt rank; 3836b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 3837b7f5c055SJed Brown PetscInt (*edges)[2] = NULL, *edgeSets = NULL; 3838b7f5c055SJed Brown PetscInt *cells_flat = NULL; 3839b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 3840b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 38418434afd1SBarry Smith PetscSimplePointFn *normalFunc = NULL; 3842b7f5c055SJed Brown DMLabel label; 3843b7f5c055SJed Brown 3844b7f5c055SJed Brown PetscFunctionBegin; 384546139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 38469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 384763a3b9bcSJacob 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); 3848b7f5c055SJed Brown switch (tpstype) { 3849b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 3850b7f5c055SJed 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"); 3851c5853193SPierre Jolivet if (rank == 0) { 3852b7f5c055SJed Brown PetscInt (*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 3853b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 3854b7f5c055SJed Brown PetscReal L = 1; 3855b7f5c055SJed Brown 3856b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 3857b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 3858b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 3859b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 3860b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 3861b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 38629566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 38639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 38649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 38659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 3866b7f5c055SJed Brown // x-normal pipes 3867b7f5c055SJed Brown vcount = 0; 3868b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 3869b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3870b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3871b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3872b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 3873b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3874b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3875b7f5c055SJed Brown } 3876b7f5c055SJed Brown } 3877b7f5c055SJed Brown } 3878b7f5c055SJed Brown } 3879b7f5c055SJed Brown // y-normal pipes 3880b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3881b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 3882b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3883b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3884b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3885b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 3886b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3887b7f5c055SJed Brown } 3888b7f5c055SJed Brown } 3889b7f5c055SJed Brown } 3890b7f5c055SJed Brown } 3891b7f5c055SJed Brown // z-normal pipes 3892b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3893b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3894b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 3895b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3896b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3897b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3898b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 3899b7f5c055SJed Brown } 3900b7f5c055SJed Brown } 3901b7f5c055SJed Brown } 3902b7f5c055SJed Brown } 3903b7f5c055SJed Brown // junctions 3904b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3905b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3906b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3907b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 3908b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 3909b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 3910b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 3911b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 3912b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 3913b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 3914b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 3915b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 3916b7f5c055SJed Brown } 3917b7f5c055SJed Brown } 3918b7f5c055SJed Brown } 3919b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 3920b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 3921b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 3922b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 3923b7f5c055SJed Brown }; 3924b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 39259371c9d4SSatish 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}; 3926b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 39279371c9d4SSatish 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}; 3928b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 3929b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 3930b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 3931b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 3932b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 3933b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 3934b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 3935b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 3936b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 3937b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 3938b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 3939b7f5c055SJed Brown if (ijk[dir] == 0) { 3940b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 3941b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 3942b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 3943b7f5c055SJed Brown numEdges++; 3944b7f5c055SJed Brown } 3945b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 3946b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 3947b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 3948b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 3949b7f5c055SJed Brown numEdges++; 3950b7f5c055SJed Brown } 3951b7f5c055SJed Brown } 3952b7f5c055SJed Brown } 3953b7f5c055SJed Brown } 3954b7f5c055SJed Brown } 3955b7f5c055SJed Brown } 395663a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 3957b7f5c055SJed Brown numFaces = 24 * Njunctions; 3958b7f5c055SJed Brown cells_flat = cells[0][0][0]; 3959b7f5c055SJed Brown } 3960b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 39614663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 3962b7f5c055SJed Brown break; 3963b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 3964c5853193SPierre Jolivet if (rank == 0) { 3965b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 3966b7f5c055SJed Brown // 3967b7f5c055SJed 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) 3968b7f5c055SJed Brown // 3969b7f5c055SJed Brown // on the cell [0,2]^3. 3970b7f5c055SJed Brown // 3971b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 3972b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 3973b7f5c055SJed Brown // like a boomerang: 3974b7f5c055SJed Brown // 3975b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 3976b7f5c055SJed Brown // ----- ------- ------- ------- // 3977b7f5c055SJed Brown // // 3978b7f5c055SJed Brown // + + + + + + + \ + // 3979b7f5c055SJed Brown // \ / \ // 3980b7f5c055SJed Brown // \ `-_ _-' / } // 3981b7f5c055SJed Brown // *-_ `-' _-' / // 3982b7f5c055SJed Brown // + `-+ + + +-' + + / + // 3983b7f5c055SJed Brown // // 3984b7f5c055SJed Brown // // 3985b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 3986b7f5c055SJed Brown // ----- ------- ------- ------- // 3987b7f5c055SJed Brown // // 3988b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 3989b7f5c055SJed Brown // `-_ _-_ _-` / // 3990b7f5c055SJed Brown // \ _-' `-_ / { // 3991b7f5c055SJed Brown // \ / \ // 3992b7f5c055SJed Brown // + + + + + + + \ + // 3993b7f5c055SJed Brown // 3994b7f5c055SJed Brown // 3995b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 3996b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 3997b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 3998b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 3999b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 4000b7f5c055SJed Brown // 4001b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 4002b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 4003b7f5c055SJed Brown // 4004b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 4005b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 4006b7f5c055SJed Brown 4007b7f5c055SJed Brown PetscInt facesPerBlock = 64; 4008b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 4009b7f5c055SJed Brown PetscInt extentPlus[3]; 4010b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 40119371c9d4SSatish 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; 40129371c9d4SSatish Balay const PetscInt pattern[64][4] = { 40139371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 4014b7f5c055SJed Brown /* layer 0 */ 40159371c9d4SSatish Balay {A, C, K, G }, 40169371c9d4SSatish Balay {C, B, II, K }, 40179371c9d4SSatish Balay {D, A, H, L }, 40189371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 40199371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 40209371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 40219371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 40229371c9d4SSatish Balay {B, F, M, II }, 4023b7f5c055SJed Brown /* layer 1 */ 40249371c9d4SSatish Balay {G, K, Q, O }, 40259371c9d4SSatish Balay {K, II, P, Q }, 40269371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 40279371c9d4SSatish Balay {J, L, R, P }, 40289371c9d4SSatish Balay {N, J, P, S }, 40299371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 40309371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 40319371c9d4SSatish Balay {II, M, T, P }, 4032b7f5c055SJed Brown /* layer 2 */ 40339371c9d4SSatish Balay {O, Q, Y, U }, 40349371c9d4SSatish Balay {Q, P, W, Y }, 40359371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 40369371c9d4SSatish Balay {P, R, Ap, W }, 40379371c9d4SSatish Balay {S, P, X, Bp }, 40389371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 40399371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 40409371c9d4SSatish Balay {P, T, Z, X }, 4041b7f5c055SJed Brown /* layer 3 */ 40429371c9d4SSatish Balay {U, Y, Ep, Dp }, 40439371c9d4SSatish Balay {Y, W, Cp, Ep }, 40449371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 40459371c9d4SSatish Balay {W, Ap, Gp, Cp }, 40469371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 40479371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 40489371c9d4SSatish Balay {Z, V, Dp, Hp }, 40499371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 4050b7f5c055SJed Brown /* layer 4 */ 40519371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 40529371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 40539371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 40549371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 40559371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 40569371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 40579371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 40589371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 4059b7f5c055SJed Brown /* layer 5 */ 40609371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 40619371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 40629371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 40639371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 40649371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 40659371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 40669371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 40679371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 4068b7f5c055SJed Brown /* layer 6 */ 40699371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 40709371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 40719371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 40729371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 40739371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 40749371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 40759371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 40769371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 4077b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 40789371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 40799371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 40809371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 40819371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 40829371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 40839371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 40849371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 40859371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 4086b7f5c055SJed Brown }; 4087b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 40889371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 4089bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 4090bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 4091bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 4092bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 4093bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 4094bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 4095b7f5c055SJed Brown 4096bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 4097bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 4098bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 4099bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 4100bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 4101bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 4102bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 4103bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 4104b7f5c055SJed Brown 4105bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 4106bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 4107bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 4108bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 4109bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 4110bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 4111b7f5c055SJed Brown 4112bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 4113bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 4114bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 4115bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 4116bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 4117bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 4118bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 4119bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 4120b7f5c055SJed Brown 4121bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 4122bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 4123bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 4124bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 4125bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 4126bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 4127b7f5c055SJed Brown 4128bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 4129bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 4130bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 4131bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 4132bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 4133bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 4134bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 4135bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 4136b7f5c055SJed Brown 4137bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 4138bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 4139bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 4140bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 4141bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 4142bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 4143b7f5c055SJed Brown 4144bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 4145bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 4146bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 4147bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 4148bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 4149bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 4150bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 4151bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 4152b7f5c055SJed Brown }; 4153b7f5c055SJed Brown PetscInt (*cells)[64][4] = NULL; 4154b7f5c055SJed Brown PetscBool *seen; 4155b7f5c055SJed Brown PetscInt *vertToTrueVert; 4156b7f5c055SJed Brown PetscInt count; 4157b7f5c055SJed Brown 4158b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 4159b7f5c055SJed Brown numBlocks = 1; 4160b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 4161b7f5c055SJed Brown numBlocksPlus = 1; 4162b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 4163b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 41649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 41659566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 4166b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 4167b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 4168b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 4169b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 4170b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 4171b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 4172b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 4173b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 4174b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 4175b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 4176b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 4177b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 4178b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 4179b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 4180b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 4181b7f5c055SJed Brown 4182b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 4183b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 4184b7f5c055SJed Brown } 4185b7f5c055SJed Brown } 4186b7f5c055SJed Brown } 4187b7f5c055SJed Brown } 4188b7f5c055SJed Brown } 41899371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 41909371c9d4SSatish Balay if (seen[i]) numVertices++; 4191b7f5c055SJed Brown count = 0; 41929566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 41939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 4194b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 4195b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 4196b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 4197b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 4198b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 4199b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 4200b7f5c055SJed Brown 4201b7f5c055SJed Brown if (seen[vIdx]) { 4202b7f5c055SJed Brown PetscInt thisVert; 4203b7f5c055SJed Brown 4204b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 4205b7f5c055SJed Brown 4206b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 4207b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 4208b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 4209b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 4210b7f5c055SJed Brown } 4211b7f5c055SJed Brown } 4212b7f5c055SJed Brown } 4213b7f5c055SJed Brown } 4214b7f5c055SJed Brown } 4215b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 4216b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 4217ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 4218b7f5c055SJed Brown } 4219b7f5c055SJed Brown } 42209566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 42219566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 4222b7f5c055SJed Brown cells_flat = cells[0][0]; 4223b7f5c055SJed Brown numEdges = 0; 4224b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 4225b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 4226b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 4227b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 4228b7f5c055SJed Brown 4229b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 4230b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 4231b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 4232b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 4233b7f5c055SJed Brown } 4234b7f5c055SJed Brown } 4235b7f5c055SJed Brown } 4236b7f5c055SJed Brown } 42379566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 42389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 4239b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 4240b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 4241b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 4242b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 4243b7f5c055SJed Brown 4244b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 4245b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 4246b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 4247b7f5c055SJed Brown edges[edge][0] = ev[0]; 4248b7f5c055SJed Brown edges[edge][1] = ev[1]; 4249b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 4250b7f5c055SJed Brown } 4251b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 4252b7f5c055SJed Brown edges[edge][0] = ev[0]; 4253b7f5c055SJed Brown edges[edge][1] = ev[1]; 4254b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 4255b7f5c055SJed Brown } 4256b7f5c055SJed Brown } 4257b7f5c055SJed Brown } 4258b7f5c055SJed Brown } 4259b7f5c055SJed Brown } 4260b7f5c055SJed Brown } 4261b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 42624663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 4263b7f5c055SJed Brown break; 4264b7f5c055SJed Brown } 4265b7f5c055SJed Brown 42669566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 4267c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 42689566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 42699566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 4270b7f5c055SJed Brown { 4271b7f5c055SJed Brown DM idm; 42729566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 427369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 4274b7f5c055SJed Brown } 4275c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 42769566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 42779566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 4278b7f5c055SJed Brown 42799566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 42809566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 4281b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 4282b7f5c055SJed Brown PetscInt njoin; 4283b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 42849566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 428563a3b9bcSJacob 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]); 42869566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 42879566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 4288b7f5c055SJed Brown } 42899566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 42909566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 42911436d7faSJed Brown if (tps_distribute) { 42921436d7faSJed Brown DM pdm = NULL; 42931436d7faSJed Brown PetscPartitioner part; 42941436d7faSJed Brown 42959566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 42969566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 42979566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 429848a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 42991436d7faSJed Brown // Do not auto-distribute again 43009566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 43011436d7faSJed Brown } 4302b7f5c055SJed Brown 43039566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 4304b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 4305b7f5c055SJed Brown PetscInt m; 4306f1d4225fSZach Atkins DM dmf, cdm, cdmf; 4307b7f5c055SJed Brown Vec X; 4308b7f5c055SJed Brown PetscScalar *x; 4309f1d4225fSZach Atkins 43109566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 4311f1d4225fSZach Atkins PetscCall(DMGetCoordinateDM(dm, &cdm)); 4312f1d4225fSZach Atkins PetscCall(DMGetCoordinateDM(dmf, &cdmf)); 4313f1d4225fSZach Atkins PetscCall(DMCopyDisc(cdm, cdmf)); 431469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 4315b7f5c055SJed Brown 43169566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 43179566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 43189566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 431948a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 43209566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 4321b7f5c055SJed Brown } 4322b7f5c055SJed Brown 4323b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 43249566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 43259566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 4326b7f5c055SJed Brown 432746139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 432846139095SJed Brown 4329b7f5c055SJed Brown if (thickness > 0) { 43304663dae6SJed Brown DM edm, cdm, ecdm; 43314663dae6SJed Brown DMPlexTransform tr; 43324663dae6SJed Brown const char *prefix; 43334663dae6SJed Brown PetscOptions options; 43344663dae6SJed Brown // Code from DMPlexExtrude 43354663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 43364663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 4337ce78bad3SBarry Smith PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDETYPE)); 43384663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 43394663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 43404663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 43414663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 43424663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 43434663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 43444663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 43454663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 43464663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 43474663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 43484663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 43494663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 43504663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 43514663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 43524663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 43534663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 43544663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 43554663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 43564663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 43574663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 4358a77a5016SMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, edm)); 435969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 4360b7f5c055SJed Brown } 43613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4362b7f5c055SJed Brown } 4363b7f5c055SJed Brown 4364b7f5c055SJed Brown /*@ 4365b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 4366b7f5c055SJed Brown 4367b7f5c055SJed Brown Collective 4368b7f5c055SJed Brown 4369b7f5c055SJed Brown Input Parameters: 4370a1cb98faSBarry Smith + comm - The communicator for the `DM` object 4371b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 4372b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 437320f4b53cSBarry Smith . periodic - array of length 3 with periodicity, or `NULL` for non-periodic 43741436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 4375817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 43761436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 4377817da375SSatish Balay - thickness - Thickness in normal direction 4378b7f5c055SJed Brown 4379b7f5c055SJed Brown Output Parameter: 4380a1cb98faSBarry Smith . dm - The `DM` object 4381a1cb98faSBarry Smith 4382a1cb98faSBarry Smith Level: beginner 4383b7f5c055SJed Brown 4384b7f5c055SJed Brown Notes: 438515229ffcSPierre Jolivet This meshes the surface of the Schwarz P or Gyroid surfaces. Schwarz P is the simplest member of the triply-periodic minimal surfaces. 43861d27aa22SBarry Smith <https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22)> and can be cut with "clean" boundaries. 43871d27aa22SBarry 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. 4388b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 4389b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 4390b7f5c055SJed Brown This projection could readily be extended to related surfaces. 4391b7f5c055SJed Brown 43921d27aa22SBarry Smith See {cite}`maskery2018insights` 43931d27aa22SBarry Smith 43941d27aa22SBarry Smith The face (edge) sets for the Schwarz P surface are numbered $1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z)$. 43951d27aa22SBarry Smith When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). 43961d27aa22SBarry Smith Use `DMPlexLabelComplete()` to propagate to coarse-level vertices. 4397b7f5c055SJed Brown 439860225df5SJacob Faibussowitsch Developer Notes: 4399b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 4400b7f5c055SJed Brown 44011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 4402b7f5c055SJed Brown @*/ 4403d71ae5a4SJacob 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) 4404d71ae5a4SJacob Faibussowitsch { 4405b7f5c055SJed Brown PetscFunctionBegin; 44069566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44079566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 44089566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 44093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4410b7f5c055SJed Brown } 4411b7f5c055SJed Brown 44129318fe57SMatthew G. Knepley /*@ 44139318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 44149318fe57SMatthew G. Knepley 44159318fe57SMatthew G. Knepley Collective 44169318fe57SMatthew G. Knepley 44179318fe57SMatthew G. Knepley Input Parameters: 4418a1cb98faSBarry Smith + comm - The communicator for the `DM` object 44199318fe57SMatthew G. Knepley . dim - The dimension 44209318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 44219318fe57SMatthew G. Knepley - R - The radius 44229318fe57SMatthew G. Knepley 44239318fe57SMatthew G. Knepley Output Parameter: 4424a1cb98faSBarry Smith . dm - The `DM` object 44259318fe57SMatthew G. Knepley 44269318fe57SMatthew G. Knepley Level: beginner 44279318fe57SMatthew G. Knepley 44281cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 44299318fe57SMatthew G. Knepley @*/ 4430d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 4431d71ae5a4SJacob Faibussowitsch { 44329318fe57SMatthew G. Knepley PetscFunctionBegin; 44334f572ea9SToby Isaac PetscAssertPointer(dm, 5); 44349566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44359566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 44369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 44373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44389318fe57SMatthew G. Knepley } 44399318fe57SMatthew G. Knepley 4440d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 4441d71ae5a4SJacob Faibussowitsch { 44429318fe57SMatthew G. Knepley DM sdm, vol; 44439318fe57SMatthew G. Knepley DMLabel bdlabel; 4444dd2b43ebSStefano Zampini const char *prefix; 44459318fe57SMatthew G. Knepley 44469318fe57SMatthew G. Knepley PetscFunctionBegin; 44479566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 44489566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 4449dd2b43ebSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 4450dd2b43ebSStefano Zampini PetscCall(DMSetOptionsPrefix(sdm, prefix)); 4451dd2b43ebSStefano Zampini PetscCall(DMAppendOptionsPrefix(sdm, "bd_")); 4452dd2b43ebSStefano Zampini PetscCall(DMPlexDistributeSetDefault(sdm, PETSC_FALSE)); 44539566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 44549566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 44559566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 44569566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 44579566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 445869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 44599566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 44609566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 44619566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 44629566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 44633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 446451a74b61SMatthew G. Knepley } 446551a74b61SMatthew G. Knepley 446651a74b61SMatthew G. Knepley /*@ 446751a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 446851a74b61SMatthew G. Knepley 446951a74b61SMatthew G. Knepley Collective 447051a74b61SMatthew G. Knepley 447151a74b61SMatthew G. Knepley Input Parameters: 4472a1cb98faSBarry Smith + comm - The communicator for the `DM` object 447351a74b61SMatthew G. Knepley . dim - The dimension 447451a74b61SMatthew G. Knepley - R - The radius 447551a74b61SMatthew G. Knepley 447651a74b61SMatthew G. Knepley Output Parameter: 4477a1cb98faSBarry Smith . dm - The `DM` object 447851a74b61SMatthew G. Knepley 4479a1cb98faSBarry Smith Options Database Key: 448060225df5SJacob Faibussowitsch . bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 448151a74b61SMatthew G. Knepley 448251a74b61SMatthew G. Knepley Level: beginner 448351a74b61SMatthew G. Knepley 44841cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 448551a74b61SMatthew G. Knepley @*/ 4486d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 4487d71ae5a4SJacob Faibussowitsch { 448851a74b61SMatthew G. Knepley PetscFunctionBegin; 44899566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44909566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 44919566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 44923ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44932829fed8SMatthew G. Knepley } 44942829fed8SMatthew G. Knepley 4495d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 4496d71ae5a4SJacob Faibussowitsch { 44970a6ba040SMatthew G. Knepley PetscFunctionBegin; 44989318fe57SMatthew G. Knepley switch (ct) { 44999371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 45009318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 45019318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 45029318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 45039318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 45049318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 45059318fe57SMatthew G. Knepley 45069566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 45079566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45089371c9d4SSatish Balay } break; 45099371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 45109318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 45119318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 45129318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 45139318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 45149318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 45159318fe57SMatthew G. Knepley 45169566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 45179566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45189371c9d4SSatish Balay } break; 45199371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 4520b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 4521b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 4522b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 4523b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 4524b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 4525b5a892a1SMatthew G. Knepley 45269566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 45279566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45289371c9d4SSatish Balay } break; 45299371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 45309318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 45319318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 45329318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 45339318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 45349318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 45359318fe57SMatthew G. Knepley 45369566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45379566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45389371c9d4SSatish Balay } break; 45399371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 45409318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45419318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 45429318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45439318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 45449318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 45459318fe57SMatthew G. Knepley 45469566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45479566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45489371c9d4SSatish Balay } break; 45499371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 45509318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45519318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 45529318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45539318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 45549318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 45559318fe57SMatthew G. Knepley 45569566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45579566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45589371c9d4SSatish Balay } break; 45599371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 45609318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45619318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 4562f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45639318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 4564f0edb160SMatthew 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}; 45659318fe57SMatthew G. Knepley 45669566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45679566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45689371c9d4SSatish Balay } break; 45699371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 45709318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 45719318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 4572f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 45739318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 45749371c9d4SSatish Balay PetscScalar vertexCoords[24] = {-1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0}; 45759318fe57SMatthew G. Knepley 45769566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45779566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45789371c9d4SSatish Balay } break; 45799371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 45809318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 45819318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 4582f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 45839318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 45849371c9d4SSatish 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}; 45859318fe57SMatthew G. Knepley 45869566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45879566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45889371c9d4SSatish Balay } break; 45899371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 45909318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 45919318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 45929318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 45939318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 45949371c9d4SSatish 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}; 45959318fe57SMatthew G. Knepley 45969566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45979566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45989371c9d4SSatish Balay } break; 45999371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 46009318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 46019318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 46029318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 46039318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 46049371c9d4SSatish 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}; 46059318fe57SMatthew G. Knepley 46069566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 46079566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 46089371c9d4SSatish Balay } break; 46099371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 46109318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 46119318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 4612f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 46139318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 46149371c9d4SSatish 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}; 46159318fe57SMatthew G. Knepley 46169566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 46179566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 46189371c9d4SSatish Balay } break; 4619d71ae5a4SJacob Faibussowitsch default: 4620d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 46219318fe57SMatthew G. Knepley } 46229318fe57SMatthew G. Knepley { 46239318fe57SMatthew G. Knepley PetscInt Nv, v; 46249318fe57SMatthew G. Knepley 46259318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 46269566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 46279566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 46289566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 46299566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 46309318fe57SMatthew G. Knepley } 46319566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 46329566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 46333ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46340a6ba040SMatthew G. Knepley } 46350a6ba040SMatthew G. Knepley 46369318fe57SMatthew G. Knepley /*@ 4637a1cb98faSBarry Smith DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell 46389318fe57SMatthew G. Knepley 46399318fe57SMatthew G. Knepley Collective 46409318fe57SMatthew G. Knepley 46419318fe57SMatthew G. Knepley Input Parameters: 46429318fe57SMatthew G. Knepley + comm - The communicator 46439318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 46449318fe57SMatthew G. Knepley 46459318fe57SMatthew G. Knepley Output Parameter: 46469318fe57SMatthew G. Knepley . refdm - The reference cell 46479318fe57SMatthew G. Knepley 46489318fe57SMatthew G. Knepley Level: intermediate 46499318fe57SMatthew G. Knepley 465042747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()` 46519318fe57SMatthew G. Knepley @*/ 4652d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 4653d71ae5a4SJacob Faibussowitsch { 46540a6ba040SMatthew G. Knepley PetscFunctionBegin; 46559566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 46569566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 46579566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 46583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46599318fe57SMatthew G. Knepley } 466079a015ccSMatthew G. Knepley 4661d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 4662d71ae5a4SJacob Faibussowitsch { 46639318fe57SMatthew G. Knepley DM plex; 46649318fe57SMatthew G. Knepley DMLabel label; 46659318fe57SMatthew G. Knepley PetscBool hasLabel; 46660a6ba040SMatthew G. Knepley 4667c22d3578SMatthew G. Knepley PetscFunctionBegin; 46689566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 46693ba16761SJacob Faibussowitsch if (hasLabel) PetscFunctionReturn(PETSC_SUCCESS); 46709566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 46719566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 46729566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 46739566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 46741c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 46759566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 46763ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46779318fe57SMatthew G. Knepley } 4678acdc6f61SToby Isaac 4679669647acSMatthew G. Knepley /* 4680669647acSMatthew 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. 4681669647acSMatthew G. Knepley 4682669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 4683669647acSMatthew G. Knepley */ 4684d71ae5a4SJacob 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[]) 4685d71ae5a4SJacob Faibussowitsch { 4686669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 4687669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 4688669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 4689669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 4690669647acSMatthew G. Knepley 4691669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 4692669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 4693669647acSMatthew G. Knepley } 4694669647acSMatthew G. Knepley 46955390be7dSMatthew G. Knepley // Insert vertices and their joins, marked by depth 46965390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Vertices(DM dm, DMLabel label, DMLabel vlabel, PetscInt val, PetscInt n, const PetscInt vertices[]) 46975390be7dSMatthew G. Knepley { 46985390be7dSMatthew G. Knepley PetscFunctionBegin; 46995390be7dSMatthew G. Knepley PetscCall(DMPlexMarkSubmesh_Interpolated(dm, vlabel, val, PETSC_FALSE, PETSC_FALSE, label, NULL)); 47005390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 47015390be7dSMatthew G. Knepley } 47025390be7dSMatthew G. Knepley 47035390be7dSMatthew G. Knepley // Insert faces and their closures, marked by depth 47045390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Faces(DM dm, DMLabel label, PetscInt n, const PetscInt faces[]) 47055390be7dSMatthew G. Knepley { 47065390be7dSMatthew G. Knepley PetscFunctionBegin; 47075390be7dSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) { 47085390be7dSMatthew G. Knepley const PetscInt point = faces[p]; 47095390be7dSMatthew G. Knepley PetscInt *closure = NULL; 47105390be7dSMatthew G. Knepley PetscInt clSize, pdepth; 47115390be7dSMatthew G. Knepley 47125390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, point, &pdepth)); 47135390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, point, pdepth)); 47145390be7dSMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 47155390be7dSMatthew G. Knepley for (PetscInt cl = 0; cl < clSize * 2; cl += 2) { 47165390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, closure[cl], &pdepth)); 47175390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, closure[cl], pdepth)); 47185390be7dSMatthew G. Knepley } 47195390be7dSMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 47205390be7dSMatthew G. Knepley } 47215390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 47225390be7dSMatthew G. Knepley } 47235390be7dSMatthew G. Knepley 47244e22dd4cSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *flg); 47254e22dd4cSMatthew G. Knepley 47265dca41c3SJed Brown const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "zbox", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 47279318fe57SMatthew G. Knepley 4728ce78bad3SBarry Smith static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 4729d71ae5a4SJacob Faibussowitsch { 47309318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 47319318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 47329318fe57SMatthew G. Knepley PetscInt dim = 2; 4733b9da1bb3SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, orient = PETSC_FALSE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 4734d0812dedSMatthew G. Knepley PetscBool flg, flg2, fflg, strflg, bdfflg, nameflg; 47359318fe57SMatthew G. Knepley MPI_Comm comm; 4736ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4737ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4738ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 47394e22dd4cSMatthew G. Knepley const char *option; 47409318fe57SMatthew G. Knepley 47419318fe57SMatthew G. Knepley PetscFunctionBegin; 4742708be2fdSJed Brown PetscCall(PetscLogEventBegin(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 47439566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 47449318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 47459566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 4746d0812dedSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_file_contents", "Contents of a file format in a string", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &strflg)); 47479566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 47489566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 47499566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 47509566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 47519566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 47529566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 47539566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 47549566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 4755b9da1bb3SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_orient", "Orient the constructed mesh", "DMPlexOrient", orient, &orient, &flg)); 47569566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 47579566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 47589566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 47593f3e541fSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_adj", "Debug output level all adjacency computations", "", 0, &((DM_Plex *)dm->data)->printAdj, NULL, 0)); 47609318fe57SMatthew G. Knepley 476161a622f3SMatthew G. Knepley switch (cell) { 476261a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 476361a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 476461a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 476561a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 476661a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 476761a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 4768d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 4769d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_TRUE; 4770d71ae5a4SJacob Faibussowitsch break; 4771d71ae5a4SJacob Faibussowitsch default: 4772d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_FALSE; 4773d71ae5a4SJacob Faibussowitsch break; 477461a622f3SMatthew G. Knepley } 477561a622f3SMatthew G. Knepley 47769318fe57SMatthew G. Knepley if (fflg) { 47779318fe57SMatthew G. Knepley DM dmnew; 47781e4a82c4SMatthew G. Knepley const char *name; 47799318fe57SMatthew G. Knepley 47801e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 47811e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, nameflg ? plexname : name, interpolate, &dmnew)); 47825de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 478369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 47849318fe57SMatthew G. Knepley } else if (refDomain) { 47859566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 47869318fe57SMatthew G. Knepley } else if (bdfflg) { 47879318fe57SMatthew G. Knepley DM bdm, dmnew; 47881e4a82c4SMatthew G. Knepley const char *name; 47899318fe57SMatthew G. Knepley 47901e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 47911e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, nameflg ? plexname : name, interpolate, &bdm)); 47929566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 47939566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 47949566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 47959566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 47965de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 479769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 4798d0812dedSMatthew G. Knepley } else if (strflg) { 4799d0812dedSMatthew G. Knepley DM dmnew; 4800d0812dedSMatthew G. Knepley PetscViewer viewer; 4801d0812dedSMatthew G. Knepley const char *contents; 4802d0812dedSMatthew G. Knepley char *strname; 4803d0812dedSMatthew G. Knepley char tmpdir[PETSC_MAX_PATH_LEN]; 4804d0812dedSMatthew G. Knepley char tmpfilename[PETSC_MAX_PATH_LEN]; 4805d0812dedSMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 4806d0812dedSMatthew G. Knepley MPI_Comm comm; 4807d0812dedSMatthew G. Knepley PetscMPIInt rank; 4808d0812dedSMatthew G. Knepley 4809d0812dedSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4810d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 4811d0812dedSMatthew G. Knepley PetscCall(PetscStrchr(filename, ':', &strname)); 4812d0812dedSMatthew G. Knepley PetscCheck(strname, comm, PETSC_ERR_ARG_WRONG, "File contents must have the form \"ext:string_name\", not %s", filename); 4813d0812dedSMatthew G. Knepley strname[0] = '\0'; 4814d0812dedSMatthew G. Knepley ++strname; 4815d0812dedSMatthew G. Knepley PetscCall(PetscDLSym(NULL, strname, (void **)&contents)); 4816d0812dedSMatthew G. Knepley PetscCheck(contents, comm, PETSC_ERR_ARG_WRONG, "Could not locate mesh string %s", strname); 4817d0812dedSMatthew G. Knepley PetscCall(PetscGetTmp(comm, tmpdir, PETSC_MAX_PATH_LEN)); 4818ed32af8cSMatthew G. Knepley PetscCall(PetscStrlcat(tmpdir, "/meshXXXXXX", PETSC_MAX_PATH_LEN)); 4819ed32af8cSMatthew G. Knepley PetscCall(PetscMkdtemp(tmpdir)); 4820ed32af8cSMatthew G. Knepley PetscCall(PetscSNPrintf(tmpfilename, PETSC_MAX_PATH_LEN, "%s/mesh.%s", tmpdir, filename)); 4821d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIOpen(comm, tmpfilename, &viewer)); 4822d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", contents)); 4823d0812dedSMatthew G. Knepley PetscCall(PetscViewerDestroy(&viewer)); 4824d0812dedSMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), tmpfilename, plexname, interpolate, &dmnew)); 4825ed32af8cSMatthew G. Knepley PetscCall(PetscRMTree(tmpdir)); 4826d0812dedSMatthew G. Knepley PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%s Mesh", strname)); 4827d0812dedSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, name)); 4828d0812dedSMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 4829d0812dedSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 48309318fe57SMatthew G. Knepley } else { 48319566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 48329318fe57SMatthew G. Knepley switch (shape) { 4833669647acSMatthew G. Knepley case DM_SHAPE_BOX: 48345dca41c3SJed Brown case DM_SHAPE_ZBOX: 4835669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 48369318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 48379318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 48389318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 48399318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4840669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 48419318fe57SMatthew G. Knepley PetscInt i, n; 48429318fe57SMatthew G. Knepley 48439318fe57SMatthew G. Knepley n = dim; 48449318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 48459566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 48469318fe57SMatthew G. Knepley n = 3; 48479566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 484863a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 48499318fe57SMatthew G. Knepley n = 3; 48509566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 485163a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 48529318fe57SMatthew G. Knepley n = 3; 48539566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 485463a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 4855669647acSMatthew G. Knepley 4856669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 4857669647acSMatthew G. Knepley if (isAnnular) 4858669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 4859669647acSMatthew G. Knepley 48609318fe57SMatthew G. Knepley switch (cell) { 486161a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 48629566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 4863d410b0cfSMatthew G. Knepley if (!interpolate) { 4864d410b0cfSMatthew G. Knepley DM udm; 4865d410b0cfSMatthew G. Knepley 48669566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 486769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 4868d410b0cfSMatthew G. Knepley } 48699318fe57SMatthew G. Knepley break; 4870d71ae5a4SJacob Faibussowitsch default: 48715dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(dm, shape, dim, simplex, faces, lower, upper, bdt, interpolate)); 4872d71ae5a4SJacob Faibussowitsch break; 48739318fe57SMatthew G. Knepley } 4874669647acSMatthew G. Knepley if (isAnnular) { 4875669647acSMatthew G. Knepley DM cdm; 4876669647acSMatthew G. Knepley PetscDS cds; 4877669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 4878669647acSMatthew G. Knepley 4879669647acSMatthew G. Knepley // Fix coordinates for annular region 4880669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 4881669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 4882669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 4883e65c294aSksagiyam PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE)); 4884669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 4885669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 4886669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 4887669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 4888669647acSMatthew G. Knepley } 48899371c9d4SSatish Balay } break; 48909371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 48919318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 48929318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 48939318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 48949318fe57SMatthew G. Knepley PetscInt i, n; 48959318fe57SMatthew G. Knepley 48969318fe57SMatthew G. Knepley n = dim + 1; 48979318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 48989566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 48999318fe57SMatthew G. Knepley n = 3; 49009566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 490163a3b9bcSJacob 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); 49029318fe57SMatthew G. Knepley n = 3; 49039566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 490463a3b9bcSJacob 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); 49059566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 49069371c9d4SSatish Balay } break; 49079371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 49089318fe57SMatthew G. Knepley PetscReal R = 1.0; 49099318fe57SMatthew G. Knepley 49109566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 49119566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 49129371c9d4SSatish Balay } break; 49139371c9d4SSatish Balay case DM_SHAPE_BALL: { 49149318fe57SMatthew G. Knepley PetscReal R = 1.0; 49159318fe57SMatthew G. Knepley 49169566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 49179566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 49189371c9d4SSatish Balay } break; 49199371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 49209318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 49219318fe57SMatthew G. Knepley PetscInt Nw = 6; 492249704ca5SMatthew G. Knepley PetscInt Nr = 0; 49239318fe57SMatthew G. Knepley 49249566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 49259566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 492649704ca5SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_refine", "Number of refinements before projection", "", Nr, &Nr, NULL)); 49279318fe57SMatthew G. Knepley switch (cell) { 4928d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_TRI_PRISM_TENSOR: 4929d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 4930d71ae5a4SJacob Faibussowitsch break; 4931d71ae5a4SJacob Faibussowitsch default: 493249704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt, Nr)); 4933d71ae5a4SJacob Faibussowitsch break; 49349318fe57SMatthew G. Knepley } 49359371c9d4SSatish Balay } break; 4936b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 49379371c9d4SSatish Balay case DM_SHAPE_GYROID: { 4938b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 4939b7f5c055SJed Brown PetscReal thickness = 0.; 4940b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4941b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 49421436d7faSJed Brown PetscBool tps_distribute; 49439566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 49449566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 49459566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 49469566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 49479566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 49489566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 49499566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 49509566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 49519371c9d4SSatish Balay } break; 49529371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 495305bd46c0SStefano Zampini DM dmnew; 495405bd46c0SStefano Zampini PetscReal rl = 0.0; 495505bd46c0SStefano Zampini 495605bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 495705bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 49585de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 495969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 49609371c9d4SSatish Balay } break; 4961cfb853baSMatthew G. Knepley case DM_SHAPE_HYPERCUBIC: { 49628d2ec52aSSatish Balay PetscInt *edges, overlap = 1; 4963cfb853baSMatthew G. Knepley PetscReal *lower, *upper; 4964cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 4965cfb853baSMatthew G. Knepley PetscInt n, d; 4966cfb853baSMatthew G. Knepley 4967cfb853baSMatthew G. Knepley *useCoordSpace = PETSC_FALSE; 4968cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt)); 4969cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 4970cfb853baSMatthew G. Knepley edges[d] = 1; 4971cfb853baSMatthew G. Knepley lower[d] = 0.; 4972cfb853baSMatthew G. Knepley upper[d] = 1.; 4973cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 4974cfb853baSMatthew G. Knepley } 4975cfb853baSMatthew G. Knepley n = dim; 4976cfb853baSMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg)); 4977cfb853baSMatthew G. Knepley n = dim; 4978cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 4979cfb853baSMatthew 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); 4980cfb853baSMatthew G. Knepley n = dim; 4981cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 4982cfb853baSMatthew 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); 4983cfb853baSMatthew G. Knepley n = dim; 4984cfb853baSMatthew G. Knepley PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 4985cfb853baSMatthew 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); 49868d2ec52aSSatish Balay PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", overlap, &overlap, NULL, 0)); 49878d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, overlap, bdt)); 4988cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edges, lower, upper, bdt)); 4989cfb853baSMatthew G. Knepley } break; 4990d71ae5a4SJacob Faibussowitsch default: 4991d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 49929318fe57SMatthew G. Knepley } 49939318fe57SMatthew G. Knepley } 49949566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 499548a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 4996b9da1bb3SMatthew G. Knepley if (orient) PetscCall(DMPlexOrient(dm)); 49974e22dd4cSMatthew G. Knepley // Allow label creation 49984e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_label_", &option, NULL, &flg)); 49994e22dd4cSMatthew G. Knepley if (flg) { 50004e22dd4cSMatthew G. Knepley DMLabel label; 5001db1ec57dSMatthew G. Knepley PetscInt *points, cStart, cEnd, n; 50024e22dd4cSMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 50034e22dd4cSMatthew G. Knepley const char *name = &option[14]; 50044e22dd4cSMatthew G. Knepley 5005db1ec57dSMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 5006db1ec57dSMatthew G. Knepley n = PetscMax(cEnd - cStart, 1024); 5007db1ec57dSMatthew G. Knepley PetscCall(PetscMalloc1(n, &points)); 50084e22dd4cSMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 50094e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 50104e22dd4cSMatthew G. Knepley fulloption[0] = '-'; 50114e22dd4cSMatthew G. Knepley fulloption[1] = 0; 50124e22dd4cSMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, option, PETSC_MAX_PATH_LEN)); 50134e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, NULL)); 50144e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) PetscCall(DMLabelSetValue(label, points[p], 1)); 5015db1ec57dSMatthew G. Knepley PetscCall(PetscFree(points)); 50164e22dd4cSMatthew G. Knepley } 5017dd0eeac9SMatthew G. Knepley // Allow cohesive label creation 5018dd0eeac9SMatthew G. Knepley // Faces are input, completed, and all points are marked with their depth 5019dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_cohesive_label_", &option, NULL, &flg)); 5020dd0eeac9SMatthew G. Knepley if (flg) { 5021dd0eeac9SMatthew G. Knepley DMLabel label; 5022dd0eeac9SMatthew G. Knepley PetscInt points[1024], n, pStart, pEnd, Nl = 1; 50235390be7dSMatthew G. Knepley PetscBool noCreate = PETSC_FALSE; 5024dd0eeac9SMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 5025dd0eeac9SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 5026dd0eeac9SMatthew G. Knepley size_t len; 5027dd0eeac9SMatthew G. Knepley 5028dd0eeac9SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 5029dd0eeac9SMatthew G. Knepley PetscCall(PetscStrncpy(name, &option[23], PETSC_MAX_PATH_LEN)); 5030dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlen(name, &len)); 5031dd0eeac9SMatthew G. Knepley if (name[len - 1] == '0') Nl = 10; 5032dd0eeac9SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 50336497c311SBarry Smith if (l > 0) name[len - 1] = (char)('0' + l); 5034dd0eeac9SMatthew G. Knepley fulloption[0] = 0; 5035dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, "-dm_plex_cohesive_label_", 32)); 5036dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, name, PETSC_MAX_PATH_LEN - 32)); 5037dd0eeac9SMatthew G. Knepley n = 1024; 5038dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, &flg)); 5039dd0eeac9SMatthew G. Knepley if (!flg) break; 50405390be7dSMatthew G. Knepley PetscCall(DMHasLabel(dm, name, &noCreate)); 50415390be7dSMatthew G. Knepley if (noCreate) { 50425390be7dSMatthew G. Knepley DMLabel inlabel; 50435390be7dSMatthew G. Knepley IS pointIS; 50445390be7dSMatthew G. Knepley const PetscInt *lpoints; 50455390be7dSMatthew G. Knepley PetscInt pdep, ln, inval = points[0]; 50465390be7dSMatthew G. Knepley char newname[PETSC_MAX_PATH_LEN]; 50475390be7dSMatthew G. Knepley 50485390be7dSMatthew G. Knepley PetscCheck(n == 1, comm, PETSC_ERR_ARG_WRONG, "Must specify a label value with this option"); 50495390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &inlabel)); 50505390be7dSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(inlabel, inval, &pointIS)); 50515390be7dSMatthew G. Knepley PetscCall(ISGetLocalSize(pointIS, &ln)); 50525390be7dSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &lpoints)); 50535390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, lpoints[0], &pdep)); 50545390be7dSMatthew G. Knepley PetscCall(PetscSNPrintf(newname, PETSC_MAX_PATH_LEN, "%s%" PetscInt_FMT, name, points[0])); 50555390be7dSMatthew G. Knepley PetscCall(DMCreateLabel(dm, newname)); 50565390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, newname, &label)); 50575390be7dSMatthew G. Knepley if (!pdep) PetscCall(ProcessCohesiveLabel_Vertices(dm, label, inlabel, inval, ln, lpoints)); 50585390be7dSMatthew G. Knepley else PetscCall(ProcessCohesiveLabel_Faces(dm, label, ln, lpoints)); 50595390be7dSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &lpoints)); 50605390be7dSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 50615390be7dSMatthew G. Knepley } else { 5062dd0eeac9SMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 5063dd0eeac9SMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 5064dd0eeac9SMatthew G. Knepley if (pStart >= pEnd) n = 0; 50655390be7dSMatthew G. Knepley PetscCall(ProcessCohesiveLabel_Faces(dm, label, n, points)); 5066dd0eeac9SMatthew G. Knepley } 5067dd0eeac9SMatthew G. Knepley PetscCall(DMPlexOrientLabel(dm, label)); 50680542aa8cSMatthew G. Knepley PetscCall(DMPlexLabelCohesiveComplete(dm, label, NULL, 1, PETSC_FALSE, PETSC_FALSE, NULL)); 5069dd0eeac9SMatthew G. Knepley } 5070dd0eeac9SMatthew G. Knepley } 50715390be7dSMatthew G. Knepley PetscCall(DMViewFromOptions(dm, NULL, "-created_dm_view")); 5072708be2fdSJed Brown PetscCall(PetscLogEventEnd(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 50733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50740a6ba040SMatthew G. Knepley } 50750a6ba040SMatthew G. Knepley 5076ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems PetscOptionsObject) 5077d71ae5a4SJacob Faibussowitsch { 50780a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 50797f9d8d6cSVaclav Hapla PetscBool flg, flg2; 50809318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 5081adc21957SMatthew G. Knepley char method[PETSC_MAX_PATH_LEN]; 50820a6ba040SMatthew G. Knepley 50830a6ba040SMatthew G. Knepley PetscFunctionBegin; 50840a6ba040SMatthew G. Knepley /* Handle viewing */ 50859566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 50865962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level for all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 50875962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fvm", "Debug output level for all fvm computations", "DMPlexSNESComputeResidualFVM", 0, &mesh->printFVM, NULL, 0)); 50889566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 50899566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 5090f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 5091a77a5016SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_project", "Debug output level all projection computations", "DMPlexProject", 0, &mesh->printProject, NULL, 0)); 50929566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 50939566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 50945e2c5519SMatthew G. Knepley // Interpolation 50955e2c5519SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_interpolate_prefer_tensor", "When different orderings exist, prefer the tensor order", "DMPlexSetInterpolationPreferTensor", mesh->interpolatePreferTensor, &mesh->interpolatePreferTensor, NULL)); 50969318fe57SMatthew G. Knepley /* Labeling */ 50970b595cf8SStefano Zampini PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", NULL, bdLabel, sizeof(bdLabel), &flg)); 50989566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 5099953fc75cSMatthew G. Knepley /* Point Location */ 51009566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 51010848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 51029566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 5103d02c7345SMatthew G. Knepley /* Reordering */ 5104adc21957SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_reorder_section", "Compute point permutation for local section", "DMReorderSectionSetDefault", PETSC_FALSE, &flg2, &flg)); 5105adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetDefault(dm, flg2 ? DM_REORDER_DEFAULT_TRUE : DM_REORDER_DEFAULT_FALSE)); 51060b595cf8SStefano Zampini PetscCall(PetscOptionsString("-dm_reorder_section_type", "Reordering method for local section", "DMReorderSectionSetType", NULL, method, PETSC_MAX_PATH_LEN, &flg)); 5107adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetType(dm, method)); 51082e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 51099566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 511061f058f9SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_save_transform", "Save the transform producing this mesh", "DMAdapt", PETSC_FALSE, &mesh->saveTransform, NULL)); 5111b29cfa1cSToby Isaac /* Projection behavior */ 5112d5b43468SJose E. Roman PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 51139566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 5114f12cf164SMatthew G. Knepley /* Checking structure */ 5115f12cf164SMatthew G. Knepley { 51167f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 5117f12cf164SMatthew G. Knepley 51187f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 51197f9d8d6cSVaclav Hapla if (all) { 51207f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 51217f9d8d6cSVaclav Hapla } else { 51229566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 51237f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 51249566063dSJacob 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)); 51257f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 51269566063dSJacob 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)); 51277f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 51289566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 51297f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 51309566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 5131d7d32a9aSMatthew G. Knepley if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 51329566063dSJacob 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)); 51337f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 51347f9d8d6cSVaclav Hapla } 51359566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 51369566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 5137f12cf164SMatthew G. Knepley } 51389318fe57SMatthew G. Knepley { 51399318fe57SMatthew G. Knepley PetscReal scale = 1.0; 51404f3833eaSMatthew G. Knepley 51419566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 51429318fe57SMatthew G. Knepley if (flg) { 51439318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 51449318fe57SMatthew G. Knepley 51459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 51469566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 51479566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 51489566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 51499318fe57SMatthew G. Knepley } 51509318fe57SMatthew G. Knepley } 51519566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 51523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 515368d4fef7SMatthew G. Knepley } 515468d4fef7SMatthew G. Knepley 5155ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems PetscOptionsObject, PetscInt *overlap) 5156d71ae5a4SJacob Faibussowitsch { 5157c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 5158c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 5159c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 5160c506a872SMatthew G. Knepley PetscBool flg; 5161c506a872SMatthew G. Knepley 5162c506a872SMatthew G. Knepley PetscFunctionBegin; 5163c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 5164c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 5165c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 5166c506a872SMatthew G. Knepley if (numOvLabels) { 5167c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 5168c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 5169c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 5170c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 5171c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 5172c506a872SMatthew G. Knepley } 5173c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 5174c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 5175c506a872SMatthew 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); 5176c506a872SMatthew G. Knepley 5177c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 5178c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 5179c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 5180c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 5181c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 5182c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 5183c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 5184c506a872SMatthew G. Knepley } 5185c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 5186c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 5187c506a872SMatthew 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); 5188c506a872SMatthew G. Knepley } 51893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5190c506a872SMatthew G. Knepley } 5191c506a872SMatthew G. Knepley 5192ce78bad3SBarry Smith static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems PetscOptionsObject) 5193d71ae5a4SJacob Faibussowitsch { 5194bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 5195bdf63967SMatthew G. Knepley char oname[256]; 51964e22dd4cSMatthew G. Knepley char sublabelname[PETSC_MAX_PATH_LEN] = ""; 5197adc21957SMatthew G. Knepley DMReorderDefaultFlag reorder; 5198d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 51999318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 5200530e699aSMatthew 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; 520168d4fef7SMatthew G. Knepley 520268d4fef7SMatthew G. Knepley PetscFunctionBegin; 5203d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 5204dd4c3f67SMatthew G. Knepley if (dm->cloneOpts) goto non_refine; 52059318fe57SMatthew G. Knepley /* Handle automatic creation */ 52069566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 5207530e699aSMatthew G. Knepley if (dim < 0) PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 52086bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 5209d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 52109566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 5211d89e6e46SMatthew G. Knepley if (flg) { 5212d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 5213d89e6e46SMatthew G. Knepley 52149566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 5215d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 5216d89e6e46SMatthew G. Knepley DM udm; 5217d89e6e46SMatthew G. Knepley 52189566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 521969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 5220d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 5221d89e6e46SMatthew G. Knepley DM idm; 5222d89e6e46SMatthew G. Knepley 52239566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 522469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 5225d89e6e46SMatthew G. Knepley } 5226d89e6e46SMatthew G. Knepley } 52274e22dd4cSMatthew G. Knepley // Handle submesh selection before distribution 52284e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_submesh", "Label to use for submesh selection", "", sublabelname, sublabelname, PETSC_MAX_PATH_LEN, &flg)); 52294e22dd4cSMatthew G. Knepley if (flg) { 52304e22dd4cSMatthew G. Knepley DM subdm; 52314e22dd4cSMatthew G. Knepley DMLabel label; 52324e22dd4cSMatthew G. Knepley IS valueIS, pointIS; 52334e22dd4cSMatthew G. Knepley const PetscInt *values, *points; 52344e22dd4cSMatthew G. Knepley PetscBool markedFaces = PETSC_FALSE; 52354e22dd4cSMatthew G. Knepley PetscInt Nv, value, Np; 52364e22dd4cSMatthew G. Knepley 52374e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, sublabelname, &label)); 52384e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &Nv)); 52394e22dd4cSMatthew 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); 52404e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetValueIS(label, &valueIS)); 52414e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &values)); 52424e22dd4cSMatthew G. Knepley value = values[0]; 52434e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(valueIS, &values)); 52444e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 52454e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumSize(label, value, &Np)); 52464e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, value, &pointIS)); 52474e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &points)); 52484e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 52494e22dd4cSMatthew G. Knepley PetscInt pdepth; 52504e22dd4cSMatthew G. Knepley 52514e22dd4cSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, points[p], &pdepth)); 52524e22dd4cSMatthew G. Knepley if (pdepth) { 52534e22dd4cSMatthew G. Knepley markedFaces = PETSC_TRUE; 52544e22dd4cSMatthew G. Knepley break; 52554e22dd4cSMatthew G. Knepley } 52564e22dd4cSMatthew G. Knepley } 52574e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &points)); 52584e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 52594e22dd4cSMatthew G. Knepley PetscCall(DMPlexCreateSubmesh(dm, label, value, markedFaces, &subdm)); 52604e22dd4cSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &subdm)); 52614e22dd4cSMatthew G. Knepley PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 52624e22dd4cSMatthew G. Knepley } 52639b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 52649566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 52659566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 52669566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 52679566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 52689566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 52699566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 52709318fe57SMatthew G. Knepley if (flg) { 52719566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 52729566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 52739318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 52749318fe57SMatthew G. Knepley } 5275b23db253SStefano Zampini if (prerefine) PetscCall(DMLocalizeCoordinates(dm)); 52769b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 52779b44eab4SMatthew G. Knepley DM rdm; 52782192575eSBarry Smith PetscPointFn *coordFunc; 52799b44eab4SMatthew G. Knepley 5280509b31aaSMatthew G. Knepley PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc)); 5281dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 52829566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 528369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 5284dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 528561a622f3SMatthew G. Knepley if (coordFunc && remap) { 52869566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 5287509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, coordFunc)); 52889b44eab4SMatthew G. Knepley } 52899b44eab4SMatthew G. Knepley } 52909566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 52919318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 52929566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 52939318fe57SMatthew G. Knepley if (extLayers) { 52949318fe57SMatthew G. Knepley DM edm; 52959318fe57SMatthew G. Knepley 52969566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 529769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 5298509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, NULL)); 5299dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5300d410b0cfSMatthew G. Knepley extLayers = 0; 53015e17fc22SAidan Hamilton PetscCall(DMGetDimension(dm, &dim)); 53029318fe57SMatthew G. Knepley } 5303bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 53046bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 53059566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 53066bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 53079566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 5308adc21957SMatthew G. Knepley if (reorder == DM_REORDER_DEFAULT_TRUE || flg) { 5309bdf63967SMatthew G. Knepley DM pdm; 5310bdf63967SMatthew G. Knepley IS perm; 5311bdf63967SMatthew G. Knepley 53129566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 53139566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 53149566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 531569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 5316dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5317bdf63967SMatthew G. Knepley } 53189b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 53199566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 5320c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 5321a286e215SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute_save_sf", "Flag to save the migration SF", "DMPlexSetMigrationSF", saveSF, &saveSF, NULL)); 5322dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 53239b44eab4SMatthew G. Knepley if (distribute) { 53249b44eab4SMatthew G. Knepley DM pdm = NULL; 53259b44eab4SMatthew G. Knepley PetscPartitioner part; 5326a286e215SMatthew G. Knepley PetscSF sfMigration; 53279566ead2SJames Wright PetscBool use_partition_balance; 53289b44eab4SMatthew G. Knepley 53299566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 53309566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 53319566ead2SJames Wright PetscCall(DMPlexGetPartitionBalance(dm, &use_partition_balance)); 53329566ead2SJames Wright PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", use_partition_balance, &use_partition_balance, &flg)); 53339566ead2SJames Wright if (flg) PetscCall(DMPlexSetPartitionBalance(dm, use_partition_balance)); 5334a286e215SMatthew G. Knepley PetscCall(DMPlexDistribute(dm, overlap, &sfMigration, &pdm)); 53355d2873a6SJames Wright if (pdm) { 53365d2873a6SJames Wright // Delete the local section to force the existing one to be rebuilt with the distributed DM 53375d2873a6SJames Wright PetscCall(DMSetLocalSection(dm, pdm->localSection)); 53385d2873a6SJames Wright PetscCall(DMPlexReplace_Internal(dm, &pdm)); 53395d2873a6SJames Wright } 5340a286e215SMatthew G. Knepley if (saveSF) PetscCall(DMPlexSetMigrationSF(dm, sfMigration)); 5341a286e215SMatthew G. Knepley PetscCall(PetscSFDestroy(&sfMigration)); 53429b44eab4SMatthew G. Knepley } 53434054ae39SJames Wright 53444054ae39SJames Wright { 53454054ae39SJames Wright PetscBool useBoxLabel = PETSC_FALSE; 53464054ae39SJames Wright PetscCall(PetscOptionsBool("-dm_plex_box_label", "Create 'Face Sets' assuming boundary faces align with cartesian directions", "DMCreate", useBoxLabel, &useBoxLabel, NULL)); 5347d7d2d1d2SJames Wright if (useBoxLabel) { 5348d7d2d1d2SJames Wright PetscInt n = 3; 5349d7d2d1d2SJames Wright DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 5350d7d2d1d2SJames Wright 5351d7d2d1d2SJames Wright PetscCall(PetscOptionsEnumArray("-dm_plex_box_label_bd", "Boundary type for each dimension when using -dm_plex_box_label", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 5352d7d2d1d2SJames 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); 5353d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, bdt)); 5354d7d2d1d2SJames Wright } 53554054ae39SJames Wright } 5356d2b2dc1eSMatthew G. Knepley /* Must check CEED options before creating function space for coordinates */ 5357d2b2dc1eSMatthew G. Knepley { 5358d2b2dc1eSMatthew G. Knepley PetscBool useCeed = PETSC_FALSE, flg; 5359d2b2dc1eSMatthew G. Knepley 5360d2b2dc1eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_use_ceed", "Use LibCEED as the FEM backend", "DMPlexSetUseCeed", useCeed, &useCeed, &flg)); 5361d2b2dc1eSMatthew G. Knepley if (flg) PetscCall(DMPlexSetUseCeed(dm, useCeed)); 5362d2b2dc1eSMatthew G. Knepley } 53639318fe57SMatthew G. Knepley /* Create coordinate space */ 5364530e699aSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, NULL)); 5365530e699aSMatthew G. Knepley if (coordSpace) { 5366e44f6aebSMatthew G. Knepley PetscInt degree = 1, deg; 53675515ebd3SMatthew G. Knepley PetscInt height = 0; 53685515ebd3SMatthew G. Knepley DM cdm; 5369530e699aSMatthew G. Knepley PetscBool localize = PETSC_TRUE, sparseLocalize = PETSC_TRUE; 53709318fe57SMatthew G. Knepley 53719566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 5372e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDegree_Internal(dm, °)); 5373e65c294aSksagiyam if (coordSpace && deg <= 1) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_FALSE, PETSC_TRUE)); 53745515ebd3SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5375530e699aSMatthew G. Knepley if (!coordSpace) { 537661a622f3SMatthew G. Knepley PetscDS cds; 537761a622f3SMatthew G. Knepley PetscObject obj; 537861a622f3SMatthew G. Knepley PetscClassId id; 537961a622f3SMatthew G. Knepley 53809566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 53819566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 53829566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 538361a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 538461a622f3SMatthew G. Knepley PetscContainer dummy; 538561a622f3SMatthew G. Knepley 53869566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 53879566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 53889566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 53899566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 53909566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 539161a622f3SMatthew G. Knepley } 5392509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, NULL)); 539361a622f3SMatthew G. Knepley } 5394c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_localize", "Localize mesh coordinates", "", localize, &localize, NULL)); 5395c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "DMSetSparseLocalize", sparseLocalize, &sparseLocalize, &flg)); 5396c3db174cSMatthew G. Knepley if (flg) PetscCall(DMSetSparseLocalize(dm, sparseLocalize)); 53975515ebd3SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg)); 53985515ebd3SMatthew G. Knepley if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height)); 5399c3db174cSMatthew G. Knepley if (localize) PetscCall(DMLocalizeCoordinates(dm)); 54009318fe57SMatthew G. Knepley } 540168d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 540261a622f3SMatthew G. Knepley remap = PETSC_TRUE; 54039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 54049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 54059566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 54069566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 540768d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 5408acdc6f61SToby Isaac DM *dms, coarseDM; 540968d4fef7SMatthew G. Knepley 54109566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 54119566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 54129566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 54139566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 541468d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 54159566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 541668d4fef7SMatthew G. Knepley if (refine == 1) { 54179566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 54189566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 541968d4fef7SMatthew G. Knepley } else { 54209566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 54219566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 54229566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 54239566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 542468d4fef7SMatthew G. Knepley } 54259566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 54269566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 542768d4fef7SMatthew G. Knepley /* Free DMs */ 542868d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 5429dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 54309566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 543168d4fef7SMatthew G. Knepley } 54329566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 543368d4fef7SMatthew G. Knepley } else { 543468d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 54359318fe57SMatthew G. Knepley DM rdm; 54362192575eSBarry Smith PetscPointFn *coordFunc; 543768d4fef7SMatthew G. Knepley 5438dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54399566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 544068d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 544169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 5442dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54433674be70SMatthew G. Knepley PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc)); 544461a622f3SMatthew G. Knepley if (coordFunc && remap) { 54459566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 5446509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, coordFunc)); 544751a74b61SMatthew G. Knepley } 544868d4fef7SMatthew G. Knepley } 544968d4fef7SMatthew G. Knepley } 54503cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 54519566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 54529566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 5453b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 5454b653a561SMatthew G. Knepley DM *dms; 5455b653a561SMatthew G. Knepley 54569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 54579566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 5458b653a561SMatthew G. Knepley /* Free DMs */ 5459b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 5460dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 54619566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 5462b653a561SMatthew G. Knepley } 54639566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 5464b653a561SMatthew G. Knepley } else { 5465b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 54669318fe57SMatthew G. Knepley DM cdm; 54672192575eSBarry Smith PetscPointFn *coordFunc; 54683cf6fe12SMatthew G. Knepley 5469509b31aaSMatthew G. Knepley PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc)); 5470dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54719566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 54723cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 547369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 5474dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54759318fe57SMatthew G. Knepley if (coordFunc) { 54769566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 5477509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, coordFunc)); 54789318fe57SMatthew G. Knepley } 54793cf6fe12SMatthew G. Knepley } 5480b653a561SMatthew G. Knepley } 5481be664eb1SMatthew G. Knepley // Handle coordinate remapping 5482be664eb1SMatthew G. Knepley remap = PETSC_FALSE; 5483be664eb1SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_coord_remap", "Flag to control coordinate remapping", "", remap, &remap, NULL)); 5484be664eb1SMatthew G. Knepley if (remap) { 5485be664eb1SMatthew G. Knepley DMPlexCoordMap map = DM_COORD_MAP_NONE; 54862192575eSBarry Smith PetscPointFn *mapFunc = NULL; 5487be664eb1SMatthew G. Knepley PetscScalar params[16]; 5488f45b553cSPierre Jolivet PetscInt Np = PETSC_STATIC_ARRAY_LENGTH(params), cdim; 5489be664eb1SMatthew G. Knepley MPI_Comm comm; 5490be664eb1SMatthew G. Knepley 5491be664eb1SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 5492be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 5493be664eb1SMatthew G. Knepley PetscCall(PetscOptionsScalarArray("-dm_coord_map_params", "Parameters for the coordinate remapping", "", params, &Np, &flg)); 5494be664eb1SMatthew G. Knepley if (!flg) Np = 0; 5495be664eb1SMatthew G. Knepley // TODO Allow user to pass a map function by name 5496be664eb1SMatthew G. Knepley PetscCall(PetscOptionsEnum("-dm_coord_map", "Coordinate mapping for built-in mesh", "", DMPlexCoordMaps, (PetscEnum)map, (PetscEnum *)&map, &flg)); 5497be664eb1SMatthew G. Knepley if (flg) { 5498be664eb1SMatthew G. Knepley switch (map) { 5499be664eb1SMatthew G. Knepley case DM_COORD_MAP_NONE: 5500be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5501be664eb1SMatthew G. Knepley break; 5502be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHEAR: 5503be664eb1SMatthew G. Knepley mapFunc = coordMap_shear; 5504be664eb1SMatthew G. Knepley if (!Np) { 5505be664eb1SMatthew G. Knepley Np = cdim + 1; 5506be664eb1SMatthew G. Knepley params[0] = 0; 5507be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5508be664eb1SMatthew G. Knepley } 5509be664eb1SMatthew 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); 5510be664eb1SMatthew G. Knepley break; 5511be664eb1SMatthew G. Knepley case DM_COORD_MAP_FLARE: 5512be664eb1SMatthew G. Knepley mapFunc = coordMap_flare; 5513be664eb1SMatthew G. Knepley if (!Np) { 5514be664eb1SMatthew G. Knepley Np = cdim + 1; 5515be664eb1SMatthew G. Knepley params[0] = 0; 5516be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5517be664eb1SMatthew G. Knepley } 5518be664eb1SMatthew 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); 5519be664eb1SMatthew G. Knepley break; 5520be664eb1SMatthew G. Knepley case DM_COORD_MAP_ANNULUS: 5521be664eb1SMatthew G. Knepley mapFunc = coordMap_annulus; 5522be664eb1SMatthew G. Knepley if (!Np) { 5523be664eb1SMatthew G. Knepley Np = 2; 5524be664eb1SMatthew G. Knepley params[0] = 1.; 5525be664eb1SMatthew G. Knepley params[1] = 2.; 5526be664eb1SMatthew G. Knepley } 5527be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The annulus coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5528be664eb1SMatthew G. Knepley break; 5529be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHELL: 5530be664eb1SMatthew G. Knepley mapFunc = coordMap_shell; 5531be664eb1SMatthew G. Knepley if (!Np) { 5532be664eb1SMatthew G. Knepley Np = 2; 5533be664eb1SMatthew G. Knepley params[0] = 1.; 5534be664eb1SMatthew G. Knepley params[1] = 2.; 5535be664eb1SMatthew G. Knepley } 5536be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The spherical shell coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5537be664eb1SMatthew G. Knepley break; 5538530e699aSMatthew G. Knepley case DM_COORD_MAP_SINUSOID: 5539530e699aSMatthew G. Knepley mapFunc = coordMap_sinusoid; 5540530e699aSMatthew G. Knepley if (!Np) { 5541530e699aSMatthew G. Knepley Np = 3; 5542530e699aSMatthew G. Knepley params[0] = 1.; 5543530e699aSMatthew G. Knepley params[1] = 1.; 5544530e699aSMatthew G. Knepley params[2] = 1.; 5545530e699aSMatthew G. Knepley } 5546530e699aSMatthew G. Knepley PetscCheck(Np == 3, comm, PETSC_ERR_ARG_WRONG, "The sinusoidal coordinate map must have 3 parameters, not %" PetscInt_FMT, Np); 5547530e699aSMatthew G. Knepley break; 5548be664eb1SMatthew G. Knepley default: 5549be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5550be664eb1SMatthew G. Knepley } 5551be664eb1SMatthew G. Knepley } 5552be664eb1SMatthew G. Knepley if (Np) { 5553be664eb1SMatthew G. Knepley DM cdm; 5554be664eb1SMatthew G. Knepley PetscDS cds; 5555be664eb1SMatthew G. Knepley 5556be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5557be664eb1SMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 5558be664eb1SMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, Np, params)); 5559be664eb1SMatthew G. Knepley } 5560be664eb1SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, mapFunc)); 5561be664eb1SMatthew G. Knepley } 5562909dfd52SMatthew G. Knepley /* Handle ghost cells */ 55639566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 5564909dfd52SMatthew G. Knepley if (ghostCells) { 5565909dfd52SMatthew G. Knepley DM gdm; 5566909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 5567909dfd52SMatthew G. Knepley 5568909dfd52SMatthew G. Knepley lname[0] = '\0'; 55699566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 55709566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 557169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 5572909dfd52SMatthew G. Knepley } 55736913077dSMatthew G. Knepley /* Handle 1D order */ 5574adc21957SMatthew G. Knepley if (reorder != DM_REORDER_DEFAULT_FALSE && dim == 1) { 55756913077dSMatthew G. Knepley DM cdm, rdm; 55766913077dSMatthew G. Knepley PetscDS cds; 55776913077dSMatthew G. Knepley PetscObject obj; 55786913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 55796913077dSMatthew G. Knepley IS perm; 55806bc1bd01Sksagiyam PetscInt Nf; 55816913077dSMatthew G. Knepley PetscBool distributed; 55826913077dSMatthew G. Knepley 55839566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 55849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 55859566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 55869566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 55876913077dSMatthew G. Knepley if (Nf) { 55889566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 55899566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 55906913077dSMatthew G. Knepley } 55916bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 55929566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 55939566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 559469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 55959566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 55966913077dSMatthew G. Knepley } 55976913077dSMatthew G. Knepley } 55983cf6fe12SMatthew G. Knepley /* Handle */ 5599dd4c3f67SMatthew G. Knepley non_refine: 5600dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 560122d6dc08SStefano Zampini char *phases[16]; 560222d6dc08SStefano Zampini PetscInt Nphases = 16; 560322d6dc08SStefano Zampini PetscCall(PetscOptionsStringArray("-dm_plex_option_phases", "Option phase prefixes", "DMSetFromOptions", phases, &Nphases, &flg)); 5604d0609cedSBarry Smith PetscOptionsHeadEnd(); 560522d6dc08SStefano Zampini 560622d6dc08SStefano Zampini // Phases 560722d6dc08SStefano Zampini if (flg) { 5608530e699aSMatthew G. Knepley DM cdm; 5609530e699aSMatthew G. Knepley char *oldPrefix, *oldCoordPrefix; 5610530e699aSMatthew G. Knepley const char *tmp; 561122d6dc08SStefano Zampini 5612530e699aSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5613530e699aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &tmp)); 5614530e699aSMatthew G. Knepley PetscCall(PetscStrallocpy(tmp, &oldPrefix)); 5615530e699aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)cdm, &tmp)); 5616530e699aSMatthew G. Knepley PetscCall(PetscStrallocpy(tmp, &oldCoordPrefix)); 561722d6dc08SStefano Zampini for (PetscInt ph = 0; ph < Nphases; ++ph) { 561822d6dc08SStefano Zampini PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, phases[ph])); 5619530e699aSMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)cdm, phases[ph])); 562022d6dc08SStefano Zampini PetscCall(PetscInfo(dm, "Options phase %s for DM %s\n", phases[ph], dm->hdr.name)); 562122d6dc08SStefano Zampini PetscCall(DMSetFromOptions(dm)); 562222d6dc08SStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix)); 5623530e699aSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5624530e699aSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)cdm, oldCoordPrefix)); 562522d6dc08SStefano Zampini PetscCall(PetscFree(phases[ph])); 562622d6dc08SStefano Zampini } 5627530e699aSMatthew G. Knepley PetscCall(PetscFree(oldPrefix)); 5628530e699aSMatthew G. Knepley PetscCall(PetscFree(oldCoordPrefix)); 562922d6dc08SStefano Zampini } 56303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56310a6ba040SMatthew G. Knepley } 56320a6ba040SMatthew G. Knepley 5633d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) 5634d71ae5a4SJacob Faibussowitsch { 5635552f7358SJed Brown PetscFunctionBegin; 56369566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 56379566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 563857d50842SBarry Smith PetscCall(VecSetOperation(*vec, VECOP_VIEW, (PetscErrorCodeFn *)VecView_Plex)); 563957d50842SBarry Smith PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (PetscErrorCodeFn *)VecView_Plex_Native)); 564057d50842SBarry Smith PetscCall(VecSetOperation(*vec, VECOP_LOAD, (PetscErrorCodeFn *)VecLoad_Plex)); 564157d50842SBarry Smith PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (PetscErrorCodeFn *)VecLoad_Plex_Native)); 56423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5643552f7358SJed Brown } 5644552f7358SJed Brown 5645d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) 5646d71ae5a4SJacob Faibussowitsch { 5647552f7358SJed Brown PetscFunctionBegin; 56489566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 564957d50842SBarry Smith PetscCall(VecSetOperation(*vec, VECOP_VIEW, (PetscErrorCodeFn *)VecView_Plex_Local)); 565057d50842SBarry Smith PetscCall(VecSetOperation(*vec, VECOP_LOAD, (PetscErrorCodeFn *)VecLoad_Plex_Local)); 56513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5652552f7358SJed Brown } 5653552f7358SJed Brown 5654d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 5655d71ae5a4SJacob Faibussowitsch { 5656793f3fe5SMatthew G. Knepley PetscInt depth, d; 5657793f3fe5SMatthew G. Knepley 5658793f3fe5SMatthew G. Knepley PetscFunctionBegin; 56599566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 5660793f3fe5SMatthew G. Knepley if (depth == 1) { 56619566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 56629566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 56639566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 56649371c9d4SSatish Balay else { 56659371c9d4SSatish Balay *pStart = 0; 56669371c9d4SSatish Balay *pEnd = 0; 56679371c9d4SSatish Balay } 5668793f3fe5SMatthew G. Knepley } else { 56699566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 5670793f3fe5SMatthew G. Knepley } 56713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5672793f3fe5SMatthew G. Knepley } 5673793f3fe5SMatthew G. Knepley 5674d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 5675d71ae5a4SJacob Faibussowitsch { 5676502a2867SDave May PetscSF sf; 56776497c311SBarry Smith PetscMPIInt niranks, njranks; 56786497c311SBarry Smith PetscInt n; 56790a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 56800a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 5681502a2867SDave May 56822f356facSMatthew G. Knepley PetscFunctionBegin; 56839566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 56840a19bb7dSprj- if (!data->neighbors) { 56859566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 56869566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 56879566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 56889566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 56899566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 56909566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 56910a19bb7dSprj- n = njranks + niranks; 56929566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 56930a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 56949566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 56950a19bb7dSprj- } 56960a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 56970a19bb7dSprj- if (ranks) { 56980a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 56990a19bb7dSprj- else *ranks = NULL; 57000a19bb7dSprj- } 57013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5702502a2867SDave May } 5703502a2867SDave May 57041eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 57051eb70e55SToby Isaac 5706d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm) 5707d71ae5a4SJacob Faibussowitsch { 5708552f7358SJed Brown PetscFunctionBegin; 5709552f7358SJed Brown dm->ops->view = DMView_Plex; 57102c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 5711552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 571238221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 5713552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 57141bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 5715adc21957SMatthew G. Knepley dm->ops->createsectionpermutation = DMCreateSectionPermutation_Plex; 571666ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 5717552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 5718552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 5719184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 57200298fd71SBarry Smith dm->ops->createfieldis = NULL; 5721552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 572299acd26cSksagiyam dm->ops->createcellcoordinatedm = DMCreateCellCoordinateDM_Plex; 5723f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 57240a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 5725552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 5726bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 5727bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 5728b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 57291898fd5cSMatthew G. Knepley dm->ops->creategradientmatrix = DMCreateGradientMatrix_Plex; 57305a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 5731552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 57320a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 57330a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 5734b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 5735d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 57360298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 57370298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 57380298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 57390298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 5740552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 5741552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 57422adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 5743793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 5744552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 57450709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 57460709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 5747bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 57488c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 5749ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 57500709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 5751b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 57522a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 575328d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 57546c6a6b79SMatthew G. Knepley dm->ops->getlocalboundingbox = DMGetLocalBoundingBox_Coordinates; 5755907a3e9cSStefano Zampini dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_Plex; 5756907a3e9cSStefano Zampini dm->ops->createddscatters = DMCreateDomainDecompositionScatters_Plex; 57579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 57586c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 575901468941SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBounds_C", DMPlexInsertBounds_Plex)); 57609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 57619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 57629566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 57639566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 57646bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 57656bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 5766adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", DMReorderSectionGetDefault_Plex)); 5767adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", DMReorderSectionSetDefault_Plex)); 5768adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", DMReorderSectionGetType_Plex)); 5769adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", DMReorderSectionSetType_Plex)); 57709566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 5771c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 5772c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 5773d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", DMPlexGetUseCeed_Plex)); 5774d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", DMPlexSetUseCeed_Plex)); 57753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5776552f7358SJed Brown } 5777552f7358SJed Brown 5778d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 5779d71ae5a4SJacob Faibussowitsch { 578063a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 57811fca310dSJames Wright const PetscSF *face_sfs; 57821fca310dSJames Wright PetscInt num_face_sfs; 578363a16f15SMatthew G. Knepley 578463a16f15SMatthew G. Knepley PetscFunctionBegin; 578563a16f15SMatthew G. Knepley mesh->refct++; 578663a16f15SMatthew G. Knepley (*newdm)->data = mesh; 57871fca310dSJames Wright PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &face_sfs)); 57881fca310dSJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, num_face_sfs, (PetscSF *)face_sfs)); 57899566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 57909566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 57913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 579263a16f15SMatthew G. Knepley } 579363a16f15SMatthew G. Knepley 57948818961aSMatthew G Knepley /*MC 57950b4b7b1cSBarry Smith DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh (or grid), or CW Complex {cite}`cwcomplex`, 57960b4b7b1cSBarry Smith which can be expressed using a Hasse Diagram {cite}`hassediagram`. 579720f4b53cSBarry Smith In the local representation, `Vec`s contain all unknowns in the interior and shared boundary. This is 57980b4b7b1cSBarry Smith specified by a `PetscSection` object. Ownership in the global representation is determined by 5799a1cb98faSBarry Smith ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object. 58008818961aSMatthew G Knepley 5801e5893cccSMatthew G. Knepley Options Database Keys: 5802250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 5803250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 5804250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 5805250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 5806250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 5807250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 5808c3db174cSMatthew G. Knepley . -dm_localize <bool> - Whether to localize coordinates for periodic meshes 5809c3db174cSMatthew G. Knepley . -dm_sparse_localize <bool> - Whether to only localize cells on the periodic boundary 5810250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 5811ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 5812f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 5813f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 5814d5b43468SJose E. Roman . -dm_plex_max_projection_height - Maximum mesh point height used to project locally 5815f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 5816d02c7345SMatthew G. Knepley . -dm_plex_reorder_section - Use specialized blocking if available 5817aaa8cc7dSPierre Jolivet . -dm_plex_check_all - Perform all checks below 5818f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 5819f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 5820f12cf164SMatthew 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 5821f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 5822f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 5823e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 58245962854dSMatthew G. Knepley . -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 58255962854dSMatthew G. Knepley - -dm_plex_print_fvm <num> - View FVM assembly information, such as flux updates 5826e5893cccSMatthew G. Knepley 58278818961aSMatthew G Knepley Level: intermediate 58288818961aSMatthew G Knepley 58291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection` 58308818961aSMatthew G Knepley M*/ 58318818961aSMatthew G Knepley 5832d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 5833d71ae5a4SJacob Faibussowitsch { 5834552f7358SJed Brown DM_Plex *mesh; 5835412e9a14SMatthew G. Knepley PetscInt unit; 5836552f7358SJed Brown 5837552f7358SJed Brown PetscFunctionBegin; 5838f39ec787SMatthew G. Knepley PetscCall(PetscCitationsRegister(PlexCitation, &Plexcite)); 5839552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58404dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mesh)); 5841adc21957SMatthew G. Knepley dm->reorderSection = DM_REORDER_DEFAULT_NOTSET; 5842552f7358SJed Brown dm->data = mesh; 5843552f7358SJed Brown 5844552f7358SJed Brown mesh->refct = 1; 58459566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 58469566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 5847552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 5848552f7358SJed Brown mesh->refinementLimit = -1.0; 5849e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 5850adc21957SMatthew G. Knepley mesh->reorderDefault = DM_REORDER_DEFAULT_NOTSET; 58511d1f2f2aSksagiyam mesh->distributionName = NULL; 58527d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 58537d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 58545e2c5519SMatthew G. Knepley mesh->interpolatePreferTensor = PETSC_TRUE; 5855552f7358SJed Brown 58569566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 58572e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 5858d9deefdfSMatthew G. Knepley 58598865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 5860552f7358SJed Brown 5861df0420ecSMatthew G. Knepley mesh->depthState = -1; 5862ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 58636113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 5864c29ce622SStefano Zampini mesh->nonempty_comm = MPI_COMM_SELF; 5865552f7358SJed Brown 58669566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 58673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5868552f7358SJed Brown } 5869552f7358SJed Brown 5870552f7358SJed Brown /*@ 5871a1cb98faSBarry Smith DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 5872552f7358SJed Brown 5873d083f849SBarry Smith Collective 5874552f7358SJed Brown 5875552f7358SJed Brown Input Parameter: 5876a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object 5877552f7358SJed Brown 5878552f7358SJed Brown Output Parameter: 5879a1cb98faSBarry Smith . mesh - The `DMPLEX` object 5880552f7358SJed Brown 5881552f7358SJed Brown Level: beginner 5882552f7358SJed Brown 588342747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMCreate()`, `DMSetType()` 5884552f7358SJed Brown @*/ 5885d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 5886d71ae5a4SJacob Faibussowitsch { 5887552f7358SJed Brown PetscFunctionBegin; 58884f572ea9SToby Isaac PetscAssertPointer(mesh, 2); 58899566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 58909566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 58913ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5892552f7358SJed Brown } 5893552f7358SJed Brown 5894b09969d6SVaclav Hapla /*@C 5895e1b2f275SBarry Smith DMPlexBuildFromCellListParallel - Build a distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) where all cells have the same celltype 5896a1cb98faSBarry Smith 589720f4b53cSBarry Smith Collective; No Fortran Support 5898b09969d6SVaclav Hapla 5899b09969d6SVaclav Hapla Input Parameters: 5900a1cb98faSBarry Smith + dm - The `DM` 5901b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 5902a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 5903a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DETERMINE` 5904b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 5905e1b2f275SBarry Smith - cells - An array of $ numCells \times numCorners$ numbers, the global vertex numbers for each cell 5906b09969d6SVaclav Hapla 5907be8c289dSNicolas Barral Output Parameters: 5908a1cb98faSBarry Smith + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 5909be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 5910b09969d6SVaclav Hapla 5911b09969d6SVaclav Hapla Level: advanced 5912b09969d6SVaclav Hapla 5913a1cb98faSBarry Smith Notes: 5914a1cb98faSBarry Smith Two triangles sharing a face 5915a1cb98faSBarry Smith .vb 5916a1cb98faSBarry Smith 5917a1cb98faSBarry Smith 2 5918a1cb98faSBarry Smith / | \ 5919a1cb98faSBarry Smith / | \ 5920a1cb98faSBarry Smith / | \ 5921a1cb98faSBarry Smith 0 0 | 1 3 5922a1cb98faSBarry Smith \ | / 5923a1cb98faSBarry Smith \ | / 5924a1cb98faSBarry Smith \ | / 5925a1cb98faSBarry Smith 1 5926a1cb98faSBarry Smith .ve 5927a1cb98faSBarry Smith would have input 5928a1cb98faSBarry Smith .vb 5929a1cb98faSBarry Smith numCells = 2, numVertices = 4 5930a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 5931a1cb98faSBarry Smith .ve 5932a1cb98faSBarry Smith which would result in the `DMPLEX` 5933a1cb98faSBarry Smith .vb 5934a1cb98faSBarry Smith 5935a1cb98faSBarry Smith 4 5936a1cb98faSBarry Smith / | \ 5937a1cb98faSBarry Smith / | \ 5938a1cb98faSBarry Smith / | \ 5939a1cb98faSBarry Smith 2 0 | 1 5 5940a1cb98faSBarry Smith \ | / 5941a1cb98faSBarry Smith \ | / 5942a1cb98faSBarry Smith \ | / 5943a1cb98faSBarry Smith 3 5944a1cb98faSBarry Smith .ve 5945a1cb98faSBarry Smith 5946e1b2f275SBarry Smith Vertices are implicitly numbered consecutively $0, \ldots, \mathrm{NVertices}$. 5947e1b2f275SBarry Smith 5948e1b2f275SBarry Smith Each process owns a chunk of `numVertices` consecutive vertices. 5949e1b2f275SBarry Smith 5950e1b2f275SBarry Smith If `numVertices` is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using `PetscLayout`. 5951e1b2f275SBarry Smith 5952e1b2f275SBarry Smith If `NVertices` is `PETSC_DETERMINE` and `numVertices` is `PETSC_DECIDE`, `NVertices` is computed by PETSc as the maximum vertex index in $ cells + 1 $. 5953e1b2f275SBarry Smith 5954e1b2f275SBarry Smith If only `NVertices` is `PETSC_DETERMINE`, it is computed as the sum of `numVertices` over all processes. 5955a1cb98faSBarry Smith 5956a1cb98faSBarry Smith The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 5957a1cb98faSBarry Smith 59581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 5959a1cb98faSBarry Smith `PetscSF` 5960b09969d6SVaclav Hapla @*/ 5961ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[]) 5962d71ae5a4SJacob Faibussowitsch { 59632464107aSksagiyam PetscSF sfPoint; 59642464107aSksagiyam PetscLayout layout; 596582fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 5966a47d0d45SMatthew G. Knepley 5967a47d0d45SMatthew G. Knepley PetscFunctionBegin; 596825b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 59699566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 597025b6865aSVaclav Hapla /* Get/check global number of vertices */ 597125b6865aSVaclav Hapla { 597225b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 597325b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 597425b6865aSVaclav Hapla 597525b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 59761690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 59779371c9d4SSatish Balay for (i = 0; i < len; i++) 59789371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 597925b6865aSVaclav Hapla ++NVerticesInCells; 5980462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 598125b6865aSVaclav Hapla 598225b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 59839371c9d4SSatish Balay else 59849371c9d4SSatish 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); 598525b6865aSVaclav Hapla } 59869079aca8SVaclav Hapla /* Count locally unique vertices */ 59879079aca8SVaclav Hapla { 59889079aca8SVaclav Hapla PetscHSetI vhash; 59899079aca8SVaclav Hapla PetscInt off = 0; 59909079aca8SVaclav Hapla 59919566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 5992a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 599348a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 5994a47d0d45SMatthew G. Knepley } 59959566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 59969566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 5997ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 59989566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 59999566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 600063a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 6001a47d0d45SMatthew G. Knepley } 60029566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 6003a47d0d45SMatthew G. Knepley /* Create cones */ 60049566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 60059566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 60069566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 60079566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 6008a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 6009a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 6010a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 6011a47d0d45SMatthew G. Knepley PetscInt lv; 6012a47d0d45SMatthew G. Knepley 60139079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 60149079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 60159566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 601663a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 6017961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 6018a47d0d45SMatthew G. Knepley } 6019a47d0d45SMatthew G. Knepley } 60202464107aSksagiyam /* Build point sf */ 60219566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 60229566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 60239566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 60249566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 60259566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 60269566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 60279566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 60289566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 60292464107aSksagiyam if (dm->sf) { 60302464107aSksagiyam const char *prefix; 60312464107aSksagiyam 60329566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 60339566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 60342464107aSksagiyam } 60359566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 60369566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 6037f4f49eeaSPierre Jolivet if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 6038a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 60399566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 60409566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 60419566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 60423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6043a47d0d45SMatthew G. Knepley } 6044a47d0d45SMatthew G. Knepley 6045b0fe842aSMatthew G. Knepley /*@C 6046b0fe842aSMatthew G. Knepley DMPlexBuildFromCellSectionParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) allowing multiple celltypes 6047b0fe842aSMatthew G. Knepley 6048b0fe842aSMatthew G. Knepley Collective; No Fortran Support 6049b0fe842aSMatthew G. Knepley 6050b0fe842aSMatthew G. Knepley Input Parameters: 6051b0fe842aSMatthew G. Knepley + dm - The `DM` 6052b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 6053b0fe842aSMatthew G. Knepley . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 6054b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DETERMINE` 6055b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 6056b0fe842aSMatthew G. Knepley - cells - An array of the global vertex numbers for each cell 6057b0fe842aSMatthew G. Knepley 6058b0fe842aSMatthew G. Knepley Output Parameters: 6059b0fe842aSMatthew G. Knepley + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 6060b0fe842aSMatthew G. Knepley - verticesAdjSaved - (Optional) vertex adjacency array 6061b0fe842aSMatthew G. Knepley 6062b0fe842aSMatthew G. Knepley Level: advanced 6063b0fe842aSMatthew G. Knepley 6064b0fe842aSMatthew G. Knepley Notes: 6065b0fe842aSMatthew G. Knepley A triangle and quadrilateral sharing a face 6066b0fe842aSMatthew G. Knepley .vb 6067b0fe842aSMatthew G. Knepley 2----------3 6068b0fe842aSMatthew G. Knepley / | | 6069b0fe842aSMatthew G. Knepley / | | 6070b0fe842aSMatthew G. Knepley / | | 6071b0fe842aSMatthew G. Knepley 0 0 | 1 | 6072b0fe842aSMatthew G. Knepley \ | | 6073b0fe842aSMatthew G. Knepley \ | | 6074b0fe842aSMatthew G. Knepley \ | | 6075b0fe842aSMatthew G. Knepley 1----------4 6076b0fe842aSMatthew G. Knepley .ve 6077b0fe842aSMatthew G. Knepley would have input 6078b0fe842aSMatthew G. Knepley .vb 6079b0fe842aSMatthew G. Knepley numCells = 2, numVertices = 5 6080b0fe842aSMatthew G. Knepley cells = [0 1 2 1 4 3 2] 6081b0fe842aSMatthew G. Knepley .ve 6082b0fe842aSMatthew G. Knepley which would result in the `DMPLEX` 6083b0fe842aSMatthew G. Knepley .vb 6084b0fe842aSMatthew G. Knepley 4----------5 6085b0fe842aSMatthew G. Knepley / | | 6086b0fe842aSMatthew G. Knepley / | | 6087b0fe842aSMatthew G. Knepley / | | 6088b0fe842aSMatthew G. Knepley 2 0 | 1 | 6089b0fe842aSMatthew G. Knepley \ | | 6090b0fe842aSMatthew G. Knepley \ | | 6091b0fe842aSMatthew G. Knepley \ | | 6092b0fe842aSMatthew G. Knepley 3----------6 6093b0fe842aSMatthew G. Knepley .ve 6094b0fe842aSMatthew G. Knepley 6095b0fe842aSMatthew G. Knepley Vertices are implicitly numbered consecutively 0,...,NVertices. 6096b0fe842aSMatthew G. Knepley Each rank owns a chunk of numVertices consecutive vertices. 6097b0fe842aSMatthew G. Knepley If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 6098b0fe842aSMatthew 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. 6099b0fe842aSMatthew G. Knepley If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 6100b0fe842aSMatthew G. Knepley 6101b0fe842aSMatthew G. Knepley The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 6102b0fe842aSMatthew G. Knepley 6103b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexCreateFromCellSectionParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 6104b0fe842aSMatthew G. Knepley `PetscSF` 6105b0fe842aSMatthew G. Knepley @*/ 6106ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellSectionParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[]) 6107b0fe842aSMatthew G. Knepley { 6108b0fe842aSMatthew G. Knepley PetscSF sfPoint; 6109b0fe842aSMatthew G. Knepley PetscLayout layout; 6110b0fe842aSMatthew G. Knepley PetscInt numVerticesAdj, *verticesAdj, *cones, cStart, cEnd, len; 6111b0fe842aSMatthew G. Knepley 6112b0fe842aSMatthew G. Knepley PetscFunctionBegin; 6113b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, NVertices, 4); 6114b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 6115b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetChart(cellSection, &cStart, &cEnd)); 6116b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(cellSection, &len)); 6117b0fe842aSMatthew 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); 6118b0fe842aSMatthew G. Knepley /* Get/check global number of vertices */ 6119b0fe842aSMatthew G. Knepley { 6120b0fe842aSMatthew G. Knepley PetscInt NVerticesInCells; 6121b0fe842aSMatthew G. Knepley 6122b0fe842aSMatthew G. Knepley /* NVerticesInCells = max(cells) + 1 */ 6123b0fe842aSMatthew G. Knepley NVerticesInCells = PETSC_MIN_INT; 6124b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) 6125b0fe842aSMatthew G. Knepley if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 6126b0fe842aSMatthew G. Knepley ++NVerticesInCells; 6127b0fe842aSMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 6128b0fe842aSMatthew G. Knepley 6129b0fe842aSMatthew G. Knepley if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 6130b0fe842aSMatthew G. Knepley else 6131b0fe842aSMatthew 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); 6132b0fe842aSMatthew G. Knepley } 6133b0fe842aSMatthew G. Knepley /* Count locally unique vertices */ 6134b0fe842aSMatthew G. Knepley { 6135b0fe842aSMatthew G. Knepley PetscHSetI vhash; 6136b0fe842aSMatthew G. Knepley PetscInt off = 0; 6137b0fe842aSMatthew G. Knepley 6138b0fe842aSMatthew G. Knepley PetscCall(PetscHSetICreate(&vhash)); 6139b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) PetscCall(PetscHSetIAdd(vhash, cells[i])); 6140b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 6141b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 6142b0fe842aSMatthew G. Knepley else verticesAdj = *verticesAdjSaved; 6143b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 6144b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIDestroy(&vhash)); 6145b0fe842aSMatthew 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); 6146b0fe842aSMatthew G. Knepley } 6147b0fe842aSMatthew G. Knepley PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 6148b0fe842aSMatthew G. Knepley /* Create cones */ 6149b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 6150b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 6151b0fe842aSMatthew G. Knepley PetscInt dof; 6152b0fe842aSMatthew G. Knepley 6153b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 6154b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetConeSize(dm, c, dof)); 6155b0fe842aSMatthew G. Knepley } 6156b0fe842aSMatthew G. Knepley PetscCall(DMSetUp(dm)); 6157b0fe842aSMatthew G. Knepley PetscCall(DMPlexGetCones(dm, &cones)); 6158b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 6159b0fe842aSMatthew G. Knepley PetscInt dof, off; 6160b0fe842aSMatthew G. Knepley 6161b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 6162b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cellSection, c, &off)); 6163b0fe842aSMatthew G. Knepley for (PetscInt p = off; p < off + dof; ++p) { 6164b0fe842aSMatthew G. Knepley const PetscInt gv = cells[p]; 6165b0fe842aSMatthew G. Knepley PetscInt lv; 6166b0fe842aSMatthew G. Knepley 6167b0fe842aSMatthew G. Knepley /* Positions within verticesAdj form 0-based local vertex numbering; 6168b0fe842aSMatthew G. Knepley we need to shift it by numCells to get correct DAG points (cells go first) */ 6169b0fe842aSMatthew G. Knepley PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 6170b0fe842aSMatthew G. Knepley PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 6171b0fe842aSMatthew G. Knepley cones[p] = lv + numCells; 6172b0fe842aSMatthew G. Knepley } 6173b0fe842aSMatthew G. Knepley } 6174b0fe842aSMatthew G. Knepley /* Build point sf */ 6175b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 6176b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetSize(layout, NVertices)); 6177b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 6178b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetBlockSize(layout, 1)); 6179b0fe842aSMatthew G. Knepley PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 6180b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutDestroy(&layout)); 6181b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 6182b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 6183b0fe842aSMatthew G. Knepley if (dm->sf) { 6184b0fe842aSMatthew G. Knepley const char *prefix; 6185b0fe842aSMatthew G. Knepley 6186b0fe842aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 6187b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 6188b0fe842aSMatthew G. Knepley } 6189b0fe842aSMatthew G. Knepley PetscCall(DMSetPointSF(dm, sfPoint)); 6190b0fe842aSMatthew G. Knepley PetscCall(PetscSFDestroy(&sfPoint)); 6191b0fe842aSMatthew G. Knepley if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 6192b0fe842aSMatthew G. Knepley /* Fill in the rest of the topology structure */ 6193b0fe842aSMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 6194b0fe842aSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 6195b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 6196b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 6197b0fe842aSMatthew G. Knepley } 6198b0fe842aSMatthew G. Knepley 6199cc4c1da9SBarry Smith /*@ 6200a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 6201a1cb98faSBarry Smith 620220f4b53cSBarry Smith Collective; No Fortran Support 6203b09969d6SVaclav Hapla 6204b09969d6SVaclav Hapla Input Parameters: 6205a1cb98faSBarry Smith + dm - The `DM` 6206b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6207a1cb98faSBarry Smith . sfVert - `PetscSF` describing complete vertex ownership 6208b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6209b09969d6SVaclav Hapla 6210b09969d6SVaclav Hapla Level: advanced 6211b09969d6SVaclav Hapla 62121cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 6213b09969d6SVaclav Hapla @*/ 6214d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 6215d71ae5a4SJacob Faibussowitsch { 6216a47d0d45SMatthew G. Knepley PetscSection coordSection; 6217a47d0d45SMatthew G. Knepley Vec coordinates; 6218a47d0d45SMatthew G. Knepley PetscScalar *coords; 62191edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 6220835f2295SStefano Zampini PetscMPIInt spaceDimi; 6221a47d0d45SMatthew G. Knepley 6222a47d0d45SMatthew G. Knepley PetscFunctionBegin; 62239566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 62249566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 62251dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 62269566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 62279566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 62281dca8a05SBarry 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); 62299566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 62309566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 62319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 62329566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 62331edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 62349566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 62359566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 6236a47d0d45SMatthew G. Knepley } 62379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 62389566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 62399566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 62409566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 62419566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 62429566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 62439566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 62449566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6245a47d0d45SMatthew G. Knepley { 6246a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 6247a47d0d45SMatthew G. Knepley 6248a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 6249835f2295SStefano Zampini PetscCall(PetscMPIIntCast(spaceDim, &spaceDimi)); 6250835f2295SStefano Zampini PetscCallMPI(MPI_Type_contiguous(spaceDimi, MPIU_SCALAR, &coordtype)); 62519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 625221016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 625321016a8bSBarry Smith { 625421016a8bSBarry Smith PetscScalar *svertexCoords; 625521016a8bSBarry Smith PetscInt i; 62569566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 62573612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 62589566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 62599566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 62609566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 626121016a8bSBarry Smith } 626221016a8bSBarry Smith #else 62639566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 62649566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 626521016a8bSBarry Smith #endif 62669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 6267a47d0d45SMatthew G. Knepley } 62689566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 62699566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 62709566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 62719566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 62723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6273a47d0d45SMatthew G. Knepley } 6274a47d0d45SMatthew G. Knepley 6275c3edce3dSSatish Balay /*@ 6276b0fe842aSMatthew 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 6277a1cb98faSBarry Smith 6278a1cb98faSBarry Smith Collective 6279a47d0d45SMatthew G. Knepley 6280a47d0d45SMatthew G. Knepley Input Parameters: 6281a47d0d45SMatthew G. Knepley + comm - The communicator 6282a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 6283a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 6284a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 6285a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DECIDE` 6286a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 6287a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6288a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 6289a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 6290a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6291a47d0d45SMatthew G. Knepley 6292d8d19677SJose E. Roman Output Parameters: 6293a1cb98faSBarry Smith + dm - The `DM` 6294a1cb98faSBarry Smith . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 629560225df5SJacob Faibussowitsch - verticesAdj - (Optional) vertex adjacency array 6296a47d0d45SMatthew G. Knepley 6297b09969d6SVaclav Hapla Level: intermediate 6298a47d0d45SMatthew G. Knepley 6299a1cb98faSBarry Smith Notes: 6300a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 6301a1cb98faSBarry Smith `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 6302a1cb98faSBarry Smith 6303a1cb98faSBarry Smith See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters. 6304a1cb98faSBarry Smith 6305a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 6306a1cb98faSBarry Smith 63071cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 6308a47d0d45SMatthew G. Knepley @*/ 6309ce78bad3SBarry 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) 6310d71ae5a4SJacob Faibussowitsch { 6311a47d0d45SMatthew G. Knepley PetscSF sfVert; 6312a47d0d45SMatthew G. Knepley 6313a47d0d45SMatthew G. Knepley PetscFunctionBegin; 63149566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 63159566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 6316a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 6317064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 63189566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 63199566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 6320a47d0d45SMatthew G. Knepley if (interpolate) { 63215fd9971aSMatthew G. Knepley DM idm; 6322a47d0d45SMatthew G. Knepley 63239566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 63249566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 6325a47d0d45SMatthew G. Knepley *dm = idm; 6326a47d0d45SMatthew G. Knepley } 63279566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 632818d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 63299566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 63303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6331a47d0d45SMatthew G. Knepley } 6332a47d0d45SMatthew G. Knepley 6333cc4c1da9SBarry Smith /*@ 6334b0fe842aSMatthew G. Knepley DMPlexCreateFromCellSectionParallel - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) and supports multiple celltypes 6335b0fe842aSMatthew G. Knepley 6336b0fe842aSMatthew G. Knepley Collective 6337b0fe842aSMatthew G. Knepley 6338b0fe842aSMatthew G. Knepley Input Parameters: 6339b0fe842aSMatthew G. Knepley + comm - The communicator 6340b0fe842aSMatthew G. Knepley . dim - The topological dimension of the mesh 6341b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 6342b0fe842aSMatthew G. Knepley . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 6343b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DECIDE` 6344b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 6345b0fe842aSMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6346b0fe842aSMatthew G. Knepley . cells - An array of the global vertex numbers for each cell 6347b0fe842aSMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 6348b0fe842aSMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6349b0fe842aSMatthew G. Knepley 6350b0fe842aSMatthew G. Knepley Output Parameters: 6351b0fe842aSMatthew G. Knepley + dm - The `DM` 6352b0fe842aSMatthew G. Knepley . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 6353b0fe842aSMatthew G. Knepley - verticesAdj - (Optional) vertex adjacency array 6354b0fe842aSMatthew G. Knepley 6355b0fe842aSMatthew G. Knepley Level: intermediate 6356b0fe842aSMatthew G. Knepley 6357b0fe842aSMatthew G. Knepley Notes: 6358b0fe842aSMatthew G. Knepley This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 6359b0fe842aSMatthew G. Knepley `DMPlexBuildFromCellSectionParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 6360b0fe842aSMatthew G. Knepley 6361b0fe842aSMatthew G. Knepley See `DMPlexBuildFromCellSectionParallel()` for an example and details about the topology-related parameters. 6362b0fe842aSMatthew G. Knepley 6363b0fe842aSMatthew G. Knepley See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 6364b0fe842aSMatthew G. Knepley 6365b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 6366b0fe842aSMatthew G. Knepley @*/ 6367ce78bad3SBarry 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) 6368b0fe842aSMatthew G. Knepley { 6369b0fe842aSMatthew G. Knepley PetscSF sfVert; 6370b0fe842aSMatthew G. Knepley 6371b0fe842aSMatthew G. Knepley PetscFunctionBegin; 6372b0fe842aSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 6373b0fe842aSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 6374b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 6375b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 6376b0fe842aSMatthew G. Knepley PetscCall(DMSetDimension(*dm, dim)); 6377b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildFromCellSectionParallel(*dm, numCells, numVertices, NVertices, cellSection, cells, &sfVert, verticesAdj)); 6378b0fe842aSMatthew G. Knepley if (interpolate) { 6379b0fe842aSMatthew G. Knepley DM idm; 6380b0fe842aSMatthew G. Knepley 6381b0fe842aSMatthew G. Knepley PetscCall(DMPlexInterpolate(*dm, &idm)); 6382b0fe842aSMatthew G. Knepley PetscCall(DMDestroy(dm)); 6383b0fe842aSMatthew G. Knepley *dm = idm; 6384b0fe842aSMatthew G. Knepley } 6385b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 6386b0fe842aSMatthew G. Knepley if (vertexSF) *vertexSF = sfVert; 6387b0fe842aSMatthew G. Knepley else PetscCall(PetscSFDestroy(&sfVert)); 6388b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 6389b0fe842aSMatthew G. Knepley } 6390b0fe842aSMatthew G. Knepley 6391b0fe842aSMatthew G. Knepley /*@ 6392a1cb98faSBarry Smith DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) 6393a1cb98faSBarry Smith 639420f4b53cSBarry Smith Collective; No Fortran Support 63959298eaa6SMatthew G Knepley 63969298eaa6SMatthew G Knepley Input Parameters: 6397a1cb98faSBarry Smith + dm - The `DM` 6398b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 6399a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE` 64009298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 6401a3b724e8SBarry Smith - cells - An array of `numCells` x `numCorners` numbers, the global vertex numbers for each cell 64029298eaa6SMatthew G Knepley 6403b09969d6SVaclav Hapla Level: advanced 64049298eaa6SMatthew G Knepley 6405b09969d6SVaclav Hapla Notes: 6406b09969d6SVaclav Hapla Two triangles sharing a face 6407a1cb98faSBarry Smith .vb 64089298eaa6SMatthew G Knepley 6409a1cb98faSBarry Smith 2 6410a1cb98faSBarry Smith / | \ 6411a1cb98faSBarry Smith / | \ 6412a1cb98faSBarry Smith / | \ 6413a1cb98faSBarry Smith 0 0 | 1 3 6414a1cb98faSBarry Smith \ | / 6415a1cb98faSBarry Smith \ | / 6416a1cb98faSBarry Smith \ | / 6417a1cb98faSBarry Smith 1 6418a1cb98faSBarry Smith .ve 6419a1cb98faSBarry Smith would have input 6420a1cb98faSBarry Smith .vb 6421a1cb98faSBarry Smith numCells = 2, numVertices = 4 6422a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 6423a1cb98faSBarry Smith .ve 6424a1cb98faSBarry Smith which would result in the `DMPLEX` 6425a1cb98faSBarry Smith .vb 6426a1cb98faSBarry Smith 6427a1cb98faSBarry Smith 4 6428a1cb98faSBarry Smith / | \ 6429a1cb98faSBarry Smith / | \ 6430a1cb98faSBarry Smith / | \ 6431a1cb98faSBarry Smith 2 0 | 1 5 6432a1cb98faSBarry Smith \ | / 6433a1cb98faSBarry Smith \ | / 6434a1cb98faSBarry Smith \ | / 6435a1cb98faSBarry Smith 3 6436a1cb98faSBarry Smith .ve 6437a1cb98faSBarry Smith 6438a1cb98faSBarry Smith If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1. 643925b6865aSVaclav Hapla 64401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 6441b09969d6SVaclav Hapla @*/ 6442d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 6443d71ae5a4SJacob Faibussowitsch { 6444961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 6445b09969d6SVaclav Hapla 6446b09969d6SVaclav Hapla PetscFunctionBegin; 64479566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 64489566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 644925b6865aSVaclav Hapla /* Get/check global number of vertices */ 645025b6865aSVaclav Hapla { 645125b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 645225b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 645325b6865aSVaclav Hapla 645425b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 64551690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 64569371c9d4SSatish Balay for (i = 0; i < len; i++) 64579371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 645825b6865aSVaclav Hapla ++NVerticesInCells; 645925b6865aSVaclav Hapla 646025b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 64619371c9d4SSatish Balay else 64629371c9d4SSatish 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); 646325b6865aSVaclav Hapla } 64649566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 646548a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 64669566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 64679566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 6468b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 6469ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 6470b09969d6SVaclav Hapla } 64719566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 64729566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 64739566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 64743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6475b09969d6SVaclav Hapla } 6476b09969d6SVaclav Hapla 6477cc4c1da9SBarry Smith /*@ 6478a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 6479a1cb98faSBarry Smith 6480cc4c1da9SBarry Smith Collective 6481b09969d6SVaclav Hapla 6482b09969d6SVaclav Hapla Input Parameters: 6483a1cb98faSBarry Smith + dm - The `DM` 6484b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6485b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6486b09969d6SVaclav Hapla 6487b09969d6SVaclav Hapla Level: advanced 6488b09969d6SVaclav Hapla 64891cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 6490b09969d6SVaclav Hapla @*/ 6491d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 6492d71ae5a4SJacob Faibussowitsch { 6493b09969d6SVaclav Hapla PetscSection coordSection; 6494b09969d6SVaclav Hapla Vec coordinates; 6495b09969d6SVaclav Hapla DM cdm; 6496b09969d6SVaclav Hapla PetscScalar *coords; 64971edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 6498b09969d6SVaclav Hapla 6499b09969d6SVaclav Hapla PetscFunctionBegin; 65009566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 65019566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 65021dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 65039566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 65049566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 65059566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 65069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 65079566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 65081edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 65099566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 65109566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 6511b09969d6SVaclav Hapla } 65129566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6513b09969d6SVaclav Hapla 65149566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 65159566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 65169566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 65179566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 65189566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 65191edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 6520ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 6521b09969d6SVaclav Hapla } 65229566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 65239566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 65249566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 65259566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 65263ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6527b09969d6SVaclav Hapla } 6528b09969d6SVaclav Hapla 6529b09969d6SVaclav Hapla /*@ 6530a1cb98faSBarry Smith DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 65313df08285SMatthew G. Knepley 6532a1cb98faSBarry Smith Collective 6533b09969d6SVaclav Hapla 6534b09969d6SVaclav Hapla Input Parameters: 6535b09969d6SVaclav Hapla + comm - The communicator 6536b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 65373df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 6538a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0 65393df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 6540b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6541ce78bad3SBarry Smith . cells - An array of $ numCells \times numCorners$ numbers, the vertices for each cell, only on process 0 6542b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6543ce78bad3SBarry Smith - vertexCoords - An array of $ numVertices \times spaceDim$ numbers, the coordinates of each vertex, only on process 0 6544b09969d6SVaclav Hapla 6545b09969d6SVaclav Hapla Output Parameter: 6546a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0 654725b6865aSVaclav Hapla 6548b09969d6SVaclav Hapla Level: intermediate 6549b09969d6SVaclav Hapla 6550a1cb98faSBarry Smith Notes: 6551a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`, 6552a1cb98faSBarry Smith `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()` 6553a1cb98faSBarry Smith 6554a1cb98faSBarry Smith See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters. 6555a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters. 6556a1cb98faSBarry Smith See `DMPlexCreateFromCellListParallelPetsc()` for parallel input 6557a1cb98faSBarry Smith 65581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 65599298eaa6SMatthew G Knepley @*/ 6560d71ae5a4SJacob 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) 6561d71ae5a4SJacob Faibussowitsch { 65623df08285SMatthew G. Knepley PetscMPIInt rank; 65639298eaa6SMatthew G Knepley 65649298eaa6SMatthew G Knepley PetscFunctionBegin; 656528b400f6SJacob 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."); 65669566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 65679566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 65689566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 65699566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 6570c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 65719566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 65729298eaa6SMatthew G Knepley if (interpolate) { 65735fd9971aSMatthew G. Knepley DM idm; 65749298eaa6SMatthew G Knepley 65759566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 65769566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 65779298eaa6SMatthew G Knepley *dm = idm; 65789298eaa6SMatthew G Knepley } 6579c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 65809566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 65813ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 65829298eaa6SMatthew G Knepley } 65839298eaa6SMatthew G Knepley 6584939f6067SMatthew G. Knepley /*@ 658520f4b53cSBarry Smith DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a `DM` 6586939f6067SMatthew G. Knepley 6587939f6067SMatthew G. Knepley Input Parameters: 658820f4b53cSBarry Smith + dm - The empty `DM` object, usually from `DMCreate()` and `DMSetDimension()` 6589939f6067SMatthew G. Knepley . depth - The depth of the DAG 6590ce78bad3SBarry Smith . numPoints - Array of size $ depth + 1 $ containing the number of points at each `depth` 6591939f6067SMatthew G. Knepley . coneSize - The cone size of each point 6592939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 6593939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 6594ce78bad3SBarry Smith - vertexCoords - An array of $ numPoints[0] \times spacedim $ numbers representing the coordinates of each vertex, with `spacedim` the value set via `DMSetCoordinateDim()` 6595939f6067SMatthew G. Knepley 6596939f6067SMatthew G. Knepley Output Parameter: 659720f4b53cSBarry Smith . dm - The `DM` 659820f4b53cSBarry Smith 659920f4b53cSBarry Smith Level: advanced 6600939f6067SMatthew G. Knepley 6601a1cb98faSBarry Smith Note: 6602a1cb98faSBarry Smith Two triangles sharing a face would have input 6603a1cb98faSBarry Smith .vb 6604a1cb98faSBarry Smith depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 6605a1cb98faSBarry Smith cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 6606a1cb98faSBarry Smith vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 6607a1cb98faSBarry Smith .ve 6608939f6067SMatthew G. Knepley which would result in the DMPlex 6609a1cb98faSBarry Smith .vb 6610a1cb98faSBarry Smith 4 6611a1cb98faSBarry Smith / | \ 6612a1cb98faSBarry Smith / | \ 6613a1cb98faSBarry Smith / | \ 6614a1cb98faSBarry Smith 2 0 | 1 5 6615a1cb98faSBarry Smith \ | / 6616a1cb98faSBarry Smith \ | / 6617a1cb98faSBarry Smith \ | / 6618a1cb98faSBarry Smith 3 6619a1cb98faSBarry Smith .ve 6620a1cb98faSBarry Smith Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()` 6621939f6067SMatthew G. Knepley 6622ce78bad3SBarry Smith Developer Note: 6623ce78bad3SBarry Smith This does not create anything so should not have create in the name. 6624ce78bad3SBarry Smith 66251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 6626939f6067SMatthew G. Knepley @*/ 6627d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 6628d71ae5a4SJacob Faibussowitsch { 66299298eaa6SMatthew G Knepley Vec coordinates; 66309298eaa6SMatthew G Knepley PetscSection coordSection; 66319298eaa6SMatthew G Knepley PetscScalar *coords; 6632811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 66339298eaa6SMatthew G Knepley 66349298eaa6SMatthew G Knepley PetscFunctionBegin; 66359566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 66369566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 663763a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 66389298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 66399566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 66409298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 66419566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 6642ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 664397e052ccSToby Isaac } 66441dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 66459566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 66469298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 66479566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 66489566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 66499298eaa6SMatthew G Knepley } 66509566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 66519566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 66529298eaa6SMatthew G Knepley /* Build coordinates */ 66539566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 66549566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 66559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 66569566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 66579298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 66589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 66599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 66609298eaa6SMatthew G Knepley } 66619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 66629566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 66639566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 66649566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 66659566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 666658b7e2c1SStefano Zampini PetscCall(VecSetBlockSize(coordinates, PetscMax(dimEmbed, 1))); 66679566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 66689318fe57SMatthew G. Knepley if (vertexCoords) { 66699566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 66709298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 66719298eaa6SMatthew G Knepley PetscInt off; 66729298eaa6SMatthew G Knepley 66739566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 6674ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 66759298eaa6SMatthew G Knepley } 66769318fe57SMatthew G. Knepley } 66779566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 66789566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 66799566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 66803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 66819298eaa6SMatthew G Knepley } 66828415267dSToby Isaac 6683a4e35b19SJacob Faibussowitsch /* 6684a1cb98faSBarry Smith DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file. 6685a1cb98faSBarry Smith 6686a1cb98faSBarry Smith Collective 66878ca92349SMatthew G. Knepley 66888ca92349SMatthew G. Knepley + comm - The MPI communicator 66898ca92349SMatthew G. Knepley . filename - Name of the .dat file 66908ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 66918ca92349SMatthew G. Knepley 66928ca92349SMatthew G. Knepley Output Parameter: 6693a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 66948ca92349SMatthew G. Knepley 66958ca92349SMatthew G. Knepley Level: beginner 66968ca92349SMatthew G. Knepley 6697a1cb98faSBarry Smith Note: 6698a1cb98faSBarry Smith The format is the simplest possible: 6699a1cb98faSBarry Smith .vb 6700d0812dedSMatthew G. Knepley dim Ne Nv Nc Nl 6701d0812dedSMatthew G. Knepley v_1 v_2 ... v_Nc 6702d0812dedSMatthew G. Knepley ... 6703d0812dedSMatthew G. Knepley x y z marker_1 ... marker_Nl 6704a1cb98faSBarry Smith .ve 6705a1cb98faSBarry Smith 6706a1cb98faSBarry Smith Developer Note: 6707a1cb98faSBarry Smith Should use a `PetscViewer` not a filename 6708a1cb98faSBarry Smith 67096afe31f6SMartin Diehl .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 6710a4e35b19SJacob Faibussowitsch */ 6711ff6a9541SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 6712d71ae5a4SJacob Faibussowitsch { 67138ca92349SMatthew G. Knepley DMLabel marker; 67148ca92349SMatthew G. Knepley PetscViewer viewer; 67158ca92349SMatthew G. Knepley Vec coordinates; 67168ca92349SMatthew G. Knepley PetscSection coordSection; 67178ca92349SMatthew G. Knepley PetscScalar *coords; 67188ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 6719d0812dedSMatthew G. Knepley PetscInt cdim, coordSize, v, c, d; 67208ca92349SMatthew G. Knepley PetscMPIInt rank; 6721d0812dedSMatthew G. Knepley int snum, dim, Nv, Nc, Ncn, Nl; 67228ca92349SMatthew G. Knepley 67238ca92349SMatthew G. Knepley PetscFunctionBegin; 67249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 67259566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 67269566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 67279566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 67289566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 6729dd400576SPatrick Sanan if (rank == 0) { 6730d0812dedSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING)); 6731d0812dedSMatthew G. Knepley snum = sscanf(line, "%d %d %d %d %d", &dim, &Nc, &Nv, &Ncn, &Nl); 6732d0812dedSMatthew G. Knepley PetscCheck(snum == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 673325ce1634SJed Brown } else { 6734f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 67358ca92349SMatthew G. Knepley } 6736d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm)); 6737835f2295SStefano Zampini cdim = dim; 67389566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 67399566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 67409566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 6741835f2295SStefano Zampini PetscCall(DMSetDimension(*dm, dim)); 67429566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 67438ca92349SMatthew G. Knepley /* Read topology */ 6744dd400576SPatrick Sanan if (rank == 0) { 6745f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 6746f8d5e320SMatthew G. Knepley PetscInt cone[8]; 67478ca92349SMatthew G. Knepley int vbuf[8], v; 67488ca92349SMatthew G. Knepley 67499371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 67509371c9d4SSatish Balay format[c * 3 + 0] = '%'; 67519371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 67529371c9d4SSatish Balay format[c * 3 + 2] = ' '; 67539371c9d4SSatish Balay } 6754f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 67559566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 67569566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 67578ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 67589566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 6759f8d5e320SMatthew G. Knepley switch (Ncn) { 6760d71ae5a4SJacob Faibussowitsch case 2: 6761d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1]); 6762d71ae5a4SJacob Faibussowitsch break; 6763d71ae5a4SJacob Faibussowitsch case 3: 6764d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); 6765d71ae5a4SJacob Faibussowitsch break; 6766d71ae5a4SJacob Faibussowitsch case 4: 6767d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); 6768d71ae5a4SJacob Faibussowitsch break; 6769d71ae5a4SJacob Faibussowitsch case 6: 6770d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); 6771d71ae5a4SJacob Faibussowitsch break; 6772d71ae5a4SJacob Faibussowitsch case 8: 6773d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 6774d71ae5a4SJacob Faibussowitsch break; 6775d71ae5a4SJacob Faibussowitsch default: 6776d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 6777f8d5e320SMatthew G. Knepley } 677808401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6779f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 67808ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 6781f8d5e320SMatthew G. Knepley if (Ncn == 8) { 67828ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 67838ca92349SMatthew G. Knepley cone[1] = cone[3]; 67848ca92349SMatthew G. Knepley cone[3] = tmp; 67858ca92349SMatthew G. Knepley } 67869566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 67878ca92349SMatthew G. Knepley } 67888ca92349SMatthew G. Knepley } 67899566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 67909566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 67918ca92349SMatthew G. Knepley /* Read coordinates */ 67929566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 67939566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 67949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 67959566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 67968ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 67979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 67989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 67998ca92349SMatthew G. Knepley } 68009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 68019566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 68029566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 68039566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 68049566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 68059566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 68069566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 68079566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6808dd400576SPatrick Sanan if (rank == 0) { 6809f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 68108ca92349SMatthew G. Knepley double x[3]; 6811f8d5e320SMatthew G. Knepley int l, val[3]; 68128ca92349SMatthew G. Knepley 6813f8d5e320SMatthew G. Knepley if (Nl) { 68149371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 68159371c9d4SSatish Balay format[l * 3 + 0] = '%'; 68169371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 68179371c9d4SSatish Balay format[l * 3 + 2] = ' '; 68189371c9d4SSatish Balay } 6819f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 68209566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 68219566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 6822f8d5e320SMatthew G. Knepley } 68238ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 68249566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 6825f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 682608401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6827f8d5e320SMatthew G. Knepley switch (Nl) { 6828d71ae5a4SJacob Faibussowitsch case 0: 6829d71ae5a4SJacob Faibussowitsch snum = 0; 6830d71ae5a4SJacob Faibussowitsch break; 6831d71ae5a4SJacob Faibussowitsch case 1: 6832d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0]); 6833d71ae5a4SJacob Faibussowitsch break; 6834d71ae5a4SJacob Faibussowitsch case 2: 6835d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1]); 6836d71ae5a4SJacob Faibussowitsch break; 6837d71ae5a4SJacob Faibussowitsch case 3: 6838d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1], &val[2]); 6839d71ae5a4SJacob Faibussowitsch break; 6840d71ae5a4SJacob Faibussowitsch default: 6841d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 6842f8d5e320SMatthew G. Knepley } 684308401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 68448ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 68459566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 68468ca92349SMatthew G. Knepley } 68478ca92349SMatthew G. Knepley } 68489566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 68499566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 68509566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 68519566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 68528ca92349SMatthew G. Knepley if (interpolate) { 68538ca92349SMatthew G. Knepley DM idm; 68548ca92349SMatthew G. Knepley DMLabel bdlabel; 68558ca92349SMatthew G. Knepley 68569566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 68579566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 68588ca92349SMatthew G. Knepley *dm = idm; 68598ca92349SMatthew G. Knepley 6860f8d5e320SMatthew G. Knepley if (!Nl) { 68619566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 68629566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 68639566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 68649566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 68658ca92349SMatthew G. Knepley } 6866f8d5e320SMatthew G. Knepley } 68673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68688ca92349SMatthew G. Knepley } 68698ca92349SMatthew G. Knepley 6870edfba7faSMatthew G. Knepley /* 6871edfba7faSMatthew G. Knepley DMPlexCreateSTLFromFile - Create a `DMPLEX` mesh from an STL file. 6872edfba7faSMatthew G. Knepley 6873edfba7faSMatthew G. Knepley Collective 6874edfba7faSMatthew G. Knepley 6875edfba7faSMatthew G. Knepley + comm - The MPI communicator 6876edfba7faSMatthew G. Knepley . filename - Name of the .dat file 6877edfba7faSMatthew G. Knepley - interpolate - Create faces and edges in the mesh 6878edfba7faSMatthew G. Knepley 6879edfba7faSMatthew G. Knepley Output Parameter: 6880edfba7faSMatthew G. Knepley . dm - The `DM` object representing the mesh 6881edfba7faSMatthew G. Knepley 6882edfba7faSMatthew G. Knepley Level: beginner 6883edfba7faSMatthew G. Knepley 6884edfba7faSMatthew G. Knepley Notes: 6885edfba7faSMatthew G. Knepley The binary format is: 6886edfba7faSMatthew G. Knepley .vb 6887edfba7faSMatthew G. Knepley UINT8[80] - Header - 80 bytes 6888edfba7faSMatthew G. Knepley UINT32 - Number of triangles - 04 bytes 6889edfba7faSMatthew G. Knepley foreach triangle - 50 bytes 6890edfba7faSMatthew G. Knepley REAL32[3] - Normal vector - 12 bytes 6891edfba7faSMatthew G. Knepley REAL32[3] - Vertex 1 - 12 bytes 6892edfba7faSMatthew G. Knepley REAL32[3] - Vertex 2 - 12 bytes 6893edfba7faSMatthew G. Knepley REAL32[3] - Vertex 3 - 12 bytes 6894edfba7faSMatthew G. Knepley UINT16 - Attribute byte count - 02 bytes 6895edfba7faSMatthew G. Knepley end 6896edfba7faSMatthew G. Knepley .ve 6897edfba7faSMatthew G. Knepley 6898edfba7faSMatthew G. Knepley The format is here <https://en.wikipedia.org/wiki/STL_(file_format)> 6899edfba7faSMatthew G. Knepley 6900edfba7faSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 6901edfba7faSMatthew G. Knepley */ 6902edfba7faSMatthew G. Knepley static PetscErrorCode DMPlexCreateSTLFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 6903edfba7faSMatthew G. Knepley { 6904edfba7faSMatthew G. Knepley PetscViewer viewer; 6905edfba7faSMatthew G. Knepley Vec coordinates; 6906edfba7faSMatthew G. Knepley PetscSection coordSection; 6907edfba7faSMatthew G. Knepley PetscScalar *coords; 6908edfba7faSMatthew G. Knepley PetscInt coordSize; 6909edfba7faSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 6910edfba7faSMatthew G. Knepley PetscBT bt; 6911edfba7faSMatthew G. Knepley float *trialCoords = NULL; 6912edfba7faSMatthew G. Knepley PetscInt *cells = NULL; 6913edfba7faSMatthew G. Knepley PetscBool isascii; 6914edfba7faSMatthew G. Knepley PetscMPIInt rank; 6915edfba7faSMatthew G. Knepley PetscInt Nc, Nv, nv = 0; 6916edfba7faSMatthew G. Knepley 6917edfba7faSMatthew G. Knepley PetscFunctionBegin; 6918edfba7faSMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 6919edfba7faSMatthew G. Knepley PetscCall(PetscViewerCreate(comm, &viewer)); 6920edfba7faSMatthew G. Knepley PetscCall(PetscViewerSetType(viewer, PETSCVIEWERBINARY)); 6921edfba7faSMatthew G. Knepley PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 6922edfba7faSMatthew G. Knepley PetscCall(PetscViewerFileSetName(viewer, filename)); 6923edfba7faSMatthew G. Knepley if (rank == 0) { 6924edfba7faSMatthew G. Knepley int num; 6925edfba7faSMatthew G. Knepley 6926edfba7faSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_CHAR)); 6927edfba7faSMatthew G. Knepley line[5] = 0; 6928edfba7faSMatthew G. Knepley PetscCall(PetscStrncmp(line, "solid", 5, &isascii)); 6929edfba7faSMatthew G. Knepley PetscCheck(!isascii, comm, PETSC_ERR_SUP, "No support for ASCII yet"); 6930edfba7faSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, line, 75, NULL, PETSC_CHAR)); 6931edfba7faSMatthew G. Knepley line[75] = 0; 6932edfba7faSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_INT32)); 6933edfba7faSMatthew G. Knepley PetscCall(PetscByteSwap(&num, PETSC_INT32, 1)); 6934edfba7faSMatthew G. Knepley Nc = num; 6935edfba7faSMatthew G. Knepley // Read facet coordinates 6936edfba7faSMatthew G. Knepley PetscCall(PetscMalloc1(Nc * 9, &trialCoords)); 6937edfba7faSMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 6938edfba7faSMatthew G. Knepley double normal[3]; 6939edfba7faSMatthew G. Knepley short int dummy; 6940edfba7faSMatthew G. Knepley 6941edfba7faSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, normal, 3, NULL, PETSC_FLOAT)); 6942edfba7faSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, &trialCoords[c * 9 + 0], 9, NULL, PETSC_FLOAT)); 6943edfba7faSMatthew G. Knepley PetscCall(PetscByteSwap(&trialCoords[c * 9 + 0], PETSC_FLOAT, 9)); 6944edfba7faSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, &dummy, 1, NULL, PETSC_SHORT)); 6945edfba7faSMatthew G. Knepley } 6946edfba7faSMatthew G. Knepley PetscCall(PetscMalloc1(Nc * 3, &cells)); 6947edfba7faSMatthew G. Knepley // Find unique vertices 6948edfba7faSMatthew G. Knepley PetscCall(PetscBTCreate(Nc * 3, &bt)); 6949edfba7faSMatthew G. Knepley PetscCall(PetscBTMemzero(Nc * 3, bt)); 6950edfba7faSMatthew G. Knepley PetscCall(PetscBTSet(bt, 0)); 6951edfba7faSMatthew G. Knepley PetscCall(PetscBTSet(bt, 1)); 6952edfba7faSMatthew G. Knepley PetscCall(PetscBTSet(bt, 2)); 6953edfba7faSMatthew G. Knepley Nv = 0; 6954edfba7faSMatthew G. Knepley cells[0] = Nc + Nv++; 6955edfba7faSMatthew G. Knepley cells[1] = Nc + Nv++; 6956edfba7faSMatthew G. Knepley cells[2] = Nc + Nv++; 6957edfba7faSMatthew G. Knepley for (PetscInt v = 3; v < Nc * 3; ++v) { 6958edfba7faSMatthew G. Knepley PetscBool match = PETSC_FALSE; 6959edfba7faSMatthew G. Knepley 6960edfba7faSMatthew G. Knepley for (PetscInt w = 0, x = 0; w < v; ++w) { 6961edfba7faSMatthew G. Knepley if (PetscBTLookup(bt, w)) { 6962edfba7faSMatthew G. Knepley if (trialCoords[v * 3 + 0] == trialCoords[w * 3 + 0] && trialCoords[v * 3 + 1] == trialCoords[w * 3 + 1] && trialCoords[v * 3 + 2] == trialCoords[w * 3 + 2]) { 6963edfba7faSMatthew G. Knepley match = PETSC_TRUE; 6964edfba7faSMatthew G. Knepley cells[v] = Nc + x; 6965edfba7faSMatthew G. Knepley break; 6966edfba7faSMatthew G. Knepley } 6967edfba7faSMatthew G. Knepley ++x; 6968edfba7faSMatthew G. Knepley } 6969edfba7faSMatthew G. Knepley } 6970edfba7faSMatthew G. Knepley if (!match) { 6971edfba7faSMatthew G. Knepley PetscCall(PetscBTSet(bt, v)); 6972edfba7faSMatthew G. Knepley cells[v] = Nc + Nv++; 6973edfba7faSMatthew G. Knepley } 6974edfba7faSMatthew G. Knepley } 6975edfba7faSMatthew G. Knepley } else { 6976edfba7faSMatthew G. Knepley Nc = Nv = 0; 6977edfba7faSMatthew G. Knepley } 6978edfba7faSMatthew G. Knepley for (PetscInt v = 3; v < Nc * 3; ++v) PetscCheck(cells[v] < Nc + Nv, comm, PETSC_ERR_PLIB, "Invalid cells[%" PetscInt_FMT "]: %" PetscInt_FMT, v, cells[v]); 6979edfba7faSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 6980edfba7faSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 6981edfba7faSMatthew G. Knepley PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 6982edfba7faSMatthew G. Knepley PetscCall(DMSetDimension(*dm, 2)); 6983edfba7faSMatthew G. Knepley PetscCall(DMSetCoordinateDim(*dm, 3)); 6984edfba7faSMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, 3)); 6985edfba7faSMatthew G. Knepley PetscCall(DMSetUp(*dm)); 6986edfba7faSMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) PetscCall(DMPlexSetCone(*dm, c, &cells[c * 3])); 6987edfba7faSMatthew G. Knepley PetscCall(PetscFree(cells)); 6988edfba7faSMatthew G. Knepley PetscCall(DMPlexSymmetrize(*dm)); 6989edfba7faSMatthew G. Knepley PetscCall(DMPlexStratify(*dm)); 6990edfba7faSMatthew G. Knepley 6991edfba7faSMatthew G. Knepley PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 6992edfba7faSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(coordSection, 1)); 6993edfba7faSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 6994edfba7faSMatthew G. Knepley PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 6995edfba7faSMatthew G. Knepley for (PetscInt v = Nc; v < Nc + Nv; ++v) { 6996edfba7faSMatthew G. Knepley PetscCall(PetscSectionSetDof(coordSection, v, 3)); 6997edfba7faSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 6998edfba7faSMatthew G. Knepley } 6999edfba7faSMatthew G. Knepley PetscCall(PetscSectionSetUp(coordSection)); 7000edfba7faSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 7001edfba7faSMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 7002edfba7faSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 7003edfba7faSMatthew G. Knepley PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 7004edfba7faSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinates, 3)); 7005edfba7faSMatthew G. Knepley PetscCall(VecSetType(coordinates, VECSTANDARD)); 7006edfba7faSMatthew G. Knepley PetscCall(VecGetArray(coordinates, &coords)); 7007edfba7faSMatthew G. Knepley for (PetscInt tv = 0; tv < Nc * 3; ++tv) { 7008edfba7faSMatthew G. Knepley if (PetscBTLookup(bt, tv)) { 7009edfba7faSMatthew G. Knepley for (PetscInt d = 0; d < 3; ++d) coords[nv * 3 + d] = trialCoords[tv * 3 + d]; 7010edfba7faSMatthew G. Knepley ++nv; 7011edfba7faSMatthew G. Knepley } 7012edfba7faSMatthew G. Knepley } 70138c5add6aSPierre Jolivet PetscCheck(nv == Nv, comm, PETSC_ERR_PLIB, "Number of vertices copied %" PetscInt_FMT " != %" PetscInt_FMT " number of mesh vertices", nv, Nv); 7014edfba7faSMatthew G. Knepley PetscCall(PetscFree(trialCoords)); 7015edfba7faSMatthew G. Knepley PetscCall(PetscBTDestroy(&bt)); 7016edfba7faSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &coords)); 7017edfba7faSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 7018edfba7faSMatthew G. Knepley PetscCall(VecDestroy(&coordinates)); 7019edfba7faSMatthew G. Knepley PetscCall(PetscViewerDestroy(&viewer)); 7020edfba7faSMatthew G. Knepley if (interpolate) { 7021edfba7faSMatthew G. Knepley DM idm; 7022edfba7faSMatthew G. Knepley 7023edfba7faSMatthew G. Knepley PetscCall(DMPlexInterpolate(*dm, &idm)); 7024edfba7faSMatthew G. Knepley PetscCall(DMDestroy(dm)); 7025edfba7faSMatthew G. Knepley *dm = idm; 7026edfba7faSMatthew G. Knepley } 7027edfba7faSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 7028edfba7faSMatthew G. Knepley } 7029edfba7faSMatthew G. Knepley 7030f536a3c1SMatthew G. Knepley /* 7031f536a3c1SMatthew G. Knepley DMPlexCreateShapefile - Create a `DMPLEX` mesh from the ESRI Shapefile format. 7032f536a3c1SMatthew G. Knepley 7033f536a3c1SMatthew G. Knepley Collective 7034f536a3c1SMatthew G. Knepley 7035f536a3c1SMatthew G. Knepley + comm - The MPI communicator 7036f536a3c1SMatthew G. Knepley - viewer - `PetscViewer` for the .shp file 7037f536a3c1SMatthew G. Knepley 7038f536a3c1SMatthew G. Knepley Output Parameter: 7039f536a3c1SMatthew G. Knepley . dm - The `DM` object representing the mesh 7040f536a3c1SMatthew G. Knepley 7041f536a3c1SMatthew G. Knepley Level: beginner 7042f536a3c1SMatthew G. Knepley 7043f536a3c1SMatthew G. Knepley Note: 7044f536a3c1SMatthew G. Knepley The format is specified at [Wikipedia](https://en.wikipedia.org/wiki/Shapefile) and [ESRI](https://www.esri.com/content/dam/esrisites/sitecore-archive/Files/Pdfs/library/whitepapers/pdfs/shapefile.pdf). 7045f536a3c1SMatthew G. Knepley 7046f536a3c1SMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 7047f536a3c1SMatthew G. Knepley */ 7048f536a3c1SMatthew G. Knepley static PetscErrorCode DMPlexCreateShapefile(MPI_Comm comm, PetscViewer viewer, DM *dm) 7049f536a3c1SMatthew G. Knepley { 7050f536a3c1SMatthew G. Knepley Vec coordinates; 7051f536a3c1SMatthew G. Knepley PetscSection coordSection; 7052f536a3c1SMatthew G. Knepley PetscScalar *coords; 7053f536a3c1SMatthew G. Knepley PetscInt cdim = 2, coordSize; 7054f536a3c1SMatthew G. Knepley int dim = 1, Nv, Nc, vOff; 7055f536a3c1SMatthew G. Knepley double *points = NULL; 7056f536a3c1SMatthew G. Knepley double mbr[4], zb[2], mb[2]; 7057f536a3c1SMatthew G. Knepley PetscMPIInt rank; 7058f536a3c1SMatthew G. Knepley 7059f536a3c1SMatthew G. Knepley PetscFunctionBegin; 7060f536a3c1SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7061f536a3c1SMatthew G. Knepley if (rank == 0) { 7062f536a3c1SMatthew G. Knepley PetscInt cnt; 7063f536a3c1SMatthew G. Knepley int magic, dummy[5], len, version, shtype, totlen = 0; 7064f536a3c1SMatthew G. Knepley 7065f536a3c1SMatthew G. Knepley // Read header 7066f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &magic, 1, &cnt, PETSC_INT32)); 7067f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 0-3"); 7068f536a3c1SMatthew G. Knepley PetscCheck(magic == 0x0000270a, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: invalid magic number %X", magic); 7069f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, dummy, 5, &cnt, PETSC_INT32)); 7070f536a3c1SMatthew G. Knepley PetscCheck(cnt == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 4-23"); 7071f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &len, 1, &cnt, PETSC_INT32)); 7072f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 24-27"); 7073f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &version, 1, &cnt, PETSC_INT32)); 7074f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(&version, PETSC_INT32, 1)); 7075f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 28-31"); 7076f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: version %d file length %d\n", version, len)); 7077f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &shtype, 1, &cnt, PETSC_INT32)); 7078f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(&shtype, PETSC_INT32, 1)); 7079f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 32-35"); 7080f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: shape type %d\n", shtype)); 7081f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, mbr, 4, &cnt, PETSC_DOUBLE)); 7082f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(mbr, PETSC_DOUBLE, 4)); 7083f536a3c1SMatthew G. Knepley PetscCheck(cnt == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 36-67"); 7084f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: minimum bounding rectangle (%g, %g) -- (%g, %g)\n", mbr[0], mbr[1], mbr[2], mbr[3])); 7085f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, zb, 2, &cnt, PETSC_DOUBLE)); 7086f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(zb, PETSC_DOUBLE, 2)); 7087f536a3c1SMatthew G. Knepley PetscCheck(cnt == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 68-83"); 7088f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: Z bounds (%g) -- (%g)\n", zb[0], zb[1])); 7089f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, mb, 2, &cnt, PETSC_DOUBLE)); 7090f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(mb, PETSC_DOUBLE, 2)); 7091f536a3c1SMatthew G. Knepley PetscCheck(cnt == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 84-99"); 7092f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: M bounds (%g) -- (%g)\n", mb[0], mb[1])); 7093f536a3c1SMatthew G. Knepley totlen += 100; 7094f536a3c1SMatthew G. Knepley { 7095f536a3c1SMatthew G. Knepley int rnum, rlen, rshtype, rnpart, rnp; 7096f536a3c1SMatthew G. Knepley double rmbr[4]; 7097f536a3c1SMatthew G. Knepley int *partOffsets; 7098f536a3c1SMatthew G. Knepley 7099f536a3c1SMatthew G. Knepley // Read record header 7100f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &rnum, 1, &cnt, PETSC_INT32)); 7101f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record header bytes 0-3"); 7102f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &rlen, 1, &cnt, PETSC_INT32)); 7103f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record header bytes 4-7"); 7104f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: record %d length %d\n", rnum, rlen)); 7105f536a3c1SMatthew G. Knepley totlen += 8; 7106f536a3c1SMatthew G. Knepley // Read record 7107f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &rshtype, 1, &cnt, PETSC_INT32)); 7108f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(&rshtype, PETSC_INT32, 1)); 7109f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record bytes 0-3"); 7110f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: record shape type %d\n", rshtype)); 7111f536a3c1SMatthew G. Knepley totlen += 4; 7112f536a3c1SMatthew G. Knepley switch (rshtype) { 7113f536a3c1SMatthew G. Knepley case 5: // Polygon 7114f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, rmbr, 4, &cnt, PETSC_DOUBLE)); 7115f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(rmbr, PETSC_DOUBLE, 4)); 7116f536a3c1SMatthew G. Knepley PetscCheck(cnt == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record bytes 4-35"); 7117f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: record minimum bounding rectangle (%g, %g) -- (%g, %g)\n", rmbr[0], rmbr[1], rmbr[2], rmbr[3])); 7118f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &rnpart, 1, &cnt, PETSC_INT32)); 7119f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(&rnpart, PETSC_INT32, 1)); 7120f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record bytes 36-39"); 7121f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: record shape number of parts %d\n", rnpart)); 7122f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &rnp, 1, &cnt, PETSC_INT32)); 7123f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(&rnp, PETSC_INT32, 1)); 7124f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record bytes 36-39"); 7125f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: record shape number of points %d\n", rnp)); 7126f536a3c1SMatthew G. Knepley totlen += 40; 7127f536a3c1SMatthew G. Knepley PetscCall(PetscMalloc1(rnpart, &partOffsets)); 7128f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, partOffsets, rnpart, &cnt, PETSC_INT32)); 7129f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(partOffsets, PETSC_INT32, rnpart)); 7130f536a3c1SMatthew G. Knepley PetscCheck(cnt == rnpart, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record part offsets"); 7131f536a3c1SMatthew G. Knepley totlen += 4 * rnpart; 7132f536a3c1SMatthew G. Knepley PetscCall(PetscMalloc1(rnp * 2, &points)); 7133f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, points, rnp * 2, &cnt, PETSC_DOUBLE)); 7134f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(points, PETSC_DOUBLE, rnp * 2)); 7135f536a3c1SMatthew G. Knepley PetscCheck(cnt == rnp * 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record points"); 7136f536a3c1SMatthew G. Knepley totlen += 8 * rnp * 2; 7137f536a3c1SMatthew G. Knepley PetscCheck(totlen == 2 * len, PETSC_COMM_SELF, PETSC_ERR_SUP, "Unable to parse Shapefile file: only support a single object: %d != %d", totlen, 2 * len); 7138f536a3c1SMatthew G. Knepley // Only get the last polygon now 7139f536a3c1SMatthew G. Knepley vOff = partOffsets[rnpart - 1]; 7140f536a3c1SMatthew G. Knepley Nv = rnp - vOff; 7141f536a3c1SMatthew G. Knepley Nc = Nv - 1; 7142f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: record first polygon size %d totlen %d\n", Nv, totlen)); 7143f536a3c1SMatthew G. Knepley PetscCall(PetscFree(partOffsets)); 7144f536a3c1SMatthew G. Knepley break; 7145f536a3c1SMatthew G. Knepley default: 7146f536a3c1SMatthew G. Knepley PetscCheck(0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only support polygons right now"); 7147f536a3c1SMatthew G. Knepley } 7148f536a3c1SMatthew G. Knepley } 7149f536a3c1SMatthew G. Knepley } else { 7150f536a3c1SMatthew G. Knepley Nc = Nv = vOff = 0; 7151f536a3c1SMatthew G. Knepley } 7152f536a3c1SMatthew G. Knepley PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm)); 7153f536a3c1SMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 7154f536a3c1SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 7155f536a3c1SMatthew G. Knepley PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 7156f536a3c1SMatthew G. Knepley PetscCall(DMSetDimension(*dm, dim)); 7157f536a3c1SMatthew G. Knepley PetscCall(DMSetCoordinateDim(*dm, cdim)); 7158f536a3c1SMatthew G. Knepley // Topology of a circle 7159f536a3c1SMatthew G. Knepley if (rank == 0) { 7160f536a3c1SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, 2)); 7161f536a3c1SMatthew G. Knepley PetscCall(DMSetUp(*dm)); 7162f536a3c1SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 7163f536a3c1SMatthew G. Knepley PetscInt cone[2] = {Nc + c, Nc + c + 1}; 7164f536a3c1SMatthew G. Knepley 7165f536a3c1SMatthew G. Knepley PetscCall(DMPlexSetCone(*dm, c, cone)); 7166f536a3c1SMatthew G. Knepley } 7167f536a3c1SMatthew G. Knepley } 7168f536a3c1SMatthew G. Knepley PetscCall(DMPlexSymmetrize(*dm)); 7169f536a3c1SMatthew G. Knepley PetscCall(DMPlexStratify(*dm)); 7170f536a3c1SMatthew G. Knepley // Set coordinates 7171f536a3c1SMatthew G. Knepley PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 7172f536a3c1SMatthew G. Knepley PetscCall(PetscSectionSetNumFields(coordSection, 1)); 7173f536a3c1SMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 7174f536a3c1SMatthew G. Knepley PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 7175f536a3c1SMatthew G. Knepley for (PetscInt v = Nc; v < Nc + Nv; ++v) { 7176f536a3c1SMatthew G. Knepley PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 7177f536a3c1SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 7178f536a3c1SMatthew G. Knepley } 7179f536a3c1SMatthew G. Knepley PetscCall(PetscSectionSetUp(coordSection)); 7180f536a3c1SMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 7181f536a3c1SMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 7182f536a3c1SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 7183f536a3c1SMatthew G. Knepley PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 7184f536a3c1SMatthew G. Knepley PetscCall(VecSetBlockSize(coordinates, cdim)); 7185f536a3c1SMatthew G. Knepley PetscCall(VecSetType(coordinates, VECSTANDARD)); 7186f536a3c1SMatthew G. Knepley PetscCall(VecGetArray(coordinates, &coords)); 7187f536a3c1SMatthew G. Knepley for (PetscInt v = 0; v < Nv; ++v) { 7188f536a3c1SMatthew G. Knepley coords[v * cdim + 0] = points[(v + vOff) * cdim + 0] - mbr[0]; 7189f536a3c1SMatthew G. Knepley coords[v * cdim + 1] = points[(v + vOff) * cdim + 1] - mbr[1]; 7190f536a3c1SMatthew G. Knepley } 7191f536a3c1SMatthew G. Knepley PetscCall(PetscFree(points)); 7192f536a3c1SMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &coords)); 7193f536a3c1SMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 7194f536a3c1SMatthew G. Knepley PetscCall(VecDestroy(&coordinates)); 7195f536a3c1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 7196f536a3c1SMatthew G. Knepley } 7197f536a3c1SMatthew G. Knepley 7198f536a3c1SMatthew G. Knepley /* 7199f536a3c1SMatthew G. Knepley DMPlexCreateShapefileFromFile - Create a `DMPLEX` mesh from the ESRI Shapefile format. 7200f536a3c1SMatthew G. Knepley 7201f536a3c1SMatthew G. Knepley Collective 7202f536a3c1SMatthew G. Knepley 7203f536a3c1SMatthew G. Knepley + comm - The MPI communicator 7204f536a3c1SMatthew G. Knepley . filename - Name of the .shp file 7205f536a3c1SMatthew G. Knepley 7206f536a3c1SMatthew G. Knepley Output Parameter: 7207f536a3c1SMatthew G. Knepley . dm - The `DM` object representing the mesh 7208f536a3c1SMatthew G. Knepley 7209f536a3c1SMatthew G. Knepley Level: beginner 7210f536a3c1SMatthew G. Knepley 7211f536a3c1SMatthew G. Knepley Note: 7212f536a3c1SMatthew G. Knepley The format is specified at [Wikipedia](https://en.wikipedia.org/wiki/Shapefile) and [ESRI](https://www.esri.com/content/dam/esrisites/sitecore-archive/Files/Pdfs/library/whitepapers/pdfs/shapefile.pdf). 7213f536a3c1SMatthew G. Knepley 7214f536a3c1SMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 7215f536a3c1SMatthew G. Knepley */ 7216f536a3c1SMatthew G. Knepley static PetscErrorCode DMPlexCreateShapefileFromFile(MPI_Comm comm, const char filename[], DM *dm) 7217f536a3c1SMatthew G. Knepley { 7218f536a3c1SMatthew G. Knepley PetscViewer viewer; 7219f536a3c1SMatthew G. Knepley 7220f536a3c1SMatthew G. Knepley PetscFunctionBegin; 7221f536a3c1SMatthew G. Knepley PetscCall(PetscViewerCreate(comm, &viewer)); 7222f536a3c1SMatthew G. Knepley PetscCall(PetscViewerSetType(viewer, PETSCVIEWERBINARY)); 7223f536a3c1SMatthew G. Knepley PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 7224f536a3c1SMatthew G. Knepley PetscCall(PetscViewerFileSetName(viewer, filename)); 7225f536a3c1SMatthew G. Knepley PetscCall(DMPlexCreateShapefile(comm, viewer, dm)); 7226f536a3c1SMatthew G. Knepley PetscCall(PetscViewerDestroy(&viewer)); 7227f536a3c1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 7228f536a3c1SMatthew G. Knepley } 7229f536a3c1SMatthew G. Knepley 7230cc4c1da9SBarry Smith /*@ 7231a1cb98faSBarry Smith DMPlexCreateFromFile - This takes a filename and produces a `DM` 7232a1cb98faSBarry Smith 7233a1cb98faSBarry Smith Collective 7234ca522641SMatthew G. Knepley 7235ca522641SMatthew G. Knepley Input Parameters: 7236ca522641SMatthew G. Knepley + comm - The communicator 7237ca522641SMatthew G. Knepley . filename - A file name 7238a1cb98faSBarry Smith . plexname - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats 7239ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 7240ca522641SMatthew G. Knepley 7241ca522641SMatthew G. Knepley Output Parameter: 7242a1cb98faSBarry Smith . dm - The `DM` 7243ca522641SMatthew G. Knepley 7244a1cb98faSBarry Smith Options Database Key: 7245a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5 724602ef0d99SVaclav Hapla 7247b44f4de4SBarry Smith Use `-dm_plex_create_ prefix` to pass options to the internal `PetscViewer`, e.g. `-dm_plex_create_viewer_hdf5_collective` 7248bca97951SVaclav Hapla 7249ca522641SMatthew G. Knepley Level: beginner 7250ca522641SMatthew G. Knepley 7251a1cb98faSBarry Smith Notes: 7252a1cb98faSBarry Smith Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX` 7253a1cb98faSBarry Smith meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()` 7254a1cb98faSBarry Smith before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object. 7255a1cb98faSBarry Smith The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally 7256a1cb98faSBarry Smith calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats. 7257a1cb98faSBarry Smith 72581cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 7259ca522641SMatthew G. Knepley @*/ 7260d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 7261d71ae5a4SJacob Faibussowitsch { 7262ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 7263ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 7264ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 7265ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 7266ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 7267ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 7268ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 7269ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 7270ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 72716f2c871aSStefano Zampini const char extXDMFHDF5[] = ".xdmf.h5"; 7272ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 72735552b385SBrandon const char extEGADSlite[] = ".egadslite"; 7274ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 7275ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 72765552b385SBrandon const char extIGES2[] = ".iges"; 7277ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 72785552b385SBrandon const char extSTEP2[] = ".step"; 72795552b385SBrandon const char extBREP[] = ".brep"; 7280ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 7281edfba7faSMatthew G. Knepley const char extSTL[] = ".stl"; 7282f536a3c1SMatthew G. Knepley const char extSHP[] = ".shp"; 7283ca522641SMatthew G. Knepley size_t len; 7284f536a3c1SMatthew G. Knepley PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isPLY, isEGADSlite, isEGADS, isIGES, isIGES2, isSTEP, isSTEP2, isBREP, isCV, isSTL, isSHP, isXDMFHDF5; 7285ca522641SMatthew G. Knepley PetscMPIInt rank; 7286ca522641SMatthew G. Knepley 7287ca522641SMatthew G. Knepley PetscFunctionBegin; 72884f572ea9SToby Isaac PetscAssertPointer(filename, 2); 72894f572ea9SToby Isaac if (plexname) PetscAssertPointer(plexname, 3); 72904f572ea9SToby Isaac PetscAssertPointer(dm, 5); 72919566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 72929566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 72939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 72949566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 729528b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 7296ef3a5affSJacob Faibussowitsch 72979371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 72989371c9d4SSatish Balay do { \ 7299274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 7300274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 7301274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 7302274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 7303ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 7304ef3a5affSJacob Faibussowitsch } else { \ 7305274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 7306ef3a5affSJacob Faibussowitsch } \ 7307ef3a5affSJacob Faibussowitsch } while (0) 7308ef3a5affSJacob Faibussowitsch 7309ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 7310ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 7311ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 7312ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 7313ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 7314ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 7315ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 7316ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 7317ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 7318ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 73195552b385SBrandon CheckExtension(extEGADSlite, isEGADSlite); 7320ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 7321ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 73225552b385SBrandon CheckExtension(extIGES2, isIGES2); 7323ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 73245552b385SBrandon CheckExtension(extSTEP2, isSTEP2); 73255552b385SBrandon CheckExtension(extBREP, isBREP); 7326ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 7327edfba7faSMatthew G. Knepley CheckExtension(extSTL, isSTL); 7328f536a3c1SMatthew G. Knepley CheckExtension(extSHP, isSHP); 73296f2c871aSStefano Zampini CheckExtension(extXDMFHDF5, isXDMFHDF5); 7330ef3a5affSJacob Faibussowitsch 7331ef3a5affSJacob Faibussowitsch #undef CheckExtension 7332ef3a5affSJacob Faibussowitsch 7333de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 73349566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 7335ca522641SMatthew G. Knepley } else if (isCGNS) { 73369566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 733790c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 73389566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 73392f0bd6dcSMichael Lange } else if (isFluent) { 73409566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 7341cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 7342cc2f8f65SMatthew G. Knepley PetscViewer viewer; 7343cc2f8f65SMatthew G. Knepley 734443b242b4SVaclav 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 */ 73456f2c871aSStefano Zampini PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &isXDMFHDF5, NULL)); 73469566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 73479566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 73489566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 73499566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 73509566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 73519566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 7352cd7e8a5eSksagiyam 73539566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 7354f4f49eeaSPierre Jolivet PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 73559566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 73566f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 73579566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 73586f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPopFormat(viewer)); 73599566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 73605fd9971aSMatthew G. Knepley 73615fd9971aSMatthew G. Knepley if (interpolate) { 73625fd9971aSMatthew G. Knepley DM idm; 73635fd9971aSMatthew G. Knepley 73649566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 73659566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 73665fd9971aSMatthew G. Knepley *dm = idm; 73675fd9971aSMatthew G. Knepley } 7368f2801cd6SMatthew G. Knepley } else if (isPLY) { 73699566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 73705552b385SBrandon } else if (isEGADSlite || isEGADS || isIGES || isIGES2 || isSTEP || isSTEP2 || isBREP) { 73715552b385SBrandon PetscCall(DMPlexCreateGeomFromFile(comm, filename, dm, isEGADSlite)); 73725552b385SBrandon 73737bee2925SMatthew Knepley if (!interpolate) { 73747bee2925SMatthew Knepley DM udm; 73757bee2925SMatthew Knepley 73769566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 73779566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 73787bee2925SMatthew Knepley *dm = udm; 73797bee2925SMatthew Knepley } 73808ca92349SMatthew G. Knepley } else if (isCV) { 73819566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 7382edfba7faSMatthew G. Knepley } else if (isSTL) { 7383edfba7faSMatthew G. Knepley PetscCall(DMPlexCreateSTLFromFile(comm, filename, interpolate, dm)); 7384f536a3c1SMatthew G. Knepley } else if (isSHP) { 7385f536a3c1SMatthew G. Knepley PetscCall(DMPlexCreateShapefileFromFile(comm, filename, dm)); 738698921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 73879566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 7388f4f49eeaSPierre Jolivet if (len) PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 73899566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 73903ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7391ca522641SMatthew G. Knepley } 739212b8a6daSStefano Zampini 7393cc4c1da9SBarry Smith /*@ 73949f6c5813SMatthew 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. 73959f6c5813SMatthew G. Knepley 73960528010dSStefano Zampini Input Parameters: 73970528010dSStefano Zampini + tr - The `DMPlexTransform` 73980528010dSStefano Zampini - prefix - An options prefix, or NULL 73999f6c5813SMatthew G. Knepley 74009f6c5813SMatthew G. Knepley Output Parameter: 74019f6c5813SMatthew G. Knepley . dm - The `DM` 74029f6c5813SMatthew G. Knepley 74039f6c5813SMatthew G. Knepley Level: beginner 74049f6c5813SMatthew G. Knepley 740520f4b53cSBarry Smith Notes: 740620f4b53cSBarry 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. 740720f4b53cSBarry Smith 74089f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 74099f6c5813SMatthew G. Knepley @*/ 74100528010dSStefano Zampini PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, const char prefix[], DM *dm) 74119f6c5813SMatthew G. Knepley { 74120528010dSStefano Zampini DM bdm, bcdm, cdm; 74130528010dSStefano Zampini Vec coordinates, coordinatesNew; 74140528010dSStefano Zampini PetscSection cs; 7415817b2c36SMatthew G. Knepley PetscInt cdim, Nl; 74169f6c5813SMatthew G. Knepley 74179f6c5813SMatthew G. Knepley PetscFunctionBegin; 74189f6c5813SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm)); 74199f6c5813SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 74200528010dSStefano Zampini ((DM_Plex *)(*dm)->data)->interpolated = DMPLEX_INTERPOLATED_FULL; 74210528010dSStefano Zampini // Handle coordinates 74220528010dSStefano Zampini PetscCall(DMPlexTransformGetDM(tr, &bdm)); 7423817b2c36SMatthew G. Knepley PetscCall(DMPlexTransformSetDimensions(tr, bdm, *dm)); 7424817b2c36SMatthew G. Knepley PetscCall(DMGetCoordinateDim(*dm, &cdim)); 74250528010dSStefano Zampini PetscCall(DMGetCoordinateDM(bdm, &bcdm)); 74260528010dSStefano Zampini PetscCall(DMGetCoordinateDM(*dm, &cdm)); 74270528010dSStefano Zampini PetscCall(DMCopyDisc(bcdm, cdm)); 74280528010dSStefano Zampini PetscCall(DMGetLocalSection(cdm, &cs)); 74290528010dSStefano Zampini PetscCall(PetscSectionSetNumFields(cs, 1)); 74300528010dSStefano Zampini PetscCall(PetscSectionSetFieldComponents(cs, 0, cdim)); 74310528010dSStefano Zampini PetscCall(DMGetCoordinatesLocal(bdm, &coordinates)); 74320528010dSStefano Zampini PetscCall(VecDuplicate(coordinates, &coordinatesNew)); 74330528010dSStefano Zampini PetscCall(VecCopy(coordinates, coordinatesNew)); 74340528010dSStefano Zampini PetscCall(DMSetCoordinatesLocal(*dm, coordinatesNew)); 74350528010dSStefano Zampini PetscCall(VecDestroy(&coordinatesNew)); 74369f6c5813SMatthew G. Knepley 74379f6c5813SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)tr)); 74389f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr)); 74399f6c5813SMatthew G. Knepley ((DM_Plex *)(*dm)->data)->tr = tr; 74400528010dSStefano Zampini PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE)); 74410528010dSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix)); 74420528010dSStefano Zampini PetscCall(DMSetFromOptions(*dm)); 74439f6c5813SMatthew G. Knepley 74449f6c5813SMatthew G. Knepley PetscCall(DMGetNumLabels(bdm, &Nl)); 74459f6c5813SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 74469f6c5813SMatthew G. Knepley DMLabel label, labelNew; 74479f6c5813SMatthew G. Knepley const char *lname; 74489f6c5813SMatthew G. Knepley PetscBool isDepth, isCellType; 74499f6c5813SMatthew G. Knepley 74509f6c5813SMatthew G. Knepley PetscCall(DMGetLabelName(bdm, l, &lname)); 74519f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 74529f6c5813SMatthew G. Knepley if (isDepth) continue; 74539f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "celltype", &isCellType)); 74549f6c5813SMatthew G. Knepley if (isCellType) continue; 74559f6c5813SMatthew G. Knepley PetscCall(DMCreateLabel(*dm, lname)); 74569f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(bdm, lname, &label)); 74579f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(*dm, lname, &labelNew)); 74589f6c5813SMatthew G. Knepley PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL)); 74599f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetLabel(labelNew, label)); 74609f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetTransform(labelNew, tr)); 74619f6c5813SMatthew G. Knepley PetscCall(DMLabelSetUp(labelNew)); 74629f6c5813SMatthew G. Knepley } 74633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74649f6c5813SMatthew G. Knepley } 7465