1552f7358SJed Brown #define PETSCDM_DLL 2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3cc4c1da9SBarry Smith #include <petsc/private/hashseti.h> 40c312b8eSJed Brown #include <petscsf.h> 5cc4c1da9SBarry Smith #include <petscdmplextransform.h> /*I "petscdmplextransform.h" I*/ 69f6c5813SMatthew G. Knepley #include <petscdmlabelephemeral.h> 7b7f5c055SJed Brown #include <petsc/private/kernels/blockmatmult.h> 8b7f5c055SJed Brown #include <petsc/private/kernels/blockinvert.h> 9552f7358SJed Brown 10d0812dedSMatthew G. Knepley #ifdef PETSC_HAVE_UNISTD_H 11d0812dedSMatthew G. Knepley #include <unistd.h> 12d0812dedSMatthew G. Knepley #endif 13d0812dedSMatthew G. Knepley #include <errno.h> 14d0812dedSMatthew G. Knepley 15708be2fdSJed Brown PetscLogEvent DMPLEX_CreateFromFile, DMPLEX_CreateFromOptions, DMPLEX_BuildFromCellList, DMPLEX_BuildCoordinatesFromCellList; 1658cd63d5SVaclav Hapla 179318fe57SMatthew G. Knepley /* External function declarations here */ 189318fe57SMatthew G. Knepley static PetscErrorCode DMInitialize_Plex(DM dm); 199318fe57SMatthew G. Knepley 205552b385SBrandon PETSC_EXTERN PetscErrorCode DMPlexCheckEGADS_Private(DM dm) 215552b385SBrandon { 225552b385SBrandon PetscObject modelObj; 235552b385SBrandon 245552b385SBrandon PetscFunctionBegin; 255552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", &modelObj)); 265552b385SBrandon PetscCheck(modelObj, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Input DM must have attached EGADS Geometry Model"); 275552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 285552b385SBrandon } 295552b385SBrandon 305552b385SBrandon static PetscErrorCode DMPlexCopyContext_Private(DM dmin, const char name[], DM dmout) 315552b385SBrandon { 325552b385SBrandon PetscObject obj; 335552b385SBrandon 345552b385SBrandon PetscFunctionBegin; 355552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmin, name, &obj)); 365552b385SBrandon if (obj) PetscCall(PetscObjectCompose((PetscObject)dmout, name, obj)); 375552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 385552b385SBrandon } 395552b385SBrandon 405552b385SBrandon static PetscErrorCode DMPlexSwapContext_Private(DM dmA, const char name[], DM dmB) 415552b385SBrandon { 425552b385SBrandon PetscObject objA, objB; 435552b385SBrandon 445552b385SBrandon PetscFunctionBegin; 455552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmA, name, &objA)); 465552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dmB, name, &objB)); 475552b385SBrandon PetscCall(PetscObjectReference(objA)); 485552b385SBrandon PetscCall(PetscObjectReference(objB)); 495552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dmA, name, objB)); 505552b385SBrandon PetscCall(PetscObjectCompose((PetscObject)dmB, name, objA)); 515552b385SBrandon PetscCall(PetscObjectDereference(objA)); 525552b385SBrandon PetscCall(PetscObjectDereference(objB)); 535552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 545552b385SBrandon } 555552b385SBrandon 565552b385SBrandon PetscErrorCode DMPlexCopyEGADSInfo_Internal(DM dmin, DM dmout) 575552b385SBrandon { 585552b385SBrandon PetscFunctionBegin; 595552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Model", dmout)); 605552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADS Context", dmout)); 615552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Model", dmout)); 625552b385SBrandon PetscCall(DMPlexCopyContext_Private(dmin, "EGADSlite Context", dmout)); 635552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 645552b385SBrandon } 655552b385SBrandon 665552b385SBrandon static PetscErrorCode DMPlexSwapEGADSInfo_Private(DM dmA, DM dmB) 675552b385SBrandon { 685552b385SBrandon PetscFunctionBegin; 695552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Model", dmB)); 705552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADS Context", dmB)); 715552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Model", dmB)); 725552b385SBrandon PetscCall(DMPlexSwapContext_Private(dmA, "EGADSlite Context", dmB)); 735552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 745552b385SBrandon } 755552b385SBrandon 76e600fa54SMatthew G. Knepley /* This copies internal things in the Plex structure that we generally want when making a new, related Plex */ 77d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCopy_Internal(DM dmin, PetscBool copyPeriodicity, PetscBool copyOverlap, DM dmout) 78d71ae5a4SJacob Faibussowitsch { 794fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 8012a88998SMatthew G. Knepley VecType vecType; 8112a88998SMatthew G. Knepley MatType matType; 82129f447cSJames Wright PetscBool dist, useCeed, balance_partition; 83adc21957SMatthew G. Knepley DMReorderDefaultFlag reorder; 84e600fa54SMatthew G. Knepley 85e600fa54SMatthew G. Knepley PetscFunctionBegin; 86835f2295SStefano Zampini if (dmin == dmout) PetscFunctionReturn(PETSC_SUCCESS); 8712a88998SMatthew G. Knepley PetscCall(DMGetVecType(dmin, &vecType)); 8812a88998SMatthew G. Knepley PetscCall(DMSetVecType(dmout, vecType)); 8912a88998SMatthew G. Knepley PetscCall(DMGetMatType(dmin, &matType)); 9012a88998SMatthew G. Knepley PetscCall(DMSetMatType(dmout, matType)); 91e600fa54SMatthew G. Knepley if (copyPeriodicity) { 924fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmin, &maxCell, &Lstart, &L)); 934fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dmout, maxCell, Lstart, L)); 943d0e8ed9SDavid Salac PetscCall(DMLocalizeCoordinates(dmout)); 95e600fa54SMatthew G. Knepley } 969566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dmin, &dist)); 979566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dmout, dist)); 986bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dmin, &reorder)); 996bc1bd01Sksagiyam PetscCall(DMPlexReorderSetDefault(dmout, reorder)); 1005962854dSMatthew G. Knepley PetscCall(DMPlexGetUseCeed(dmin, &useCeed)); 1015962854dSMatthew G. Knepley PetscCall(DMPlexSetUseCeed(dmout, useCeed)); 102129f447cSJames Wright PetscCall(DMPlexGetPartitionBalance(dmin, &balance_partition)); 103129f447cSJames Wright PetscCall(DMPlexSetPartitionBalance(dmout, balance_partition)); 104e600fa54SMatthew G. Knepley ((DM_Plex *)dmout->data)->useHashLocation = ((DM_Plex *)dmin->data)->useHashLocation; 1055962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printSetValues = ((DM_Plex *)dmin->data)->printSetValues; 1065962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printFEM = ((DM_Plex *)dmin->data)->printFEM; 1075962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printFVM = ((DM_Plex *)dmin->data)->printFVM; 1085962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printL2 = ((DM_Plex *)dmin->data)->printL2; 1095962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printLocate = ((DM_Plex *)dmin->data)->printLocate; 110a77a5016SMatthew G. Knepley ((DM_Plex *)dmout->data)->printProject = ((DM_Plex *)dmin->data)->printProject; 1115962854dSMatthew G. Knepley ((DM_Plex *)dmout->data)->printTol = ((DM_Plex *)dmin->data)->printTol; 1121baa6e33SBarry Smith if (copyOverlap) PetscCall(DMPlexSetOverlap_Plex(dmout, dmin, 0)); 1135552b385SBrandon PetscCall(DMPlexCopyEGADSInfo_Internal(dmin, dmout)); 1143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 115e600fa54SMatthew G. Knepley } 116e600fa54SMatthew G. Knepley 1179318fe57SMatthew G. Knepley /* Replace dm with the contents of ndm, and then destroy ndm 1189318fe57SMatthew G. Knepley - Share the DM_Plex structure 1199318fe57SMatthew G. Knepley - Share the coordinates 1209318fe57SMatthew G. Knepley - Share the SF 1219318fe57SMatthew G. Knepley */ 122d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexReplace_Internal(DM dm, DM *ndm) 123d71ae5a4SJacob Faibussowitsch { 1249318fe57SMatthew G. Knepley PetscSF sf; 1259318fe57SMatthew G. Knepley DM dmNew = *ndm, coordDM, coarseDM; 1269318fe57SMatthew G. Knepley Vec coords; 1272192575eSBarry Smith PetscPointFn *coordFunc; 1284fb89dddSMatthew G. Knepley const PetscReal *maxCell, *Lstart, *L; 1299318fe57SMatthew G. Knepley PetscInt dim, cdim; 130e535cce4SJames Wright PetscBool use_natural; 1319318fe57SMatthew G. Knepley 1329318fe57SMatthew G. Knepley PetscFunctionBegin; 1339318fe57SMatthew G. Knepley if (dm == dmNew) { 1349566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 1353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1369318fe57SMatthew G. Knepley } 1379318fe57SMatthew G. Knepley dm->setupcalled = dmNew->setupcalled; 138d0812dedSMatthew G. Knepley if (!dm->hdr.name) { 139d0812dedSMatthew G. Knepley const char *name; 140d0812dedSMatthew G. Knepley 141d0812dedSMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)*ndm, &name)); 142d0812dedSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, name)); 143d0812dedSMatthew G. Knepley } 1443674be70SMatthew G. Knepley { 1453674be70SMatthew G. Knepley PetscInt ndim; 1463674be70SMatthew G. Knepley 1473674be70SMatthew G. Knepley // If topological dimensions are the same, we retain the old coordinate map, 1483674be70SMatthew G. Knepley // otherwise we overwrite with the new one 1493674be70SMatthew G. Knepley PetscCall(DMGetDimension(dm, &dim)); 1503674be70SMatthew G. Knepley PetscCall(DMGetDimension(dmNew, &ndim)); 1513674be70SMatthew G. Knepley PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc)); 1523674be70SMatthew G. Knepley if (dim == ndim) PetscCall(DMPlexSetCoordinateMap(dmNew, coordFunc)); 1533674be70SMatthew G. Knepley } 1549566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dmNew, &dim)); 1559566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 1569566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dmNew, &cdim)); 1579566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 1589566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmNew, &sf)); 1599566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sf)); 1609566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmNew, &coordDM)); 1619566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmNew, &coords)); 1629566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dm, coordDM)); 1639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coords)); 1646858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmNew, &coordDM)); 1656858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmNew, &coords)); 1666858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dm, coordDM)); 1676858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, coords)); 1689318fe57SMatthew G. Knepley /* Do not want to create the coordinate field if it does not already exist, so do not call DMGetCoordinateField() */ 1696858538eSMatthew G. Knepley PetscCall(DMFieldDestroy(&dm->coordinates[0].field)); 1706858538eSMatthew G. Knepley dm->coordinates[0].field = dmNew->coordinates[0].field; 1714fb89dddSMatthew G. Knepley PetscCall(DMGetPeriodicity(dmNew, &maxCell, &Lstart, &L)); 1724fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, Lstart, L)); 173e535cce4SJames Wright PetscCall(DMGetNaturalSF(dmNew, &sf)); 174e535cce4SJames Wright PetscCall(DMSetNaturalSF(dm, sf)); 175e535cce4SJames Wright PetscCall(DMGetUseNatural(dmNew, &use_natural)); 176e535cce4SJames Wright PetscCall(DMSetUseNatural(dm, use_natural)); 1779566063dSJacob Faibussowitsch PetscCall(DMDestroy_Plex(dm)); 1789566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 1799318fe57SMatthew G. Knepley dm->data = dmNew->data; 1809318fe57SMatthew G. Knepley ((DM_Plex *)dmNew->data)->refct++; 1811fca310dSJames Wright { 1821fca310dSJames Wright PetscInt num_face_sfs; 1831fca310dSJames Wright const PetscSF *sfs; 1841fca310dSJames Wright PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &sfs)); 1851fca310dSJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(dm, num_face_sfs, (PetscSF *)sfs)); // for the compose function effect on dm 1861fca310dSJames Wright } 1879566063dSJacob Faibussowitsch PetscCall(DMDestroyLabelLinkList_Internal(dm)); 1889566063dSJacob Faibussowitsch PetscCall(DMCopyLabels(dmNew, dm, PETSC_OWN_POINTER, PETSC_TRUE, DM_COPY_LABELS_FAIL)); 1899566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dmNew, &coarseDM)); 1909566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, coarseDM)); 1915552b385SBrandon PetscCall(DMPlexCopyEGADSInfo_Internal(dmNew, dm)); 1929566063dSJacob Faibussowitsch PetscCall(DMDestroy(ndm)); 1933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1949318fe57SMatthew G. Knepley } 1959318fe57SMatthew G. Knepley 1969318fe57SMatthew G. Knepley /* Swap dm with the contents of dmNew 1979318fe57SMatthew G. Knepley - Swap the DM_Plex structure 1989318fe57SMatthew G. Knepley - Swap the coordinates 1999318fe57SMatthew G. Knepley - Swap the point PetscSF 2009318fe57SMatthew G. Knepley */ 201d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexSwap_Static(DM dmA, DM dmB) 202d71ae5a4SJacob Faibussowitsch { 2039318fe57SMatthew G. Knepley DM coordDMA, coordDMB; 2049318fe57SMatthew G. Knepley Vec coordsA, coordsB; 2059318fe57SMatthew G. Knepley PetscSF sfA, sfB; 2069318fe57SMatthew G. Knepley DMField fieldTmp; 2079318fe57SMatthew G. Knepley void *tmp; 2089318fe57SMatthew G. Knepley DMLabelLink listTmp; 2099318fe57SMatthew G. Knepley DMLabel depthTmp; 2109318fe57SMatthew G. Knepley PetscInt tmpI; 2119318fe57SMatthew G. Knepley 2129318fe57SMatthew G. Knepley PetscFunctionBegin; 2133ba16761SJacob Faibussowitsch if (dmA == dmB) PetscFunctionReturn(PETSC_SUCCESS); 2149566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmA, &sfA)); 2159566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dmB, &sfB)); 2169566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)sfA)); 2179566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmA, sfB)); 2189566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dmB, sfA)); 2199566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)sfA)); 2209318fe57SMatthew G. Knepley 2219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmA, &coordDMA)); 2229566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dmB, &coordDMB)); 2239566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordDMA)); 2249566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmA, coordDMB)); 2259566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDM(dmB, coordDMA)); 2269566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 2279318fe57SMatthew G. Knepley 2289566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmA, &coordsA)); 2299566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dmB, &coordsB)); 2309566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coordsA)); 2319566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmA, coordsB)); 2329566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dmB, coordsA)); 2339566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coordsA)); 2349318fe57SMatthew G. Knepley 2356858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmA, &coordDMA)); 2366858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinateDM(dmB, &coordDMB)); 2376858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordDMA)); 2386858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmA, coordDMB)); 2396858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinateDM(dmB, coordDMA)); 2406858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordDMA)); 2416858538eSMatthew G. Knepley 2426858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmA, &coordsA)); 2436858538eSMatthew G. Knepley PetscCall(DMGetCellCoordinatesLocal(dmB, &coordsB)); 2446858538eSMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)coordsA)); 2456858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmA, coordsB)); 2466858538eSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dmB, coordsA)); 2476858538eSMatthew G. Knepley PetscCall(PetscObjectDereference((PetscObject)coordsA)); 2486858538eSMatthew G. Knepley 2495552b385SBrandon PetscCall(DMPlexSwapEGADSInfo_Private(dmA, dmB)); 2505552b385SBrandon 2516858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[0].field; 2526858538eSMatthew G. Knepley dmA->coordinates[0].field = dmB->coordinates[0].field; 2536858538eSMatthew G. Knepley dmB->coordinates[0].field = fieldTmp; 2546858538eSMatthew G. Knepley fieldTmp = dmA->coordinates[1].field; 2556858538eSMatthew G. Knepley dmA->coordinates[1].field = dmB->coordinates[1].field; 2566858538eSMatthew G. Knepley dmB->coordinates[1].field = fieldTmp; 2579318fe57SMatthew G. Knepley tmp = dmA->data; 2589318fe57SMatthew G. Knepley dmA->data = dmB->data; 2599318fe57SMatthew G. Knepley dmB->data = tmp; 2609318fe57SMatthew G. Knepley listTmp = dmA->labels; 2619318fe57SMatthew G. Knepley dmA->labels = dmB->labels; 2629318fe57SMatthew G. Knepley dmB->labels = listTmp; 2639318fe57SMatthew G. Knepley depthTmp = dmA->depthLabel; 2649318fe57SMatthew G. Knepley dmA->depthLabel = dmB->depthLabel; 2659318fe57SMatthew G. Knepley dmB->depthLabel = depthTmp; 2669318fe57SMatthew G. Knepley depthTmp = dmA->celltypeLabel; 2679318fe57SMatthew G. Knepley dmA->celltypeLabel = dmB->celltypeLabel; 2689318fe57SMatthew G. Knepley dmB->celltypeLabel = depthTmp; 2699318fe57SMatthew G. Knepley tmpI = dmA->levelup; 2709318fe57SMatthew G. Knepley dmA->levelup = dmB->levelup; 2719318fe57SMatthew G. Knepley dmB->levelup = tmpI; 2723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2739318fe57SMatthew G. Knepley } 2749318fe57SMatthew G. Knepley 2753431e603SJed Brown PetscErrorCode DMPlexInterpolateInPlace_Internal(DM dm) 276d71ae5a4SJacob Faibussowitsch { 2779318fe57SMatthew G. Knepley DM idm; 2789318fe57SMatthew G. Knepley 2799318fe57SMatthew G. Knepley PetscFunctionBegin; 2809566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 2819566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, idm)); 28269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 2833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2849318fe57SMatthew G. Knepley } 2859318fe57SMatthew G. Knepley 2869318fe57SMatthew G. Knepley /*@C 2879318fe57SMatthew G. Knepley DMPlexCreateCoordinateSpace - Creates a finite element space for the coordinates 2889318fe57SMatthew G. Knepley 28920f4b53cSBarry Smith Collective 2909318fe57SMatthew G. Knepley 2919318fe57SMatthew G. Knepley Input Parameters: 29260225df5SJacob Faibussowitsch + dm - The `DMPLEX` 29320f4b53cSBarry Smith . degree - The degree of the finite element or `PETSC_DECIDE` 2944c712d99Sksagiyam . localized - Flag to create a localized (DG) coordinate space 295e65c294aSksagiyam - project - Flag to project current coordinates into the space 2969318fe57SMatthew G. Knepley 2979318fe57SMatthew G. Knepley Level: advanced 2989318fe57SMatthew G. Knepley 299e65c294aSksagiyam .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPointFn`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()`, `DMPlexSetCoordinateMap()` 3009318fe57SMatthew G. Knepley @*/ 301e65c294aSksagiyam PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscBool localized, PetscBool project) 302d71ae5a4SJacob Faibussowitsch { 303e44f6aebSMatthew G. Knepley PetscFE fe = NULL; 3049318fe57SMatthew G. Knepley DM cdm; 305ac9d17c7SMatthew G. Knepley PetscInt dim, cdim, dE, qorder, height; 3069318fe57SMatthew G. Knepley 307e44f6aebSMatthew G. Knepley PetscFunctionBegin; 3089566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 309ac9d17c7SMatthew G. Knepley cdim = dim; 3109566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 3119318fe57SMatthew G. Knepley qorder = degree; 312e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 313d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)cdm); 314dc431b0cSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0)); 315ac9d17c7SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_coordinate_dim", "Set the coordinate dimension", "DMPlexCreateCoordinateSpace", cdim, &cdim, NULL, dim)); 316d0609cedSBarry Smith PetscOptionsEnd(); 3171df12153SMatthew G. Knepley PetscCall(DMPlexGetVTKCellHeight(dm, &height)); 318ac9d17c7SMatthew G. Knepley if (cdim > dim) { 319ac9d17c7SMatthew G. Knepley DM cdm; 320ac9d17c7SMatthew G. Knepley PetscSection cs, csNew; 321ac9d17c7SMatthew G. Knepley Vec coordinates, coordinatesNew; 322ac9d17c7SMatthew G. Knepley VecType vectype; 323ac9d17c7SMatthew G. Knepley IS idx; 324ac9d17c7SMatthew G. Knepley PetscInt *indices; 325ac9d17c7SMatthew G. Knepley PetscInt bs, n; 326ac9d17c7SMatthew G. Knepley 327ac9d17c7SMatthew G. Knepley // Recreate coordinate section 328ac9d17c7SMatthew G. Knepley { 329ac9d17c7SMatthew G. Knepley const char *fieldName = NULL, *compName = NULL; 330ac9d17c7SMatthew G. Knepley PetscInt Nc, pStart, pEnd; 331ac9d17c7SMatthew G. Knepley 332ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 333ac9d17c7SMatthew G. Knepley PetscCall(DMGetLocalSection(cdm, &cs)); 334ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cs), &csNew)); 335ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetNumFields(csNew, 1)); 336ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetFieldName(cs, 0, &fieldName)); 337ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldName(csNew, 0, fieldName)); 338ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetFieldComponents(cs, 0, &Nc)); 339ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(csNew, 0, cdim)); 340ac9d17c7SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 341ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetComponentName(cs, 0, c, &compName)); 342ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetComponentName(csNew, 0, c, compName)); 343ac9d17c7SMatthew G. Knepley } 344ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetChart(cs, &pStart, &pEnd)); 345ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetChart(csNew, pStart, pEnd)); 346ac9d17c7SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 347530e699aSMatthew G. Knepley PetscInt dof; 348530e699aSMatthew G. Knepley 349530e699aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cs, p, &dof)); 350530e699aSMatthew G. Knepley if (dof) { 351ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetDof(csNew, p, cdim)); 352ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csNew, p, 0, cdim)); 353ac9d17c7SMatthew G. Knepley } 354530e699aSMatthew G. Knepley } 355ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetUp(csNew)); 356ac9d17c7SMatthew G. Knepley } 357ac9d17c7SMatthew G. Knepley PetscCall(DMSetLocalSection(cdm, csNew)); 358ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionDestroy(&csNew)); 359530e699aSMatthew G. Knepley // Reset coordinate dimension for coordinate DM 360530e699aSMatthew G. Knepley PetscCall(DMSetCoordinateDim(cdm, cdim)); 361530e699aSMatthew G. Knepley PetscCall(DMSetCoordinateField(cdm, NULL)); 362ac9d17c7SMatthew G. Knepley // Inject coordinates into higher dimension 363ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 364ac9d17c7SMatthew G. Knepley PetscCall(VecGetBlockSize(coordinates, &bs)); 365ac9d17c7SMatthew G. Knepley PetscCheck(bs == dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension"); 366ac9d17c7SMatthew G. Knepley PetscCall(VecCreate(PetscObjectComm((PetscObject)coordinates), &coordinatesNew)); 367ac9d17c7SMatthew G. Knepley PetscCall(VecGetType(coordinates, &vectype)); 368ac9d17c7SMatthew G. Knepley PetscCall(VecSetType(coordinatesNew, vectype)); 369ac9d17c7SMatthew G. Knepley PetscCall(VecGetLocalSize(coordinates, &n)); 370ac9d17c7SMatthew G. Knepley PetscCheck(!(n % bs), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension"); 371ac9d17c7SMatthew G. Knepley n /= bs; 372ac9d17c7SMatthew G. Knepley PetscCall(VecSetSizes(coordinatesNew, n * cdim, PETSC_DETERMINE)); 373ac9d17c7SMatthew G. Knepley PetscCall(VecSetUp(coordinatesNew)); 374ac9d17c7SMatthew G. Knepley PetscCall(PetscMalloc1(n * bs, &indices)); 375ac9d17c7SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) 376ac9d17c7SMatthew G. Knepley for (PetscInt b = 0; b < bs; ++b) indices[i * bs + b] = i * cdim + b; 377ac9d17c7SMatthew G. Knepley PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n * bs, indices, PETSC_OWN_POINTER, &idx)); 378ac9d17c7SMatthew G. Knepley PetscCall(VecISCopy(coordinatesNew, idx, SCATTER_FORWARD, coordinates)); 379ac9d17c7SMatthew G. Knepley PetscCall(ISDestroy(&idx)); 380ac9d17c7SMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinatesNew)); 381ac9d17c7SMatthew G. Knepley PetscCall(VecDestroy(&coordinatesNew)); 382ac9d17c7SMatthew G. Knepley PetscCall(DMSetCoordinateDim(dm, cdim)); 383ac9d17c7SMatthew G. Knepley { 384ac9d17c7SMatthew G. Knepley PetscInt gn; 385ac9d17c7SMatthew G. Knepley 386ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinates(dm, &coordinatesNew)); 387ac9d17c7SMatthew G. Knepley PetscCall(VecGetLocalSize(coordinatesNew, &gn)); 388ac9d17c7SMatthew 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); 389ac9d17c7SMatthew G. Knepley } 390ac9d17c7SMatthew G. Knepley dE = cdim; 391530e699aSMatthew G. Knepley project = PETSC_FALSE; 392ac9d17c7SMatthew G. Knepley } 393e44f6aebSMatthew G. Knepley if (degree >= 0) { 394e44f6aebSMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 395e44f6aebSMatthew G. Knepley PetscInt cStart, cEnd, gct; 396dc431b0cSMatthew G. Knepley 3971df12153SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd)); 398dc431b0cSMatthew G. Knepley if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 399e44f6aebSMatthew G. Knepley gct = (PetscInt)ct; 400462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &gct, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm))); 401e44f6aebSMatthew G. Knepley ct = (DMPolytopeType)gct; 402e44f6aebSMatthew G. Knepley // Work around current bug in PetscDualSpaceSetUp_Lagrange() 403e44f6aebSMatthew G. Knepley // Can be seen in plex_tutorials-ex10_1 4044c712d99Sksagiyam if (ct != DM_POLYTOPE_SEG_PRISM_TENSOR && ct != DM_POLYTOPE_TRI_PRISM_TENSOR && ct != DM_POLYTOPE_QUAD_PRISM_TENSOR) { 4054c712d99Sksagiyam PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe)); 4064c712d99Sksagiyam if (localized) { 4074c712d99Sksagiyam PetscFE dgfe = NULL; 4084c712d99Sksagiyam 4094c712d99Sksagiyam PetscCall(PetscFECreateBrokenElement(fe, &dgfe)); 4104c712d99Sksagiyam PetscCall(PetscFEDestroy(&fe)); 4114c712d99Sksagiyam fe = dgfe; 4124f9ab2b4SJed Brown } 4134c712d99Sksagiyam } 4144c712d99Sksagiyam } 4154c712d99Sksagiyam PetscCall(DMSetCoordinateDisc(dm, fe, localized, project)); 4169566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 4173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4189318fe57SMatthew G. Knepley } 4199318fe57SMatthew G. Knepley 4201df5d5c5SMatthew G. Knepley /*@ 4211df5d5c5SMatthew G. Knepley DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 4221df5d5c5SMatthew G. Knepley 423d083f849SBarry Smith Collective 4241df5d5c5SMatthew G. Knepley 4251df5d5c5SMatthew G. Knepley Input Parameters: 426a1cb98faSBarry Smith + comm - The communicator for the `DM` object 4271df5d5c5SMatthew G. Knepley . dim - The spatial dimension 4281df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells 4291df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces) 4301df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 4311df5d5c5SMatthew G. Knepley 4321df5d5c5SMatthew G. Knepley Output Parameter: 43360225df5SJacob Faibussowitsch . newdm - The `DM` object 4341df5d5c5SMatthew G. Knepley 4351df5d5c5SMatthew G. Knepley Level: beginner 4361df5d5c5SMatthew G. Knepley 4371cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()` 4381df5d5c5SMatthew G. Knepley @*/ 439d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) 440d71ae5a4SJacob Faibussowitsch { 4411df5d5c5SMatthew G. Knepley DM dm; 4421df5d5c5SMatthew G. Knepley PetscMPIInt rank; 4431df5d5c5SMatthew G. Knepley 4441df5d5c5SMatthew G. Knepley PetscFunctionBegin; 4459566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &dm)); 4469566063dSJacob Faibussowitsch PetscCall(DMSetType(dm, DMPLEX)); 4479566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 44846139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 4499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 450ce78fa2fSMatthew G. Knepley switch (dim) { 451ce78fa2fSMatthew G. Knepley case 2: 4529566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular")); 4539566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral")); 454ce78fa2fSMatthew G. Knepley break; 455ce78fa2fSMatthew G. Knepley case 3: 4569566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral")); 4579566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral")); 458ce78fa2fSMatthew G. Knepley break; 459d71ae5a4SJacob Faibussowitsch default: 460d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 461ce78fa2fSMatthew G. Knepley } 4621df5d5c5SMatthew G. Knepley if (rank) { 4631df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {0, 0}; 4649566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL)); 4651df5d5c5SMatthew G. Knepley } else { 4661df5d5c5SMatthew G. Knepley switch (dim) { 4671df5d5c5SMatthew G. Knepley case 2: 4681df5d5c5SMatthew G. Knepley if (simplex) { 4691df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {4, 2}; 4701df5d5c5SMatthew G. Knepley PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 4711df5d5c5SMatthew G. Knepley PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 4721df5d5c5SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 4731df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 4741df5d5c5SMatthew G. Knepley 4759566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4761df5d5c5SMatthew G. Knepley } else { 4771df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {6, 2}; 4781df5d5c5SMatthew G. Knepley PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 4791df5d5c5SMatthew G. Knepley PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 4801df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 4811df5d5c5SMatthew 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}; 4821df5d5c5SMatthew G. Knepley 4839566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4841df5d5c5SMatthew G. Knepley } 4851df5d5c5SMatthew G. Knepley break; 4861df5d5c5SMatthew G. Knepley case 3: 4871df5d5c5SMatthew G. Knepley if (simplex) { 4881df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {5, 2}; 4891df5d5c5SMatthew G. Knepley PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 4901df5d5c5SMatthew G. Knepley PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 4911df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 4921df5d5c5SMatthew 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}; 4931df5d5c5SMatthew G. Knepley 4949566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4951df5d5c5SMatthew G. Knepley } else { 4961df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {12, 2}; 4971df5d5c5SMatthew G. Knepley PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 4981df5d5c5SMatthew G. Knepley PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 4991df5d5c5SMatthew G. Knepley PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 5009371c9d4SSatish 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}; 5011df5d5c5SMatthew G. Knepley 5029566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 5031df5d5c5SMatthew G. Knepley } 5041df5d5c5SMatthew G. Knepley break; 505d71ae5a4SJacob Faibussowitsch default: 506d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 5071df5d5c5SMatthew G. Knepley } 5081df5d5c5SMatthew G. Knepley } 50946139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 5101df5d5c5SMatthew G. Knepley *newdm = dm; 5111df5d5c5SMatthew G. Knepley if (refinementLimit > 0.0) { 5121df5d5c5SMatthew G. Knepley DM rdm; 5131df5d5c5SMatthew G. Knepley const char *name; 5141df5d5c5SMatthew G. Knepley 5159566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 5169566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 5179566063dSJacob Faibussowitsch PetscCall(DMRefine(*newdm, comm, &rdm)); 5189566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)*newdm, &name)); 5199566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, name)); 5209566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 5211df5d5c5SMatthew G. Knepley *newdm = rdm; 5221df5d5c5SMatthew G. Knepley } 5231df5d5c5SMatthew G. Knepley if (interpolate) { 5245fd9971aSMatthew G. Knepley DM idm; 5251df5d5c5SMatthew G. Knepley 5269566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*newdm, &idm)); 5279566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 5281df5d5c5SMatthew G. Knepley *newdm = idm; 5291df5d5c5SMatthew G. Knepley } 5303ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5311df5d5c5SMatthew G. Knepley } 5321df5d5c5SMatthew G. Knepley 533d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 534d71ae5a4SJacob Faibussowitsch { 5359318fe57SMatthew G. Knepley const PetscInt numVertices = 2; 5369318fe57SMatthew G. Knepley PetscInt markerRight = 1; 5379318fe57SMatthew G. Knepley PetscInt markerLeft = 1; 5389318fe57SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 5399318fe57SMatthew G. Knepley Vec coordinates; 5409318fe57SMatthew G. Knepley PetscSection coordSection; 5419318fe57SMatthew G. Knepley PetscScalar *coords; 5429318fe57SMatthew G. Knepley PetscInt coordSize; 5439318fe57SMatthew G. Knepley PetscMPIInt rank; 5449318fe57SMatthew G. Knepley PetscInt cdim = 1, v; 545552f7358SJed Brown 5469318fe57SMatthew G. Knepley PetscFunctionBegin; 5479566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 5489318fe57SMatthew G. Knepley if (markerSeparate) { 5499318fe57SMatthew G. Knepley markerRight = 2; 5509318fe57SMatthew G. Knepley markerLeft = 1; 5519318fe57SMatthew G. Knepley } 5529566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 553c5853193SPierre Jolivet if (rank == 0) { 5549566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numVertices)); 5559566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 5569566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft)); 5579566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight)); 5589318fe57SMatthew G. Knepley } 5599566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 5609566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 5619318fe57SMatthew G. Knepley /* Build coordinates */ 5629566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 5639566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 5649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 5659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, 0, numVertices)); 5669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 5679318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 5689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 5699566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 5709318fe57SMatthew G. Knepley } 5719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 5729566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 5739566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 5749566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 5759566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 5769566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 5779566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 5789566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5799318fe57SMatthew G. Knepley coords[0] = lower[0]; 5809318fe57SMatthew G. Knepley coords[1] = upper[0]; 5819566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 5829566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 5839566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 5843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5859318fe57SMatthew G. Knepley } 58626492d91SMatthew G. Knepley 587d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 588d71ae5a4SJacob Faibussowitsch { 5891df21d24SMatthew G. Knepley const PetscInt numVertices = (edges[0] + 1) * (edges[1] + 1); 5901df21d24SMatthew G. Knepley const PetscInt numEdges = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1]; 591552f7358SJed Brown PetscInt markerTop = 1; 592552f7358SJed Brown PetscInt markerBottom = 1; 593552f7358SJed Brown PetscInt markerRight = 1; 594552f7358SJed Brown PetscInt markerLeft = 1; 595552f7358SJed Brown PetscBool markerSeparate = PETSC_FALSE; 596552f7358SJed Brown Vec coordinates; 597552f7358SJed Brown PetscSection coordSection; 598552f7358SJed Brown PetscScalar *coords; 599552f7358SJed Brown PetscInt coordSize; 600552f7358SJed Brown PetscMPIInt rank; 601552f7358SJed Brown PetscInt v, vx, vy; 602552f7358SJed Brown 603552f7358SJed Brown PetscFunctionBegin; 6049566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 605552f7358SJed Brown if (markerSeparate) { 6061df21d24SMatthew G. Knepley markerTop = 3; 6071df21d24SMatthew G. Knepley markerBottom = 1; 6081df21d24SMatthew G. Knepley markerRight = 2; 6091df21d24SMatthew G. Knepley markerLeft = 4; 610552f7358SJed Brown } 6119566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 612dd400576SPatrick Sanan if (rank == 0) { 613552f7358SJed Brown PetscInt e, ex, ey; 614552f7358SJed Brown 6159566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices)); 61648a46eb9SPierre Jolivet for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 6179566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 618552f7358SJed Brown for (vx = 0; vx <= edges[0]; vx++) { 619552f7358SJed Brown for (ey = 0; ey < edges[1]; ey++) { 620552f7358SJed Brown PetscInt edge = vx * edges[1] + ey + edges[0] * (edges[1] + 1); 621552f7358SJed Brown PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges; 622da80777bSKarl Rupp PetscInt cone[2]; 623552f7358SJed Brown 6249371c9d4SSatish Balay cone[0] = vertex; 6259371c9d4SSatish Balay cone[1] = vertex + edges[0] + 1; 6269566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 627552f7358SJed Brown if (vx == edges[0]) { 6289566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 6299566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 630552f7358SJed Brown if (ey == edges[1] - 1) { 6319566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 6329566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 633552f7358SJed Brown } 634552f7358SJed Brown } else if (vx == 0) { 6359566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 6369566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 637552f7358SJed Brown if (ey == edges[1] - 1) { 6389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 6399566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft)); 640552f7358SJed Brown } 641552f7358SJed Brown } 642552f7358SJed Brown } 643552f7358SJed Brown } 644552f7358SJed Brown for (vy = 0; vy <= edges[1]; vy++) { 645552f7358SJed Brown for (ex = 0; ex < edges[0]; ex++) { 646552f7358SJed Brown PetscInt edge = vy * edges[0] + ex; 647552f7358SJed Brown PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges; 648da80777bSKarl Rupp PetscInt cone[2]; 649552f7358SJed Brown 6509371c9d4SSatish Balay cone[0] = vertex; 6519371c9d4SSatish Balay cone[1] = vertex + 1; 6529566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 653552f7358SJed Brown if (vy == edges[1]) { 6549566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 6559566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 656552f7358SJed Brown if (ex == edges[0] - 1) { 6579566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 6589566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 659552f7358SJed Brown } 660552f7358SJed Brown } else if (vy == 0) { 6619566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 6629566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 663552f7358SJed Brown if (ex == edges[0] - 1) { 6649566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 6659566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 666552f7358SJed Brown } 667552f7358SJed Brown } 668552f7358SJed Brown } 669552f7358SJed Brown } 670552f7358SJed Brown } 6719566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 6729566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 673552f7358SJed Brown /* Build coordinates */ 6749566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 2)); 6759566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 6769566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 6779566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 6789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 679552f7358SJed Brown for (v = numEdges; v < numEdges + numVertices; ++v) { 6809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 2)); 6819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 682552f7358SJed Brown } 6839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6849566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 6859566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 6869566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 6879566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 6889566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 2)); 6899566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 6909566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 691552f7358SJed Brown for (vy = 0; vy <= edges[1]; ++vy) { 692552f7358SJed Brown for (vx = 0; vx <= edges[0]; ++vx) { 693552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx; 694552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy; 695552f7358SJed Brown } 696552f7358SJed Brown } 6979566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 6989566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 6999566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 7003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 701552f7358SJed Brown } 702552f7358SJed Brown 703d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 704d71ae5a4SJacob Faibussowitsch { 7059e8abbc3SMichael Lange PetscInt vertices[3], numVertices; 7067b59f5a9SMichael Lange PetscInt numFaces = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2]; 707c2df9bbfSMatthew G. Knepley PetscInt markerTop = 1; 708c2df9bbfSMatthew G. Knepley PetscInt markerBottom = 1; 709c2df9bbfSMatthew G. Knepley PetscInt markerFront = 1; 710c2df9bbfSMatthew G. Knepley PetscInt markerBack = 1; 711c2df9bbfSMatthew G. Knepley PetscInt markerRight = 1; 712c2df9bbfSMatthew G. Knepley PetscInt markerLeft = 1; 713c2df9bbfSMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 714552f7358SJed Brown Vec coordinates; 715552f7358SJed Brown PetscSection coordSection; 716552f7358SJed Brown PetscScalar *coords; 717552f7358SJed Brown PetscInt coordSize; 718552f7358SJed Brown PetscMPIInt rank; 719552f7358SJed Brown PetscInt v, vx, vy, vz; 7207b59f5a9SMichael Lange PetscInt voffset, iface = 0, cone[4]; 721552f7358SJed Brown 722552f7358SJed Brown PetscFunctionBegin; 7231dca8a05SBarry 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"); 7249566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 725c2df9bbfSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 726c2df9bbfSMatthew G. Knepley if (markerSeparate) { 727c2df9bbfSMatthew G. Knepley markerBottom = 1; 728c2df9bbfSMatthew G. Knepley markerTop = 2; 729c2df9bbfSMatthew G. Knepley markerFront = 3; 730c2df9bbfSMatthew G. Knepley markerBack = 4; 731c2df9bbfSMatthew G. Knepley markerRight = 5; 732c2df9bbfSMatthew G. Knepley markerLeft = 6; 733c2df9bbfSMatthew G. Knepley } 7349371c9d4SSatish Balay vertices[0] = faces[0] + 1; 7359371c9d4SSatish Balay vertices[1] = faces[1] + 1; 7369371c9d4SSatish Balay vertices[2] = faces[2] + 1; 7379e8abbc3SMichael Lange numVertices = vertices[0] * vertices[1] * vertices[2]; 738dd400576SPatrick Sanan if (rank == 0) { 739552f7358SJed Brown PetscInt f; 740552f7358SJed Brown 7419566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices)); 74248a46eb9SPierre Jolivet for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 7439566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 7447b59f5a9SMichael Lange 7457b59f5a9SMichael Lange /* Side 0 (Top) */ 7467b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7477b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7487b59f5a9SMichael Lange voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx; 7499371c9d4SSatish Balay cone[0] = voffset; 7509371c9d4SSatish Balay cone[1] = voffset + 1; 7519371c9d4SSatish Balay cone[2] = voffset + vertices[0] + 1; 7529371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 7539566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 754c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop)); 755c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop)); 756c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop)); 757c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop)); 758c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop)); 7597b59f5a9SMichael Lange iface++; 760552f7358SJed Brown } 761552f7358SJed Brown } 7627b59f5a9SMichael Lange 7637b59f5a9SMichael Lange /* Side 1 (Bottom) */ 7647b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7657b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7667b59f5a9SMichael Lange voffset = numFaces + vy * (faces[0] + 1) + vx; 7679371c9d4SSatish Balay cone[0] = voffset + 1; 7689371c9d4SSatish Balay cone[1] = voffset; 7699371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 7709371c9d4SSatish Balay cone[3] = voffset + vertices[0] + 1; 7719566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 772c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom)); 773c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom)); 774c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom)); 775c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom)); 776c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom)); 7777b59f5a9SMichael Lange iface++; 778552f7358SJed Brown } 779552f7358SJed Brown } 7807b59f5a9SMichael Lange 7817b59f5a9SMichael Lange /* Side 2 (Front) */ 7827b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 7837b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7847b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vx; 7859371c9d4SSatish Balay cone[0] = voffset; 7869371c9d4SSatish Balay cone[1] = voffset + 1; 7879371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + 1; 7889371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1]; 7899566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 790c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront)); 791c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront)); 792c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront)); 793c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront)); 794c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront)); 7957b59f5a9SMichael Lange iface++; 796552f7358SJed Brown } 7977b59f5a9SMichael Lange } 7987b59f5a9SMichael Lange 7997b59f5a9SMichael Lange /* Side 3 (Back) */ 8007b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8017b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 8027b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx; 8039371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 8049371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1] + 1; 8059371c9d4SSatish Balay cone[2] = voffset + 1; 8069371c9d4SSatish Balay cone[3] = voffset; 8079566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 808c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack)); 809c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack)); 810c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack)); 811c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack)); 812c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack)); 8137b59f5a9SMichael Lange iface++; 8147b59f5a9SMichael Lange } 8157b59f5a9SMichael Lange } 8167b59f5a9SMichael Lange 8177b59f5a9SMichael Lange /* Side 4 (Left) */ 8187b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8197b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 8207b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0]; 8219371c9d4SSatish Balay cone[0] = voffset; 8229371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1]; 8239371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + vertices[0]; 8249371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 8259566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 826c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft)); 827c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft)); 828c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft)); 829c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft)); 830c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft)); 8317b59f5a9SMichael Lange iface++; 8327b59f5a9SMichael Lange } 8337b59f5a9SMichael Lange } 8347b59f5a9SMichael Lange 8357b59f5a9SMichael Lange /* Side 5 (Right) */ 8367b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8377b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 838aab5bcd8SJed Brown voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0]; 8399371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 8409371c9d4SSatish Balay cone[1] = voffset; 8419371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 8429371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1] + vertices[0]; 8439566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 844c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight)); 845c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight)); 846c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight)); 847c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight)); 848c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight)); 8497b59f5a9SMichael Lange iface++; 8507b59f5a9SMichael Lange } 851552f7358SJed Brown } 852552f7358SJed Brown } 8539566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 8549566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 855552f7358SJed Brown /* Build coordinates */ 8569566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 3)); 8579566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8589566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 8599566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 8609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 861552f7358SJed Brown for (v = numFaces; v < numFaces + numVertices; ++v) { 8629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 3)); 8639566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 864552f7358SJed Brown } 8659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 8669566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 8679566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 8689566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 8699566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 8709566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 3)); 8719566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 8729566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 873552f7358SJed Brown for (vz = 0; vz <= faces[2]; ++vz) { 874552f7358SJed Brown for (vy = 0; vy <= faces[1]; ++vy) { 875552f7358SJed Brown for (vx = 0; vx <= faces[0]; ++vx) { 876552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx; 877552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy; 878552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz; 879552f7358SJed Brown } 880552f7358SJed Brown } 881552f7358SJed Brown } 8829566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 8839566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 8849566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 8853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 886552f7358SJed Brown } 887552f7358SJed Brown 888d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) 889d71ae5a4SJacob Faibussowitsch { 8909318fe57SMatthew G. Knepley PetscFunctionBegin; 8919318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 89246139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 8939566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim - 1)); 8949566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim)); 8959318fe57SMatthew G. Knepley switch (dim) { 896d71ae5a4SJacob Faibussowitsch case 1: 897d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces)); 898d71ae5a4SJacob Faibussowitsch break; 899d71ae5a4SJacob Faibussowitsch case 2: 900d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces)); 901d71ae5a4SJacob Faibussowitsch break; 902d71ae5a4SJacob Faibussowitsch case 3: 903d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces)); 904d71ae5a4SJacob Faibussowitsch break; 905d71ae5a4SJacob Faibussowitsch default: 906d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim); 9079318fe57SMatthew G. Knepley } 90846139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 9099566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 9103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9119318fe57SMatthew G. Knepley } 9129318fe57SMatthew G. Knepley 9139318fe57SMatthew G. Knepley /*@C 9149318fe57SMatthew G. Knepley DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra). 9159318fe57SMatthew G. Knepley 9169318fe57SMatthew G. Knepley Collective 9179318fe57SMatthew G. Knepley 9189318fe57SMatthew G. Knepley Input Parameters: 919a1cb98faSBarry Smith + comm - The communicator for the `DM` object 92020f4b53cSBarry Smith . dim - The spatial dimension of the box, so the resulting mesh is has dimension `dim`-1 92120f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 92220f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 92320f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 9249318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 9259318fe57SMatthew G. Knepley 9269318fe57SMatthew G. Knepley Output Parameter: 927a1cb98faSBarry Smith . dm - The `DM` object 9289318fe57SMatthew G. Knepley 9299318fe57SMatthew G. Knepley Level: beginner 9309318fe57SMatthew G. Knepley 9311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()` 9329318fe57SMatthew G. Knepley @*/ 933d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) 934d71ae5a4SJacob Faibussowitsch { 9359318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 9369318fe57SMatthew G. Knepley PetscReal low[3] = {0, 0, 0}; 9379318fe57SMatthew G. Knepley PetscReal upp[3] = {1, 1, 1}; 9389318fe57SMatthew G. Knepley 9399318fe57SMatthew G. Knepley PetscFunctionBegin; 9409566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 9419566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 9429566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate)); 9433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9449318fe57SMatthew G. Knepley } 9459318fe57SMatthew G. Knepley 946d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd) 947d71ae5a4SJacob Faibussowitsch { 948fdbf62faSLisandro Dalcin PetscInt i, fStart, fEnd, numCells = 0, numVerts = 0; 949fdbf62faSLisandro Dalcin PetscInt numPoints[2], *coneSize, *cones, *coneOrientations; 950fdbf62faSLisandro Dalcin PetscScalar *vertexCoords; 951fdbf62faSLisandro Dalcin PetscReal L, maxCell; 952fdbf62faSLisandro Dalcin PetscBool markerSeparate = PETSC_FALSE; 953fdbf62faSLisandro Dalcin PetscInt markerLeft = 1, faceMarkerLeft = 1; 954fdbf62faSLisandro Dalcin PetscInt markerRight = 1, faceMarkerRight = 2; 955fdbf62faSLisandro Dalcin PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 956fdbf62faSLisandro Dalcin PetscMPIInt rank; 957fdbf62faSLisandro Dalcin 958fdbf62faSLisandro Dalcin PetscFunctionBegin; 9594f572ea9SToby Isaac PetscAssertPointer(dm, 1); 960fdbf62faSLisandro Dalcin 9619566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, 1)); 9629566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 9639566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 964fdbf62faSLisandro Dalcin 9659566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 966dd400576SPatrick Sanan if (rank == 0) numCells = segments; 967dd400576SPatrick Sanan if (rank == 0) numVerts = segments + (wrap ? 0 : 1); 968fdbf62faSLisandro Dalcin 9699371c9d4SSatish Balay numPoints[0] = numVerts; 9709371c9d4SSatish Balay numPoints[1] = numCells; 9719566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords)); 9729566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts)); 973ad540459SPierre Jolivet for (i = 0; i < numCells; ++i) coneSize[i] = 2; 974ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0; 9759371c9d4SSatish Balay for (i = 0; i < numCells; ++i) { 9769371c9d4SSatish Balay cones[2 * i] = numCells + i % numVerts; 9779371c9d4SSatish Balay cones[2 * i + 1] = numCells + (i + 1) % numVerts; 9789371c9d4SSatish Balay } 979ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells); 9809566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 9819566063dSJacob Faibussowitsch PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords)); 982fdbf62faSLisandro Dalcin 9839566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 9849371c9d4SSatish Balay if (markerSeparate) { 9859371c9d4SSatish Balay markerLeft = faceMarkerLeft; 9869371c9d4SSatish Balay markerRight = faceMarkerRight; 9879371c9d4SSatish Balay } 988dd400576SPatrick Sanan if (!wrap && rank == 0) { 9899566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 9909566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft)); 9919566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight)); 9929566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft)); 9939566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight)); 994fdbf62faSLisandro Dalcin } 995fdbf62faSLisandro Dalcin if (wrap) { 996fdbf62faSLisandro Dalcin L = upper - lower; 997fdbf62faSLisandro Dalcin maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments)); 9984fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L)); 999fdbf62faSLisandro Dalcin } 10009566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 10013ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1002fdbf62faSLisandro Dalcin } 1003fdbf62faSLisandro Dalcin 10044054ae39SJames Wright // Creates "Face Sets" label based on the standard box labeling conventions 1005d7d2d1d2SJames Wright static PetscErrorCode DMPlexSetBoxLabel_Internal(DM dm, const DMBoundaryType periodicity[]) 10064054ae39SJames Wright { 10076ff49feeSJames Wright DM cdm; 10086ff49feeSJames Wright PetscSection csection; 10096ff49feeSJames Wright Vec coordinates; 10104054ae39SJames Wright DMLabel label; 10116ff49feeSJames Wright IS faces_is; 10122b4f33d9SJames Wright PetscInt dim, num_face = 0; 10134054ae39SJames Wright const PetscInt *faces; 10144054ae39SJames Wright PetscInt faceMarkerBottom, faceMarkerTop, faceMarkerFront, faceMarkerBack, faceMarkerRight, faceMarkerLeft; 10154054ae39SJames Wright 10164054ae39SJames Wright PetscFunctionBeginUser; 10174054ae39SJames Wright PetscCall(DMGetDimension(dm, &dim)); 1018d7c1f440SPierre 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); 10194054ae39SJames Wright // Get Face Sets label 10204054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 10214054ae39SJames Wright if (label) { 10224054ae39SJames Wright PetscCall(DMLabelReset(label)); 10234054ae39SJames Wright } else { 10244054ae39SJames Wright PetscCall(DMCreateLabel(dm, "Face Sets")); 10254054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 10264054ae39SJames Wright } 10274054ae39SJames Wright PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label)); 10286ff49feeSJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", 1, &faces_is)); 10294054ae39SJames Wright 10304054ae39SJames Wright switch (dim) { 10314054ae39SJames Wright case 2: 10324054ae39SJames Wright faceMarkerTop = 3; 10334054ae39SJames Wright faceMarkerBottom = 1; 10344054ae39SJames Wright faceMarkerRight = 2; 10354054ae39SJames Wright faceMarkerLeft = 4; 10364054ae39SJames Wright break; 10374054ae39SJames Wright case 3: 10384054ae39SJames Wright faceMarkerBottom = 1; 10394054ae39SJames Wright faceMarkerTop = 2; 10404054ae39SJames Wright faceMarkerFront = 3; 10414054ae39SJames Wright faceMarkerBack = 4; 10424054ae39SJames Wright faceMarkerRight = 5; 10434054ae39SJames Wright faceMarkerLeft = 6; 10444054ae39SJames Wright break; 10454054ae39SJames Wright default: 10464054ae39SJames Wright SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 10474054ae39SJames Wright } 10484054ae39SJames Wright 10492b4f33d9SJames Wright if (faces_is) PetscCall(ISGetLocalSize(faces_is, &num_face)); 10502b4f33d9SJames Wright if (faces_is) PetscCall(ISGetIndices(faces_is, &faces)); 10516ff49feeSJames Wright PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 10526ff49feeSJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 10536ff49feeSJames Wright PetscCall(DMGetLocalSection(cdm, &csection)); 10544054ae39SJames Wright for (PetscInt f = 0; f < num_face; ++f) { 10556ff49feeSJames Wright PetscScalar *coords = NULL; 10566ff49feeSJames Wright PetscInt face = faces[f], flip = 1, label_value = -1, coords_size; 10574054ae39SJames Wright 10584054ae39SJames Wright { // Determine if orientation of face is flipped 10594054ae39SJames Wright PetscInt num_cells_support, num_faces, start = -1; 10604054ae39SJames Wright const PetscInt *orients, *cell_faces, *cells; 10614054ae39SJames Wright 10624054ae39SJames Wright PetscCall(DMPlexGetSupport(dm, face, &cells)); 10634054ae39SJames Wright PetscCall(DMPlexGetSupportSize(dm, face, &num_cells_support)); 10644054ae39SJames 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); 10654054ae39SJames Wright PetscCall(DMPlexGetCone(dm, cells[0], &cell_faces)); 10664054ae39SJames Wright PetscCall(DMPlexGetConeSize(dm, cells[0], &num_faces)); 10674054ae39SJames Wright for (PetscInt i = 0; i < num_faces; i++) { 10684054ae39SJames Wright if (cell_faces[i] == face) start = i; 10694054ae39SJames Wright } 10704054ae39SJames Wright PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Could not find face %" PetscInt_FMT " in cone of its support", face); 10714054ae39SJames Wright PetscCall(DMPlexGetConeOrientation(dm, cells[0], &orients)); 10724054ae39SJames Wright if (orients[start] < 0) flip = -1; 10734054ae39SJames Wright } 10744054ae39SJames Wright 10756ff49feeSJames Wright // Cannot use DMPlexComputeCellGeometryFVM() for high-order geometry, so must calculate normal vectors manually 10766ff49feeSJames Wright // Use the vertices (depth 0) of coordinate DM to calculate normal vector 10776ff49feeSJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 10784054ae39SJames Wright switch (dim) { 10794054ae39SJames Wright case 2: { 10806ff49feeSJames Wright PetscScalar vec[2]; 10816ff49feeSJames Wright 10826ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) vec[d] = flip * (PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d])); 10836ff49feeSJames Wright PetscScalar normal[] = {vec[1], -vec[0]}; 10846ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 10856ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 10864054ae39SJames Wright } else { 10876ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerTop : faceMarkerBottom; 10884054ae39SJames Wright } 10894054ae39SJames Wright } break; 10904054ae39SJames Wright case 3: { 10916ff49feeSJames Wright PetscScalar vec1[3], vec2[3], normal[3]; 10926ff49feeSJames Wright 10936ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) { 10946ff49feeSJames Wright vec1[d] = PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]); 10956ff49feeSJames Wright vec2[d] = PetscRealPart(coords[2 * dim + d]) - PetscRealPart(coords[1 * dim + d]); 10966ff49feeSJames Wright } 10976ff49feeSJames Wright 10986ff49feeSJames Wright // Calculate normal vector via cross-product 10996ff49feeSJames Wright normal[0] = flip * ((vec1[1] * vec2[2]) - (vec1[2] * vec2[1])); 11006ff49feeSJames Wright normal[1] = flip * ((vec1[2] * vec2[0]) - (vec1[0] * vec2[2])); 11016ff49feeSJames Wright normal[2] = flip * ((vec1[0] * vec2[1]) - (vec1[1] * vec2[0])); 11026ff49feeSJames Wright 11036ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 11046ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[2])) { 11056ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 11064054ae39SJames Wright } else { 11076ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 11084054ae39SJames Wright } 11094054ae39SJames Wright } else { 11106ff49feeSJames Wright if (PetscAbsScalar(normal[1]) > PetscAbsScalar(normal[2])) { 11116ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerBack : faceMarkerFront; 11124054ae39SJames Wright } else { 11136ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 11144054ae39SJames Wright } 11154054ae39SJames Wright } 11164054ae39SJames Wright } break; 11174054ae39SJames Wright } 11184054ae39SJames Wright 11194054ae39SJames Wright PetscInt previous_label_value; // always 1 due to DMPlexMarkBoundaryFaces call above 11204054ae39SJames Wright PetscCall(DMGetLabelValue(dm, "Face Sets", face, &previous_label_value)); 11214054ae39SJames Wright PetscCall(DMClearLabelValue(dm, "Face Sets", face, previous_label_value)); 11224054ae39SJames Wright PetscCall(DMSetLabelValue(dm, "Face Sets", face, label_value)); 11236ff49feeSJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 11244054ae39SJames Wright } 11252b4f33d9SJames Wright if (faces_is) PetscCall(ISRestoreIndices(faces_is, &faces)); 11266ff49feeSJames Wright PetscCall(ISDestroy(&faces_is)); 1127d7d2d1d2SJames Wright 1128d7d2d1d2SJames Wright // Create Isoperiodic SF from newly-created face labels 1129d7d2d1d2SJames Wright PetscSF periodicsfs[3]; 1130d7d2d1d2SJames Wright PetscInt periodic_sf_index = 0; 1131d7d2d1d2SJames Wright PetscScalar transform[3][4][4] = {{{0.}}}; 1132d7d2d1d2SJames Wright for (PetscInt d = 0; d < dim; d++) { 1133d7d2d1d2SJames Wright IS donor_is, periodic_is; 1134d7d2d1d2SJames Wright const PetscInt *donor_faces = NULL, *periodic_faces = NULL; 1135d7d2d1d2SJames Wright PetscInt num_donor = 0, num_periodic = 0; 1136d7d2d1d2SJames Wright PetscSF centroidsf; 1137d7d2d1d2SJames Wright PetscReal donor_to_periodic_distance; 1138d7d2d1d2SJames Wright const PetscInt face_pairings[2][3][2] = { 1139d7d2d1d2SJames Wright // 2D face pairings, {donor, periodic} 1140d7d2d1d2SJames Wright {{4, 2}, {1, 3}}, 1141d7d2d1d2SJames Wright // 3D face pairings 1142d7d2d1d2SJames Wright {{5, 6}, {3, 4}, {1, 2}} 1143d7d2d1d2SJames Wright }; 1144d7d2d1d2SJames Wright 1145d7d2d1d2SJames Wright if (periodicity[d] != DM_BOUNDARY_PERIODIC) continue; 1146d7d2d1d2SJames Wright { 1147d7d2d1d2SJames Wright // Compute centroidsf, which is the mapping from donor faces to periodic faces 1148d7d2d1d2SJames Wright // Matches the centroid of the faces together, ignoring the periodic direction component (which should not match between donor and periodic face) 1149d7d2d1d2SJames Wright PetscInt coords_size, centroid_comps = dim - 1; 1150d7d2d1d2SJames Wright PetscScalar *coords = NULL; 1151d7d2d1d2SJames Wright PetscReal *donor_centroids, *periodic_centroids; 1152d7d2d1d2SJames 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 1153d7d2d1d2SJames Wright 1154d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][0], &donor_is)); 1155d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][1], &periodic_is)); 1156d7d2d1d2SJames Wright if (donor_is) { 1157d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(donor_is, &num_donor)); 1158d7d2d1d2SJames Wright PetscCall(ISGetIndices(donor_is, &donor_faces)); 1159d7d2d1d2SJames Wright } 1160d7d2d1d2SJames Wright if (periodic_is) { 1161d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(periodic_is, &num_periodic)); 1162d7d2d1d2SJames Wright PetscCall(ISGetIndices(periodic_is, &periodic_faces)); 1163d7d2d1d2SJames Wright } 1164d7d2d1d2SJames Wright PetscCall(PetscCalloc2(num_donor * centroid_comps, &donor_centroids, num_periodic * centroid_comps, &periodic_centroids)); 1165d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_donor; f++) { 1166d7d2d1d2SJames Wright PetscInt face = donor_faces[f], num_coords; 1167d7d2d1d2SJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 1168d7d2d1d2SJames Wright num_coords = coords_size / dim; 1169d7d2d1d2SJames Wright for (PetscInt c = 0; c < num_coords; c++) { 1170d7d2d1d2SJames Wright PetscInt comp_index = 0; 1171d7d2d1d2SJames Wright loc_periodic[0] = PetscRealPart(coords[c * dim + d]); 1172d7d2d1d2SJames Wright for (PetscInt i = 0; i < dim; i++) { 1173d7d2d1d2SJames Wright if (i == d) continue; // Periodic direction not used for centroid calculation 1174d7d2d1d2SJames Wright donor_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords; 1175d7d2d1d2SJames Wright comp_index++; 1176d7d2d1d2SJames Wright } 1177d7d2d1d2SJames Wright } 1178d7d2d1d2SJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 1179d7d2d1d2SJames Wright } 1180d7d2d1d2SJames Wright 1181d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_periodic; f++) { 1182d7d2d1d2SJames Wright PetscInt face = periodic_faces[f], num_coords; 1183d7d2d1d2SJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 1184d7d2d1d2SJames Wright num_coords = coords_size / dim; 1185d7d2d1d2SJames Wright for (PetscInt c = 0; c < num_coords; c++) { 1186d7d2d1d2SJames Wright PetscInt comp_index = 0; 1187d7d2d1d2SJames Wright loc_periodic[1] = PetscRealPart(coords[c * dim + d]); 1188d7d2d1d2SJames Wright for (PetscInt i = 0; i < dim; i++) { 1189d7d2d1d2SJames Wright if (i == d) continue; // Periodic direction not used for centroid calculation 1190d7d2d1d2SJames Wright periodic_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords; 1191d7d2d1d2SJames Wright comp_index++; 1192d7d2d1d2SJames Wright } 1193d7d2d1d2SJames Wright } 1194d7d2d1d2SJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 1195d7d2d1d2SJames Wright } 1196d7d2d1d2SJames Wright PetscCallMPI(MPIU_Allreduce(loc_periodic, loc_periodic_global, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm))); 1197d7d2d1d2SJames Wright donor_to_periodic_distance = loc_periodic_global[1] - loc_periodic_global[0]; 1198d7d2d1d2SJames Wright 1199d7d2d1d2SJames Wright PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), ¢roidsf)); 1200d7d2d1d2SJames Wright PetscCall(PetscSFSetGraphFromCoordinates(centroidsf, num_donor, num_periodic, centroid_comps, 1e-10, donor_centroids, periodic_centroids)); 1201d7d2d1d2SJames Wright PetscCall(PetscSFViewFromOptions(centroidsf, NULL, "-dm_plex_box_label_centroid_sf_view")); 1202d7d2d1d2SJames Wright PetscCall(PetscFree2(donor_centroids, periodic_centroids)); 1203d7d2d1d2SJames Wright } 1204d7d2d1d2SJames Wright 1205d7d2d1d2SJames Wright { // Create Isoperiodic SF using centroidsSF 1206d7d2d1d2SJames Wright PetscInt pStart, pEnd; 1207d7d2d1d2SJames Wright PetscInt *leaf_faces; 1208d7d2d1d2SJames Wright const PetscSFNode *firemote; 1209d7d2d1d2SJames Wright PetscSFNode *isoperiodic_leaves; 1210d7d2d1d2SJames Wright 1211d7d2d1d2SJames Wright PetscCall(PetscMalloc1(num_periodic, &leaf_faces)); 1212d7d2d1d2SJames Wright PetscCall(PetscSFBcastBegin(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE)); 1213d7d2d1d2SJames Wright PetscCall(PetscSFBcastEnd(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE)); 1214d7d2d1d2SJames Wright 1215d7d2d1d2SJames Wright PetscCall(PetscMalloc1(num_periodic, &isoperiodic_leaves)); 1216d7d2d1d2SJames Wright PetscCall(PetscSFGetGraph(centroidsf, NULL, NULL, NULL, &firemote)); 1217d7d2d1d2SJames Wright for (PetscInt l = 0; l < num_periodic; ++l) { 1218d7d2d1d2SJames Wright isoperiodic_leaves[l].index = leaf_faces[l]; 1219d7d2d1d2SJames Wright isoperiodic_leaves[l].rank = firemote[l].rank; 1220d7d2d1d2SJames Wright } 1221d7d2d1d2SJames Wright 1222d7d2d1d2SJames Wright PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 1223d7d2d1d2SJames Wright PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &periodicsfs[periodic_sf_index])); 1224d7d2d1d2SJames Wright PetscCall(PetscSFSetGraph(periodicsfs[periodic_sf_index], pEnd - pStart, num_periodic, (PetscInt *)periodic_faces, PETSC_COPY_VALUES, isoperiodic_leaves, PETSC_OWN_POINTER)); 1225d7d2d1d2SJames Wright PetscCall(PetscSFViewFromOptions(periodicsfs[periodic_sf_index], NULL, "-dm_plex_box_label_periodic_sf_view")); 1226d7d2d1d2SJames Wright PetscCall(PetscFree(leaf_faces)); 1227d7d2d1d2SJames Wright } 1228d7d2d1d2SJames Wright 1229d7d2d1d2SJames Wright transform[periodic_sf_index][0][0] = 1; 1230d7d2d1d2SJames Wright transform[periodic_sf_index][1][1] = 1; 1231d7d2d1d2SJames Wright transform[periodic_sf_index][2][2] = 1; 1232d7d2d1d2SJames Wright transform[periodic_sf_index][3][3] = 1; 1233d7d2d1d2SJames Wright transform[periodic_sf_index][d][3] = donor_to_periodic_distance; 1234d7d2d1d2SJames Wright 1235d7d2d1d2SJames Wright periodic_sf_index++; 1236d7d2d1d2SJames Wright PetscCall(PetscSFDestroy(¢roidsf)); 1237d7d2d1d2SJames Wright if (donor_is) { 1238d7d2d1d2SJames Wright PetscCall(ISRestoreIndices(donor_is, &donor_faces)); 1239d7d2d1d2SJames Wright PetscCall(ISDestroy(&donor_is)); 1240d7d2d1d2SJames Wright } 1241d7d2d1d2SJames Wright if (periodic_is) { 1242d7d2d1d2SJames Wright PetscCall(ISRestoreIndices(periodic_is, &periodic_faces)); 1243d7d2d1d2SJames Wright PetscCall(ISDestroy(&periodic_is)); 1244d7d2d1d2SJames Wright } 1245d7d2d1d2SJames Wright PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][0])); 1246d7d2d1d2SJames Wright PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][1])); 1247d7d2d1d2SJames Wright } 1248d7d2d1d2SJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(dm, periodic_sf_index, periodicsfs)); 1249d7d2d1d2SJames Wright PetscCall(DMPlexSetIsoperiodicFaceTransform(dm, periodic_sf_index, (const PetscScalar *)transform)); 1250d7d2d1d2SJames Wright for (PetscInt p = 0; p < periodic_sf_index; p++) PetscCall(PetscSFDestroy(&periodicsfs[p])); 1251d7d2d1d2SJames Wright 1252d7d2d1d2SJames Wright { // Update coordinate DM with new Face Sets label 1253d7d2d1d2SJames Wright DM cdm; 1254d7d2d1d2SJames Wright DMLabel oldFaceSets, newFaceSets; 1255d7d2d1d2SJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 1256d7d2d1d2SJames Wright PetscCall(DMGetLabel(cdm, "Face Sets", &oldFaceSets)); 1257d7d2d1d2SJames Wright if (oldFaceSets) PetscCall(DMRemoveLabelBySelf(cdm, &oldFaceSets, PETSC_FALSE)); 1258d7d2d1d2SJames Wright PetscCall(DMLabelDuplicate(label, &newFaceSets)); 1259d7d2d1d2SJames Wright PetscCall(DMAddLabel(cdm, newFaceSets)); 1260d7d2d1d2SJames Wright PetscCall(DMLabelDestroy(&newFaceSets)); 1261d7d2d1d2SJames Wright } 12624054ae39SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 12634054ae39SJames Wright } 12644054ae39SJames Wright 1265d698cf03SStefano Zampini static PetscErrorCode DMPlexCreateSquareMesh_Simplex_CrissCross(DM dm, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType bd[]) 1266d698cf03SStefano Zampini { 1267d698cf03SStefano Zampini PetscInt markerTop = 1, faceMarkerTop = 3; 1268d698cf03SStefano Zampini PetscInt markerBottom = 1, faceMarkerBottom = 1; 1269d698cf03SStefano Zampini PetscInt markerRight = 1, faceMarkerRight = 2; 1270d698cf03SStefano Zampini PetscInt markerLeft = 1, faceMarkerLeft = 4; 1271d698cf03SStefano Zampini PetscBool markerSeparate = PETSC_FALSE; 1272d698cf03SStefano Zampini DMBoundaryType bdX = bd[0], bdY = bd[1]; 1273d698cf03SStefano Zampini PetscMPIInt rank; 1274d698cf03SStefano Zampini 1275d698cf03SStefano Zampini PetscFunctionBegin; 1276d698cf03SStefano Zampini PetscCheck(bdX == DM_BOUNDARY_NONE || bdX == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdX]); 1277d698cf03SStefano Zampini PetscCheck(bdY == DM_BOUNDARY_NONE || bdY == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdY]); 1278d698cf03SStefano Zampini PetscCall(DMSetDimension(dm, 2)); 1279d698cf03SStefano Zampini PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1280d698cf03SStefano Zampini PetscCall(DMCreateLabel(dm, "marker")); 1281d698cf03SStefano Zampini PetscCall(DMCreateLabel(dm, "Face Sets")); 1282d698cf03SStefano Zampini PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 1283d698cf03SStefano Zampini if (markerSeparate) { 1284d698cf03SStefano Zampini markerBottom = faceMarkerBottom; 1285d698cf03SStefano Zampini markerTop = faceMarkerTop; 1286d698cf03SStefano Zampini markerRight = faceMarkerRight; 1287d698cf03SStefano Zampini markerLeft = faceMarkerLeft; 1288d698cf03SStefano Zampini } 1289d698cf03SStefano Zampini { 1290d698cf03SStefano Zampini const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 1291d698cf03SStefano Zampini const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 1292d698cf03SStefano Zampini const PetscInt numZEdges = rank == 0 ? 4 * edges[0] * edges[1] : 0; /* Z-edges are the 4 internal edges per cell */ 1293d698cf03SStefano Zampini const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC ? edges[0] : edges[0] + 1) : 0; 1294d698cf03SStefano Zampini const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC ? edges[1] : edges[1] + 1) : 0; 1295d698cf03SStefano Zampini const PetscInt numZVertices = rank == 0 ? edges[0] * edges[1] : 0; 1296d698cf03SStefano Zampini const PetscInt numCells = 4 * numXEdges * numYEdges; 1297d698cf03SStefano Zampini const PetscInt numTotXEdges = numXEdges * numYVertices; 1298d698cf03SStefano Zampini const PetscInt numTotYEdges = numYEdges * numXVertices; 1299d698cf03SStefano Zampini const PetscInt numVertices = numXVertices * numYVertices + numZVertices; 1300d698cf03SStefano Zampini const PetscInt numEdges = numTotXEdges + numTotYEdges + numZEdges; 1301d698cf03SStefano Zampini const PetscInt firstVertex = numCells; 1302d698cf03SStefano Zampini const PetscInt firstXEdge = numCells + numVertices; 1303d698cf03SStefano Zampini const PetscInt firstYEdge = firstXEdge + numTotXEdges; 1304d698cf03SStefano Zampini const PetscInt firstZEdge = firstYEdge + numTotYEdges; 1305d698cf03SStefano Zampini Vec coordinates; 1306d698cf03SStefano Zampini PetscSection coordSection; 1307d698cf03SStefano Zampini PetscScalar *coords; 1308d698cf03SStefano Zampini PetscInt coordSize; 1309d698cf03SStefano Zampini PetscInt v, vx, vy; 1310d698cf03SStefano Zampini PetscInt c, e, ex, ey; 1311d698cf03SStefano Zampini 1312d698cf03SStefano Zampini PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVertices)); 1313d698cf03SStefano Zampini for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 3)); 1314d698cf03SStefano Zampini for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 1315d698cf03SStefano Zampini PetscCall(DMSetUp(dm)); 1316d698cf03SStefano Zampini 1317d698cf03SStefano Zampini /* Build cells and Z-edges */ 1318d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ++ey) { 1319d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ++ex) { 1320d698cf03SStefano Zampini const PetscInt exp1 = (ex + 1) % numXVertices; 1321d698cf03SStefano Zampini const PetscInt eyp1 = (ey + 1) % numYVertices; 1322d698cf03SStefano Zampini const PetscInt ez = firstZEdge + 4 * (ey * numXEdges + ex); 1323d698cf03SStefano Zampini const PetscInt vc = firstVertex + numXVertices * numYVertices + ey * numXEdges + ex; 1324d698cf03SStefano Zampini const PetscInt v0 = firstVertex + ey * numXVertices + ex; 1325d698cf03SStefano Zampini const PetscInt v1 = firstVertex + ey * numXVertices + exp1; 1326d698cf03SStefano Zampini const PetscInt v2 = firstVertex + eyp1 * numXVertices + exp1; 1327d698cf03SStefano Zampini const PetscInt v3 = firstVertex + eyp1 * numXVertices + ex; 1328d698cf03SStefano Zampini const PetscInt e0 = firstXEdge + ey * numXEdges + ex; 1329d698cf03SStefano Zampini const PetscInt e1 = firstYEdge + exp1 * numYEdges + ey; 1330d698cf03SStefano Zampini const PetscInt e2 = firstXEdge + eyp1 * numXEdges + ex; 1331d698cf03SStefano Zampini const PetscInt e3 = firstYEdge + ex * numYEdges + ey; 1332d698cf03SStefano Zampini 1333d698cf03SStefano Zampini const PetscInt cones[] = {ez, e0, ez + 1, ez + 1, e1, ez + 2, ez + 2, e2, ez + 3, ez + 3, e3, ez}; 1334d698cf03SStefano Zampini const PetscInt ornts[] = {-1, 0, 0, -1, 0, 0, -1, -1, 0, -1, -1, 0}; 1335d698cf03SStefano Zampini const PetscInt verts[] = {v0, vc, v1, vc, v2, vc, v3, vc}; 1336d698cf03SStefano Zampini 1337d698cf03SStefano Zampini for (c = 0; c < 4; c++) { 1338d698cf03SStefano Zampini PetscInt cell = 4 * (ey * numXEdges + ex) + c; 1339d698cf03SStefano Zampini PetscInt edge = ez + c; 1340d698cf03SStefano Zampini 1341d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, cell, cones + 3 * c)); 1342d698cf03SStefano Zampini PetscCall(DMPlexSetConeOrientation(dm, cell, ornts + 3 * c)); 1343d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, verts + 2 * c)); 1344d698cf03SStefano Zampini } 1345d698cf03SStefano Zampini } 1346d698cf03SStefano Zampini } 1347d698cf03SStefano Zampini 1348d698cf03SStefano Zampini /* Build Y edges*/ 1349d698cf03SStefano Zampini for (vx = 0; vx < numXVertices; vx++) { 1350d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ey++) { 1351d698cf03SStefano Zampini const PetscInt edge = firstYEdge + vx * numYEdges + ey; 1352d698cf03SStefano Zampini const PetscInt v0 = firstVertex + ey * numXVertices + vx; 1353d698cf03SStefano Zampini const PetscInt v1 = firstVertex + ((ey + 1) % numYVertices) * numXVertices + vx; 1354d698cf03SStefano Zampini const PetscInt cone[] = {v0, v1}; 1355d698cf03SStefano Zampini 1356d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, cone)); 1357d698cf03SStefano Zampini if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 1358d698cf03SStefano Zampini if (vx == numXVertices - 1) { 1359d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 1360d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1361d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1362d698cf03SStefano Zampini if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1363d698cf03SStefano Zampini } else if (vx == 0) { 1364d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 1365d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1366d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1367d698cf03SStefano Zampini if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 1368d698cf03SStefano Zampini } 1369d698cf03SStefano Zampini } 1370d698cf03SStefano Zampini } 1371d698cf03SStefano Zampini } 1372d698cf03SStefano Zampini 1373d698cf03SStefano Zampini /* Build X edges*/ 1374d698cf03SStefano Zampini for (vy = 0; vy < numYVertices; vy++) { 1375d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ex++) { 1376d698cf03SStefano Zampini const PetscInt edge = firstXEdge + vy * numXEdges + ex; 1377d698cf03SStefano Zampini const PetscInt v0 = firstVertex + vy * numXVertices + ex; 1378d698cf03SStefano Zampini const PetscInt v1 = firstVertex + vy * numXVertices + (ex + 1) % numXVertices; 1379d698cf03SStefano Zampini const PetscInt cone[] = {v0, v1}; 1380d698cf03SStefano Zampini 1381d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, cone)); 1382d698cf03SStefano Zampini if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 1383d698cf03SStefano Zampini if (vy == numYVertices - 1) { 1384d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 1385d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1386d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1387d698cf03SStefano Zampini if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1388d698cf03SStefano Zampini } else if (vy == 0) { 1389d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 1390d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1391d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1392d698cf03SStefano Zampini if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 1393d698cf03SStefano Zampini } 1394d698cf03SStefano Zampini } 1395d698cf03SStefano Zampini } 1396d698cf03SStefano Zampini } 1397d698cf03SStefano Zampini 1398d698cf03SStefano Zampini /* Compute support, stratify, and celltype label */ 1399d698cf03SStefano Zampini PetscCall(DMPlexSymmetrize(dm)); 1400d698cf03SStefano Zampini PetscCall(DMPlexStratify(dm)); 1401d698cf03SStefano Zampini PetscCall(DMPlexComputeCellTypes(dm)); 1402d698cf03SStefano Zampini 1403d698cf03SStefano Zampini /* Build coordinates */ 1404d698cf03SStefano Zampini PetscCall(DMGetCoordinateSection(dm, &coordSection)); 1405d698cf03SStefano Zampini PetscCall(PetscSectionSetNumFields(coordSection, 1)); 1406d698cf03SStefano Zampini PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 1407d698cf03SStefano Zampini PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 1408d698cf03SStefano Zampini for (v = firstVertex; v < firstVertex + numVertices; ++v) { 1409d698cf03SStefano Zampini PetscCall(PetscSectionSetDof(coordSection, v, 2)); 1410d698cf03SStefano Zampini PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 1411d698cf03SStefano Zampini } 1412d698cf03SStefano Zampini PetscCall(PetscSectionSetUp(coordSection)); 1413d698cf03SStefano Zampini PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 1414d698cf03SStefano Zampini PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 1415d698cf03SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 1416d698cf03SStefano Zampini PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 1417d698cf03SStefano Zampini PetscCall(VecSetBlockSize(coordinates, 2)); 1418d698cf03SStefano Zampini PetscCall(VecSetType(coordinates, VECSTANDARD)); 1419d698cf03SStefano Zampini PetscCall(VecGetArray(coordinates, &coords)); 1420d698cf03SStefano Zampini for (vy = 0; vy < numYVertices; ++vy) { 1421d698cf03SStefano Zampini for (vx = 0; vx < numXVertices; ++vx) { 1422d698cf03SStefano Zampini coords[2 * (vy * numXVertices + vx) + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 1423d698cf03SStefano Zampini coords[2 * (vy * numXVertices + vx) + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1424d698cf03SStefano Zampini } 1425d698cf03SStefano Zampini } 1426d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ++ey) { 1427d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ++ex) { 1428d698cf03SStefano Zampini const PetscInt c = ey * numXEdges + ex + numYVertices * numXVertices; 1429d698cf03SStefano Zampini 1430d698cf03SStefano Zampini coords[2 * c + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * (ex + 0.5); 1431d698cf03SStefano Zampini coords[2 * c + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * (ey + 0.5); 1432d698cf03SStefano Zampini } 1433d698cf03SStefano Zampini } 1434d698cf03SStefano Zampini PetscCall(VecRestoreArray(coordinates, &coords)); 1435d698cf03SStefano Zampini PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 1436d698cf03SStefano Zampini PetscCall(VecDestroy(&coordinates)); 1437d698cf03SStefano Zampini 1438d698cf03SStefano Zampini /* handle periodic BC */ 1439d698cf03SStefano Zampini if (bdX == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_PERIODIC) { 1440d698cf03SStefano Zampini PetscReal L[2] = {-1., -1.}; 1441d698cf03SStefano Zampini PetscReal maxCell[2] = {-1., -1.}; 1442d698cf03SStefano Zampini 1443d698cf03SStefano Zampini for (PetscInt d = 0; d < 2; ++d) { 1444d698cf03SStefano Zampini if (bd[d] != DM_BOUNDARY_NONE) { 1445d698cf03SStefano Zampini L[d] = upper[d] - lower[d]; 1446d698cf03SStefano Zampini maxCell[d] = 1.1 * (L[d] / PetscMax(1, edges[d])); 1447d698cf03SStefano Zampini } 1448d698cf03SStefano Zampini } 1449d698cf03SStefano Zampini PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1450d698cf03SStefano Zampini } 1451d698cf03SStefano Zampini } 1452d698cf03SStefano Zampini PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 1453d698cf03SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1454d698cf03SStefano Zampini } 1455d698cf03SStefano Zampini 1456d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 1457d71ae5a4SJacob Faibussowitsch { 14589318fe57SMatthew G. Knepley DM boundary, vol; 1459c22d3578SMatthew G. Knepley DMLabel bdlabel; 1460d698cf03SStefano Zampini PetscBool crisscross = PETSC_FALSE; 1461d6218766SMatthew G. Knepley 1462d6218766SMatthew G. Knepley PetscFunctionBegin; 14634f572ea9SToby Isaac PetscAssertPointer(dm, 1); 1464d698cf03SStefano Zampini if (dim == 2) PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_box_crisscross", &crisscross, NULL)); 1465d698cf03SStefano Zampini if (crisscross) { 1466d698cf03SStefano Zampini PetscCall(DMPlexCreateSquareMesh_Simplex_CrissCross(dm, faces, lower, upper, periodicity)); 1467d698cf03SStefano Zampini } else { 1468c22d3578SMatthew 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"); 14699566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary)); 14709566063dSJacob Faibussowitsch PetscCall(DMSetType(boundary, DMPLEX)); 1471d698cf03SStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)boundary, ((PetscObject)dm)->prefix)); 14729566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 14739566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 1474c22d3578SMatthew G. Knepley PetscCall(DMGetLabel(vol, "marker", &bdlabel)); 1475c22d3578SMatthew G. Knepley if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel)); 14765de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol)); 147769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 1478d698cf03SStefano Zampini PetscCall(DMDestroy(&boundary)); 1479d698cf03SStefano Zampini } 14804054ae39SJames Wright if (interpolate) { 14814054ae39SJames Wright PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 1482d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, periodicity)); 14834054ae39SJames Wright } 14843ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1485d6218766SMatthew G. Knepley } 1486d6218766SMatthew G. Knepley 1487d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 1488d71ae5a4SJacob Faibussowitsch { 1489ed0e4b50SMatthew G. Knepley DMLabel cutLabel = NULL; 1490f4eb4c5dSMatthew G. Knepley PetscInt markerTop = 1, faceMarkerTop = 1; 1491f4eb4c5dSMatthew G. Knepley PetscInt markerBottom = 1, faceMarkerBottom = 1; 1492f4eb4c5dSMatthew G. Knepley PetscInt markerFront = 1, faceMarkerFront = 1; 1493f4eb4c5dSMatthew G. Knepley PetscInt markerBack = 1, faceMarkerBack = 1; 1494f4eb4c5dSMatthew G. Knepley PetscInt markerRight = 1, faceMarkerRight = 1; 1495f4eb4c5dSMatthew G. Knepley PetscInt markerLeft = 1, faceMarkerLeft = 1; 14963dfda0b1SToby Isaac PetscInt dim; 1497d8211ee3SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 14983dfda0b1SToby Isaac PetscMPIInt rank; 14993dfda0b1SToby Isaac 15003dfda0b1SToby Isaac PetscFunctionBegin; 15019566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 15029566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15039566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 15049566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 15059566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 15069371c9d4SSatish 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) { 15079371c9d4SSatish Balay if (cutMarker) { 15089371c9d4SSatish Balay PetscCall(DMCreateLabel(dm, "periodic_cut")); 15099371c9d4SSatish Balay PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 15109371c9d4SSatish Balay } 1511d8211ee3SMatthew G. Knepley } 15123dfda0b1SToby Isaac switch (dim) { 15133dfda0b1SToby Isaac case 2: 1514f4eb4c5dSMatthew G. Knepley faceMarkerTop = 3; 1515f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1516f4eb4c5dSMatthew G. Knepley faceMarkerRight = 2; 1517f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 4; 15183dfda0b1SToby Isaac break; 15193dfda0b1SToby Isaac case 3: 1520f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1521f4eb4c5dSMatthew G. Knepley faceMarkerTop = 2; 1522f4eb4c5dSMatthew G. Knepley faceMarkerFront = 3; 1523f4eb4c5dSMatthew G. Knepley faceMarkerBack = 4; 1524f4eb4c5dSMatthew G. Knepley faceMarkerRight = 5; 1525f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 6; 15263dfda0b1SToby Isaac break; 1527d71ae5a4SJacob Faibussowitsch default: 1528d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 15293dfda0b1SToby Isaac } 15309566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 1531f4eb4c5dSMatthew G. Knepley if (markerSeparate) { 1532f4eb4c5dSMatthew G. Knepley markerBottom = faceMarkerBottom; 1533f4eb4c5dSMatthew G. Knepley markerTop = faceMarkerTop; 1534f4eb4c5dSMatthew G. Knepley markerFront = faceMarkerFront; 1535f4eb4c5dSMatthew G. Knepley markerBack = faceMarkerBack; 1536f4eb4c5dSMatthew G. Knepley markerRight = faceMarkerRight; 1537f4eb4c5dSMatthew G. Knepley markerLeft = faceMarkerLeft; 15383dfda0b1SToby Isaac } 15393dfda0b1SToby Isaac { 1540dd400576SPatrick Sanan const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 1541dd400576SPatrick Sanan const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 1542dd400576SPatrick Sanan const PetscInt numZEdges = rank == 0 ? edges[2] : 0; 1543dd400576SPatrick Sanan const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0; 1544dd400576SPatrick Sanan const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0; 1545dd400576SPatrick Sanan const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0; 15463dfda0b1SToby Isaac const PetscInt numCells = numXEdges * numYEdges * numZEdges; 15473dfda0b1SToby Isaac const PetscInt numXFaces = numYEdges * numZEdges; 15483dfda0b1SToby Isaac const PetscInt numYFaces = numXEdges * numZEdges; 15493dfda0b1SToby Isaac const PetscInt numZFaces = numXEdges * numYEdges; 15503dfda0b1SToby Isaac const PetscInt numTotXFaces = numXVertices * numXFaces; 15513dfda0b1SToby Isaac const PetscInt numTotYFaces = numYVertices * numYFaces; 15523dfda0b1SToby Isaac const PetscInt numTotZFaces = numZVertices * numZFaces; 15533dfda0b1SToby Isaac const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 15543dfda0b1SToby Isaac const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices; 15553dfda0b1SToby Isaac const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices; 15563dfda0b1SToby Isaac const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices; 15573dfda0b1SToby Isaac const PetscInt numVertices = numXVertices * numYVertices * numZVertices; 15583dfda0b1SToby Isaac const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 15593dfda0b1SToby Isaac const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 15603dfda0b1SToby Isaac const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 15613dfda0b1SToby Isaac const PetscInt firstYFace = firstXFace + numTotXFaces; 15623dfda0b1SToby Isaac const PetscInt firstZFace = firstYFace + numTotYFaces; 15633dfda0b1SToby Isaac const PetscInt firstXEdge = numCells + numFaces + numVertices; 15643dfda0b1SToby Isaac const PetscInt firstYEdge = firstXEdge + numTotXEdges; 15653dfda0b1SToby Isaac const PetscInt firstZEdge = firstYEdge + numTotYEdges; 15663dfda0b1SToby Isaac Vec coordinates; 15673dfda0b1SToby Isaac PetscSection coordSection; 15683dfda0b1SToby Isaac PetscScalar *coords; 15693dfda0b1SToby Isaac PetscInt coordSize; 15703dfda0b1SToby Isaac PetscInt v, vx, vy, vz; 15713dfda0b1SToby Isaac PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 15723dfda0b1SToby Isaac 15739566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices)); 157448a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 157548a46eb9SPierre Jolivet for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 157648a46eb9SPierre Jolivet for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 15779566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 15783dfda0b1SToby Isaac /* Build cells */ 15793dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 15803dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 15813dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 15823dfda0b1SToby Isaac PetscInt cell = (fz * numYEdges + fy) * numXEdges + fx; 15833dfda0b1SToby Isaac PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 15843dfda0b1SToby Isaac PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices); 15853dfda0b1SToby Isaac PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 15863dfda0b1SToby Isaac PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices); 15873dfda0b1SToby Isaac PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 15883dfda0b1SToby Isaac PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices); 15893dfda0b1SToby Isaac /* B, T, F, K, R, L */ 1590b5a892a1SMatthew G. Knepley PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */ 159142206facSLisandro Dalcin PetscInt cone[6]; 15923dfda0b1SToby Isaac 15933dfda0b1SToby Isaac /* no boundary twisting in 3D */ 15949371c9d4SSatish Balay cone[0] = faceB; 15959371c9d4SSatish Balay cone[1] = faceT; 15969371c9d4SSatish Balay cone[2] = faceF; 15979371c9d4SSatish Balay cone[3] = faceK; 15989371c9d4SSatish Balay cone[4] = faceR; 15999371c9d4SSatish Balay cone[5] = faceL; 16009566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, cell, cone)); 16019566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, cell, ornt)); 16029566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 16039566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 16049566063dSJacob Faibussowitsch if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 16053dfda0b1SToby Isaac } 16063dfda0b1SToby Isaac } 16073dfda0b1SToby Isaac } 16083dfda0b1SToby Isaac /* Build x faces */ 16093dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 16103dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 16113dfda0b1SToby Isaac for (fx = 0; fx < numXVertices; ++fx) { 16123dfda0b1SToby Isaac PetscInt face = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 16133dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 16143dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz; 16153dfda0b1SToby Isaac PetscInt edgeB = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 16163dfda0b1SToby Isaac PetscInt edgeT = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy; 1617b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16183dfda0b1SToby Isaac PetscInt cone[4]; 16193dfda0b1SToby Isaac 16203dfda0b1SToby Isaac if (dim == 3) { 16213dfda0b1SToby Isaac /* markers */ 16223dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 16233dfda0b1SToby Isaac if (fx == numXVertices - 1) { 16249566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 16259566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerRight)); 16269371c9d4SSatish Balay } else if (fx == 0) { 16279566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 16289566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft)); 16293dfda0b1SToby Isaac } 16303dfda0b1SToby Isaac } 16313dfda0b1SToby Isaac } 16329371c9d4SSatish Balay cone[0] = edgeB; 16339371c9d4SSatish Balay cone[1] = edgeR; 16349371c9d4SSatish Balay cone[2] = edgeT; 16359371c9d4SSatish Balay cone[3] = edgeL; 16369566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 16379566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 16383dfda0b1SToby Isaac } 16393dfda0b1SToby Isaac } 16403dfda0b1SToby Isaac } 16413dfda0b1SToby Isaac /* Build y faces */ 16423dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 164342206facSLisandro Dalcin for (fx = 0; fx < numXEdges; ++fx) { 16443dfda0b1SToby Isaac for (fy = 0; fy < numYVertices; ++fy) { 16453dfda0b1SToby Isaac PetscInt face = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 16463dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 16473dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz; 16483dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 16493dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx; 1650b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16513dfda0b1SToby Isaac PetscInt cone[4]; 16523dfda0b1SToby Isaac 16533dfda0b1SToby Isaac if (dim == 3) { 16543dfda0b1SToby Isaac /* markers */ 16553dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 16563dfda0b1SToby Isaac if (fy == numYVertices - 1) { 16579566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 16589566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBack)); 16599371c9d4SSatish Balay } else if (fy == 0) { 16609566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 16619566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerFront)); 16623dfda0b1SToby Isaac } 16633dfda0b1SToby Isaac } 16643dfda0b1SToby Isaac } 16659371c9d4SSatish Balay cone[0] = edgeB; 16669371c9d4SSatish Balay cone[1] = edgeR; 16679371c9d4SSatish Balay cone[2] = edgeT; 16689371c9d4SSatish Balay cone[3] = edgeL; 16699566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 16709566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 16713dfda0b1SToby Isaac } 16723dfda0b1SToby Isaac } 16733dfda0b1SToby Isaac } 16743dfda0b1SToby Isaac /* Build z faces */ 16753dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 16763dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 16773dfda0b1SToby Isaac for (fz = 0; fz < numZVertices; fz++) { 16783dfda0b1SToby Isaac PetscInt face = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 16793dfda0b1SToby Isaac PetscInt edgeL = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 16803dfda0b1SToby Isaac PetscInt edgeR = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy; 16813dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 16823dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx; 1683b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16843dfda0b1SToby Isaac PetscInt cone[4]; 16853dfda0b1SToby Isaac 16863dfda0b1SToby Isaac if (dim == 2) { 16879371c9d4SSatish Balay if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) { 16889371c9d4SSatish Balay edgeR += numYEdges - 1 - 2 * fy; 16899371c9d4SSatish Balay ornt[1] = -1; 16909371c9d4SSatish Balay } 16919371c9d4SSatish Balay if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) { 16929371c9d4SSatish Balay edgeT += numXEdges - 1 - 2 * fx; 16939371c9d4SSatish Balay ornt[2] = 0; 16949371c9d4SSatish Balay } 16959566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 16969566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 1697d1c88043SMatthew G. Knepley } else { 16983dfda0b1SToby Isaac /* markers */ 16993dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 17003dfda0b1SToby Isaac if (fz == numZVertices - 1) { 17019566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 17029566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerTop)); 17039371c9d4SSatish Balay } else if (fz == 0) { 17049566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 17059566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom)); 17063dfda0b1SToby Isaac } 17073dfda0b1SToby Isaac } 17083dfda0b1SToby Isaac } 17099371c9d4SSatish Balay cone[0] = edgeB; 17109371c9d4SSatish Balay cone[1] = edgeR; 17119371c9d4SSatish Balay cone[2] = edgeT; 17129371c9d4SSatish Balay cone[3] = edgeL; 17139566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 17149566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 17153dfda0b1SToby Isaac } 17163dfda0b1SToby Isaac } 17173dfda0b1SToby Isaac } 17183dfda0b1SToby Isaac /* Build Z edges*/ 17193dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 17203dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 17213dfda0b1SToby Isaac for (ez = 0; ez < numZEdges; ez++) { 17223dfda0b1SToby Isaac const PetscInt edge = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez; 17233dfda0b1SToby Isaac const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx; 17243dfda0b1SToby Isaac const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx; 17253dfda0b1SToby Isaac PetscInt cone[2]; 17263dfda0b1SToby Isaac 17279371c9d4SSatish Balay cone[0] = vertexB; 17289371c9d4SSatish Balay cone[1] = vertexT; 1729c2df9bbfSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, edge, cone)); 17303dfda0b1SToby Isaac if (dim == 3) { 17313dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 17323dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17339566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1734c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1735c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1736c2df9bbfSMatthew G. Knepley } else if (vx == 0) { 17379566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1738c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1739c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 17403dfda0b1SToby Isaac } 17413dfda0b1SToby Isaac } 17423dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 17433dfda0b1SToby Isaac if (vy == numYVertices - 1) { 17449566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1745c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1746c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1747c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 17489566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1749c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1750c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 17513dfda0b1SToby Isaac } 17523dfda0b1SToby Isaac } 17533dfda0b1SToby Isaac } 17543dfda0b1SToby Isaac } 17553dfda0b1SToby Isaac } 17563dfda0b1SToby Isaac } 17573dfda0b1SToby Isaac /* Build Y edges*/ 17583dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 17593dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 17603dfda0b1SToby Isaac for (ey = 0; ey < numYEdges; ey++) { 17613dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx; 17623dfda0b1SToby Isaac const PetscInt edge = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey; 17633dfda0b1SToby Isaac const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx; 17643dfda0b1SToby Isaac const PetscInt vertexK = firstVertex + nextv; 17653dfda0b1SToby Isaac PetscInt cone[2]; 17663dfda0b1SToby Isaac 17679371c9d4SSatish Balay cone[0] = vertexF; 17689371c9d4SSatish Balay cone[1] = vertexK; 17699566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 17703dfda0b1SToby Isaac if (dim == 2) { 17713dfda0b1SToby Isaac if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 17723dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17739566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 17749566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 17759566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1776c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1777d8211ee3SMatthew G. Knepley } else if (vx == 0) { 17789566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 17799566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 17809566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1781c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 17823dfda0b1SToby Isaac } 1783d8211ee3SMatthew G. Knepley } else { 17844c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 17859566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 17869566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1787c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 17883dfda0b1SToby Isaac } 1789d8211ee3SMatthew G. Knepley } 1790d8211ee3SMatthew G. Knepley } else { 17913dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 17923dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17939566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1794c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1795c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1796d8211ee3SMatthew G. Knepley } else if (vx == 0) { 17979566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1798c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1799c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 18003dfda0b1SToby Isaac } 18013dfda0b1SToby Isaac } 18023dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 18033dfda0b1SToby Isaac if (vz == numZVertices - 1) { 18049566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1805c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1806c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1807d8211ee3SMatthew G. Knepley } else if (vz == 0) { 18089566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1809c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1810c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 18113dfda0b1SToby Isaac } 18123dfda0b1SToby Isaac } 18133dfda0b1SToby Isaac } 18143dfda0b1SToby Isaac } 18153dfda0b1SToby Isaac } 18163dfda0b1SToby Isaac } 18173dfda0b1SToby Isaac /* Build X edges*/ 18183dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 18193dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 18203dfda0b1SToby Isaac for (ex = 0; ex < numXEdges; ex++) { 18213dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices; 18223dfda0b1SToby Isaac const PetscInt edge = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex; 18233dfda0b1SToby Isaac const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex; 18243dfda0b1SToby Isaac const PetscInt vertexR = firstVertex + nextv; 18253dfda0b1SToby Isaac PetscInt cone[2]; 18263dfda0b1SToby Isaac 18279371c9d4SSatish Balay cone[0] = vertexL; 18289371c9d4SSatish Balay cone[1] = vertexR; 18299566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 18303dfda0b1SToby Isaac if (dim == 2) { 18313dfda0b1SToby Isaac if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 18323dfda0b1SToby Isaac if (vy == numYVertices - 1) { 18339566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 18349566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 18359566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1836c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1837d8211ee3SMatthew G. Knepley } else if (vy == 0) { 18389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 18399566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 18409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1841c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 18423dfda0b1SToby Isaac } 1843d8211ee3SMatthew G. Knepley } else { 18444c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 18459566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 18469566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1847c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 18483dfda0b1SToby Isaac } 1849d8211ee3SMatthew G. Knepley } 1850d8211ee3SMatthew G. Knepley } else { 18513dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 18523dfda0b1SToby Isaac if (vy == numYVertices - 1) { 18539566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1854c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1855c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1856c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 18579566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1858c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1859c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 18603dfda0b1SToby Isaac } 18613dfda0b1SToby Isaac } 18623dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 18633dfda0b1SToby Isaac if (vz == numZVertices - 1) { 18649566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1865c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1866c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1867c2df9bbfSMatthew G. Knepley } else if (vz == 0) { 18689566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1869c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1870c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 18713dfda0b1SToby Isaac } 18723dfda0b1SToby Isaac } 18733dfda0b1SToby Isaac } 18743dfda0b1SToby Isaac } 18753dfda0b1SToby Isaac } 18763dfda0b1SToby Isaac } 18779566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 18789566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 18793dfda0b1SToby Isaac /* Build coordinates */ 18809566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 18819566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 18829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 18839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 18843dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex + numVertices; ++v) { 18859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 18869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 18873dfda0b1SToby Isaac } 18889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 18899566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 18909566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 18919566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 18929566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 18939566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 18949566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 18959566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 18963dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; ++vz) { 18973dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; ++vy) { 18983dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; ++vx) { 18993dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 19003dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1901ad540459SPierre Jolivet if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz; 19023dfda0b1SToby Isaac } 19033dfda0b1SToby Isaac } 19043dfda0b1SToby Isaac } 19059566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 19069566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 19079566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 19083dfda0b1SToby Isaac } 19093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19103dfda0b1SToby Isaac } 19113dfda0b1SToby Isaac 1912d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1913d71ae5a4SJacob Faibussowitsch { 19149318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 19159318fe57SMatthew G. Knepley PetscInt fac[3] = {0, 0, 0}, d; 1916552f7358SJed Brown 1917552f7358SJed Brown PetscFunctionBegin; 19184f572ea9SToby Isaac PetscAssertPointer(dm, 1); 19199318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 19209566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 19219371c9d4SSatish Balay for (d = 0; d < dim; ++d) { 19229371c9d4SSatish Balay fac[d] = faces[d]; 19239371c9d4SSatish Balay bdt[d] = periodicity[d]; 19249371c9d4SSatish Balay } 19259566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2])); 19269371c9d4SSatish 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))) { 19276858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 19286858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1929552f7358SJed Brown 19309318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19316858538eSMatthew G. Knepley if (periodicity[d] != DM_BOUNDARY_NONE) { 19329318fe57SMatthew G. Knepley L[d] = upper[d] - lower[d]; 19339318fe57SMatthew G. Knepley maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d])); 1934768d5fceSMatthew G. Knepley } 19356858538eSMatthew G. Knepley } 19364fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1937768d5fceSMatthew G. Knepley } 19389566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 19393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19409318fe57SMatthew G. Knepley } 19419318fe57SMatthew G. Knepley 19425dca41c3SJed 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) 1943d71ae5a4SJacob Faibussowitsch { 19449318fe57SMatthew G. Knepley PetscFunctionBegin; 194546139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 19465dca41c3SJed Brown if (shape == DM_SHAPE_ZBOX) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 19476725e60dSJed Brown else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 19489566063dSJacob Faibussowitsch else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 19499566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity)); 19509318fe57SMatthew G. Knepley if (!interpolate && dim > 1 && !simplex) { 1951768d5fceSMatthew G. Knepley DM udm; 1952768d5fceSMatthew G. Knepley 19539566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 19549566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, udm)); 195569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 1956768d5fceSMatthew G. Knepley } 195746139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 19583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1959c8c68bd8SToby Isaac } 1960c8c68bd8SToby Isaac 19615d83a8b1SBarry Smith /*@ 1962768d5fceSMatthew G. Knepley DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 1963768d5fceSMatthew G. Knepley 1964d083f849SBarry Smith Collective 1965768d5fceSMatthew G. Knepley 1966768d5fceSMatthew G. Knepley Input Parameters: 1967a1cb98faSBarry Smith + comm - The communicator for the `DM` object 1968768d5fceSMatthew G. Knepley . dim - The spatial dimension 1969a1cb98faSBarry Smith . simplex - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells 197020f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 197120f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 197220f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 197320f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 197442108689Sksagiyam . interpolate - Flag to create intermediate mesh pieces (edges, faces) 197542108689Sksagiyam . localizationHeight - Flag to localize edges and faces in addition to cells; only significant for periodic meshes 197642108689Sksagiyam - sparseLocalize - Flag to localize coordinates only for cells near the periodic boundary; only significant for periodic meshes 1977768d5fceSMatthew G. Knepley 1978768d5fceSMatthew G. Knepley Output Parameter: 1979a1cb98faSBarry Smith . dm - The `DM` object 1980768d5fceSMatthew G. Knepley 1981768d5fceSMatthew G. Knepley Level: beginner 1982768d5fceSMatthew G. Knepley 1983a1cb98faSBarry Smith Note: 1984a1cb98faSBarry Smith To customize this mesh using options, use 1985a1cb98faSBarry Smith .vb 1986a1cb98faSBarry Smith DMCreate(comm, &dm); 1987a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 1988a1cb98faSBarry Smith DMSetFromOptions(dm); 1989a1cb98faSBarry Smith .ve 1990a1cb98faSBarry Smith and use the options in `DMSetFromOptions()`. 1991a1cb98faSBarry Smith 1992a4e35b19SJacob Faibussowitsch Here is the numbering returned for 2 faces in each direction for tensor cells\: 1993a1cb98faSBarry Smith .vb 1994a1cb98faSBarry Smith 10---17---11---18----12 1995a1cb98faSBarry Smith | | | 1996a1cb98faSBarry Smith | | | 1997a1cb98faSBarry Smith 20 2 22 3 24 1998a1cb98faSBarry Smith | | | 1999a1cb98faSBarry Smith | | | 2000a1cb98faSBarry Smith 7---15----8---16----9 2001a1cb98faSBarry Smith | | | 2002a1cb98faSBarry Smith | | | 2003a1cb98faSBarry Smith 19 0 21 1 23 2004a1cb98faSBarry Smith | | | 2005a1cb98faSBarry Smith | | | 2006a1cb98faSBarry Smith 4---13----5---14----6 2007a1cb98faSBarry Smith .ve 2008a1cb98faSBarry Smith and for simplicial cells 2009a1cb98faSBarry Smith .vb 2010a1cb98faSBarry Smith 14----8---15----9----16 2011a1cb98faSBarry Smith |\ 5 |\ 7 | 2012a1cb98faSBarry Smith | \ | \ | 2013a1cb98faSBarry Smith 13 2 14 3 15 2014a1cb98faSBarry Smith | 4 \ | 6 \ | 2015a1cb98faSBarry Smith | \ | \ | 2016a1cb98faSBarry Smith 11----6---12----7----13 2017a1cb98faSBarry Smith |\ |\ | 2018a1cb98faSBarry Smith | \ 1 | \ 3 | 2019a1cb98faSBarry Smith 10 0 11 1 12 2020a1cb98faSBarry Smith | 0 \ | 2 \ | 2021a1cb98faSBarry Smith | \ | \ | 2022a1cb98faSBarry Smith 8----4----9----5----10 2023a1cb98faSBarry Smith .ve 2024a1cb98faSBarry Smith 20251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 2026768d5fceSMatthew G. Knepley @*/ 202742108689Sksagiyam 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) 2028d71ae5a4SJacob Faibussowitsch { 20299318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 2030fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 2031fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 2032fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 2033552f7358SJed Brown 2034768d5fceSMatthew G. Knepley PetscFunctionBegin; 20359566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 20369566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 20375dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(*dm, DM_SHAPE_BOX, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 203842108689Sksagiyam if (periodicity) { 203942108689Sksagiyam DM cdm; 204042108689Sksagiyam 204142108689Sksagiyam PetscCall(DMGetCoordinateDM(*dm, &cdm)); 204242108689Sksagiyam PetscCall(DMPlexSetMaxProjectionHeight(cdm, localizationHeight)); 204342108689Sksagiyam PetscCall(DMSetSparseLocalize(*dm, sparseLocalize)); 204442108689Sksagiyam PetscCall(DMLocalizeCoordinates(*dm)); 204542108689Sksagiyam } 20463ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20479318fe57SMatthew G. Knepley } 2048fdbf62faSLisandro Dalcin 2049d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 2050d71ae5a4SJacob Faibussowitsch { 20519318fe57SMatthew G. Knepley DM bdm, vol; 20529318fe57SMatthew G. Knepley PetscInt i; 20539318fe57SMatthew G. Knepley 20549318fe57SMatthew G. Knepley PetscFunctionBegin; 20551fcf445aSMatthew G. Knepley // TODO Now we can support periodicity 205608401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 20579566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 20589566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 20599566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 206046139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, bdm, 0, 0, 0)); 20619566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 20621fcf445aSMatthew G. Knepley PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, NULL, NULL, &vol)); 206346139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, bdm, 0, 0, 0)); 20649566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 206569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 20669318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 20679318fe57SMatthew G. Knepley Vec v; 20689318fe57SMatthew G. Knepley PetscScalar *x; 20699318fe57SMatthew G. Knepley PetscInt cDim, n; 20709318fe57SMatthew G. Knepley 20719566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 20729566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 20739566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 20749566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 20759318fe57SMatthew G. Knepley x += cDim; 20769318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 20779566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 20789566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 20799318fe57SMatthew G. Knepley } 20803ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2081552f7358SJed Brown } 2082552f7358SJed Brown 208300dabe28SStefano Zampini /*@ 208439f4f5dbSPierre Jolivet DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tessellating the (x,y) plane and extruding in the third direction using wedge cells. 208500dabe28SStefano Zampini 2086d083f849SBarry Smith Collective 208700dabe28SStefano Zampini 208800dabe28SStefano Zampini Input Parameters: 2089a1cb98faSBarry Smith + comm - The communicator for the `DM` object 209020f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1, 1, 1) 209120f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 209220f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 209320f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 2094a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 209500dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 209600dabe28SStefano Zampini 209700dabe28SStefano Zampini Output Parameter: 2098a1cb98faSBarry Smith . dm - The `DM` object 209900dabe28SStefano Zampini 210000dabe28SStefano Zampini Level: beginner 210100dabe28SStefano Zampini 21021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 210300dabe28SStefano Zampini @*/ 2104d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 2105d71ae5a4SJacob Faibussowitsch { 21069318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 210700dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 210800dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 210900dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 211000dabe28SStefano Zampini 211100dabe28SStefano Zampini PetscFunctionBegin; 21129566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 21139566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 21149566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 2115d410b0cfSMatthew G. Knepley if (!interpolate) { 2116d410b0cfSMatthew G. Knepley DM udm; 211700dabe28SStefano Zampini 21189566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 211969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 212000dabe28SStefano Zampini } 21217ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 21223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 212300dabe28SStefano Zampini } 212400dabe28SStefano Zampini 2125cfb853baSMatthew G. Knepley /* 2126cfb853baSMatthew 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. 2127cfb853baSMatthew G. Knepley 2128cfb853baSMatthew G. Knepley Input Parameters: 2129cfb853baSMatthew G. Knepley + len - The length of the tuple 2130cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max) 2131cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition 2132cfb853baSMatthew G. Knepley 2133cfb853baSMatthew G. Knepley Output Parameter: 213420f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max` 2135cfb853baSMatthew G. Knepley 2136cfb853baSMatthew G. Knepley Level: developer 2137cfb853baSMatthew G. Knepley 213820f4b53cSBarry Smith Note: 213920f4b53cSBarry Smith Ordering is lexicographic with lowest index as least significant in ordering. 214020f4b53cSBarry 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}. 214120f4b53cSBarry Smith 2142cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal() 2143cfb853baSMatthew G. Knepley */ 2144cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[]) 2145cfb853baSMatthew G. Knepley { 2146cfb853baSMatthew G. Knepley PetscInt i; 2147cfb853baSMatthew G. Knepley 2148cfb853baSMatthew G. Knepley PetscFunctionBegin; 2149cfb853baSMatthew G. Knepley for (i = 0; i < len; ++i) { 2150cfb853baSMatthew G. Knepley if (tup[i] < max[i] - 1) { 2151cfb853baSMatthew G. Knepley break; 2152cfb853baSMatthew G. Knepley } else { 2153cfb853baSMatthew G. Knepley tup[i] = 0; 2154cfb853baSMatthew G. Knepley } 2155cfb853baSMatthew G. Knepley } 2156cfb853baSMatthew G. Knepley if (i == len) tup[i - 1] = max[i - 1]; 2157cfb853baSMatthew G. Knepley else ++tup[i]; 21583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2159cfb853baSMatthew G. Knepley } 2160cfb853baSMatthew G. Knepley 2161cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[]) 2162cfb853baSMatthew G. Knepley { 21638d2ec52aSSatish Balay PetscInt idx = tup[len - 1]; 2164cfb853baSMatthew G. Knepley 21658d2ec52aSSatish Balay for (PetscInt i = len - 2; i >= 0; --i) { 2166cfb853baSMatthew G. Knepley idx *= max[i]; 2167cfb853baSMatthew G. Knepley idx += tup[i]; 2168cfb853baSMatthew G. Knepley } 2169cfb853baSMatthew G. Knepley return idx; 2170cfb853baSMatthew G. Knepley } 2171cfb853baSMatthew G. Knepley 21728d2ec52aSSatish Balay static void IndexToTuple_Private(PetscInt len, const PetscInt max[], PetscInt idx, PetscInt tup[]) 2173cfb853baSMatthew G. Knepley { 21748d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21758d2ec52aSSatish Balay tup[i] = idx % max[i]; 21768d2ec52aSSatish Balay idx = (idx - tup[i]) / max[i]; 21778d2ec52aSSatish Balay } 21788d2ec52aSSatish Balay } 21798d2ec52aSSatish Balay 21808d2ec52aSSatish Balay static void TupleToRanks_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt tup[], PetscInt ranks[]) 21818d2ec52aSSatish Balay { 21828d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21838d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 21848d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 21858d2ec52aSSatish Balay const PetscInt idx = (tup[i] < 0 ? max[i] + tup[i] : tup[i]) % max[i]; 21868d2ec52aSSatish Balay 21878d2ec52aSSatish Balay if (idx < rem * (div + 1)) ranks[i] = idx / (div + 1); 21888d2ec52aSSatish Balay else ranks[i] = rem + (idx - rem * (div + 1)) / div; 21898d2ec52aSSatish Balay } 21908d2ec52aSSatish Balay } 21918d2ec52aSSatish Balay 21928d2ec52aSSatish Balay static void RanksToSizes_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt ranks[], PetscInt sizes[]) 21938d2ec52aSSatish Balay { 21948d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21958d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 21968d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 21978d2ec52aSSatish Balay 21988d2ec52aSSatish Balay sizes[i] = ranks[i] < rem ? div + 1 : div; 21998d2ec52aSSatish Balay } 22008d2ec52aSSatish Balay } 22018d2ec52aSSatish Balay 22028d2ec52aSSatish Balay /* 22038d2ec52aSSatish 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. 22048d2ec52aSSatish Balay 22058d2ec52aSSatish 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. 22068d2ec52aSSatish Balay 22078d2ec52aSSatish 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. 2208dfe9cfe5SMatthew Knepley 2209dfe9cfe5SMatthew Knepley Parallel Layout: 2210dfe9cfe5SMatthew Knepley 2211dfe9cfe5SMatthew 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. 22128d2ec52aSSatish Balay */ 22138d2ec52aSSatish Balay static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], PetscInt overlap, const DMBoundaryType bd[]) 22148d2ec52aSSatish Balay { 22158d2ec52aSSatish Balay const PetscInt debug = ((DM_Plex *)dm->data)->printAdj; 22168d2ec52aSSatish Balay PetscSF sf; 2217cfb853baSMatthew G. Knepley Vec coordinates; 2218cfb853baSMatthew G. Knepley PetscSection coordSection; 2219cfb853baSMatthew G. Knepley DMLabel cutLabel = NULL; 2220cfb853baSMatthew G. Knepley PetscBool cutMarker = PETSC_FALSE; 2221cfb853baSMatthew G. Knepley PetscBool periodic = PETSC_FALSE; 22228d2ec52aSSatish Balay PetscInt numCells = 1; 22238d2ec52aSSatish Balay PetscInt numVertices = 1; 22248d2ec52aSSatish Balay PetscSFNode *remotes; 2225cfb853baSMatthew G. Knepley PetscScalar *coords; 22268d2ec52aSSatish Balay PetscInt *procs; // The number of processes along each dimension 22278d2ec52aSSatish Balay PetscInt *lrank; // Rank in each dimension, lrank[d] \in [0, procs[d]) 22288d2ec52aSSatish Balay PetscInt *ledges; // The number of edges along each dimension for this process 22298d2ec52aSSatish Balay PetscInt *vstart; // The first vertex along each dimension on this processes 22308d2ec52aSSatish Balay PetscInt *vertices; // The number of vertices along each dimension on this process 22318d2ec52aSSatish Balay PetscInt *rvert; // The global (not local) vertex number along each dimension 22328d2ec52aSSatish Balay PetscInt *rrank; // The rank along each dimension for the process owning rvert[] 22338d2ec52aSSatish Balay PetscInt *rvertices; // The number of vertices along each dimension for the process rrank[] 22348d2ec52aSSatish Balay PetscInt *vert, *vtmp, *supp, cone[2], *leaves; 22358d2ec52aSSatish Balay PetscInt cell = 0, coordSize, Nl = 0, Nl2 = 0; 22368d2ec52aSSatish Balay PetscMPIInt rank, size; 22378d2ec52aSSatish Balay MPI_Comm comm; 2238cfb853baSMatthew G. Knepley 2239cfb853baSMatthew G. Knepley PetscFunctionBegin; 22408d2ec52aSSatish Balay PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 22418d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_rank(comm, &rank)); 22428d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_size(comm, &size)); 2243cfb853baSMatthew G. Knepley PetscCall(DMSetDimension(dm, dim)); 22448d2ec52aSSatish Balay PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 22458d2ec52aSSatish Balay PetscCall(PetscCalloc4(dim, &procs, dim, &lrank, dim, &rrank, 2 * dim, &supp)); 22468d2ec52aSSatish Balay PetscCall(PetscCalloc7(dim, &ledges, dim, &vertices, dim, &rvertices, dim, &vert, dim, &rvert, dim, &vstart, dim, &vtmp)); 2247cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 2248cfb853baSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 22498d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE; 2250cfb853baSMatthew G. Knepley if (periodic && cutMarker) { 2251cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "periodic_cut")); 2252cfb853baSMatthew G. Knepley PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 2253cfb853baSMatthew G. Knepley } 22548d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, comm, PETSC_ERR_SUP, "Hypercubic mesh must be periodic now"); 22558d2ec52aSSatish Balay overlap = overlap == PETSC_DETERMINE ? 1 : overlap; 22568d2ec52aSSatish Balay PetscCheck(overlap >= 1, comm, PETSC_ERR_SUP, "Overlap %" PetscInt_FMT " must be greater than 0", overlap); 22578d2ec52aSSatish Balay if (size > 1) { 22588d2ec52aSSatish Balay PetscInt Npr = 1; 22598d2ec52aSSatish Balay 22608d2ec52aSSatish Balay // Make process grid 22618d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "Process grid:")); 22628d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22638d2ec52aSSatish Balay procs[d] = PetscRintReal(PetscPowReal(size, 1. / dim)); 22648d2ec52aSSatish Balay Npr *= procs[d]; 22658d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, " %" PetscInt_FMT, procs[d])); 22668d2ec52aSSatish Balay } 22678d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "\n")); 22688d2ec52aSSatish Balay PetscCheck(Npr == size, comm, PETSC_ERR_PLIB, "Process grid size %" PetscInt_FMT " != %d comm size", Npr, size); 22698d2ec52aSSatish Balay IndexToTuple_Private(dim, procs, rank, lrank); 22708d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22718d2ec52aSSatish Balay ledges[d] = edges[d] / procs[d] + (edges[d] % procs[d] > lrank[d] ? 1 : 0); 22728d2ec52aSSatish Balay vstart[d] = 0; 22738d2ec52aSSatish Balay for (PetscInt r = 0; r < lrank[d]; ++r) vstart[d] += edges[d] / procs[d] + (edges[d] % procs[d] > r ? 1 : 0); 22748d2ec52aSSatish Balay vstart[d] -= overlap; // For halo 22758d2ec52aSSatish Balay } 22768d2ec52aSSatish Balay } else { 22778d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22788d2ec52aSSatish Balay procs[d] = 1; 22798d2ec52aSSatish Balay ledges[d] = edges[d]; 22808d2ec52aSSatish Balay } 22818d2ec52aSSatish Balay } 22828d2ec52aSSatish Balay // Calculate local patch size 22838d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22848d2ec52aSSatish Balay vertices[d] = ledges[d] + (procs[d] > 1 ? 2 * overlap : 0); 2285cfb853baSMatthew G. Knepley numVertices *= vertices[d]; 2286cfb853baSMatthew G. Knepley } 2287cfb853baSMatthew G. Knepley numCells = numVertices * dim; 2288cfb853baSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 22898d2ec52aSSatish Balay for (PetscInt c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2)); 22908d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim)); 2291cfb853baSMatthew G. Knepley PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */ 2292cfb853baSMatthew G. Knepley /* Build cell cones and vertex supports */ 2293cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "celltype")); 22948d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Topology for rank %d:\n", rank)); 2295cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2296cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells; 2297cfb853baSMatthew G. Knepley PetscInt s = 0; 22988d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2299cfb853baSMatthew G. Knepley 23008d2ec52aSSatish Balay if (debug) { 23018d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 23028d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d])); 23038d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 23048d2ec52aSSatish Balay } 2305cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT)); 23068d2ec52aSSatish Balay // Define edge cones 23078d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23088d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2309cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + 1) % vertices[d]; 2310cfb853baSMatthew G. Knepley cone[0] = vertex; 2311cfb853baSMatthew G. Knepley cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells; 23128d2ec52aSSatish Balay if (debug) { 23138d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ":", cone[1])); 23148d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vtmp[e])); 23158d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 23168d2ec52aSSatish Balay } 2317cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, cell, cone)); 2318cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT)); 23198d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1])); 2320cfb853baSMatthew G. Knepley ++cell; 23218d2ec52aSSatish Balay // Shared vertices are any in the first or last overlap layers 23228d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 2323cfb853baSMatthew G. Knepley } 23248d2ec52aSSatish Balay if (size > 1 && leaf) ++Nl; 23258d2ec52aSSatish Balay // Define vertex supports 23268d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23278d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2328cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + vertices[d] - 1) % vertices[d]; 2329cfb853baSMatthew G. Knepley supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d; 2330cfb853baSMatthew G. Knepley supp[s++] = (vertex - numCells) * dim + d; 2331cfb853baSMatthew G. Knepley PetscCall(DMPlexSetSupport(dm, vertex, supp)); 2332cfb853baSMatthew G. Knepley } 2333cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2334cfb853baSMatthew G. Knepley } 23358d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2336cfb853baSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 23378d2ec52aSSatish Balay // Allocate for SF 23388d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &leaves)); 23398d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &remotes)); 23408d2ec52aSSatish Balay // Build coordinates 2341cfb853baSMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 2342cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(coordSection, 1)); 2343cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 2344cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 23458d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) { 2346cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetDof(coordSection, v, dim)); 2347cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 2348cfb853baSMatthew G. Knepley } 2349cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetUp(coordSection)); 2350cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 23518d2ec52aSSatish Balay PetscCall(VecCreate(comm, &coordinates)); 2352cfb853baSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 2353cfb853baSMatthew G. Knepley PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 2354cfb853baSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinates, dim)); 2355cfb853baSMatthew G. Knepley PetscCall(VecSetType(coordinates, VECSTANDARD)); 2356cfb853baSMatthew G. Knepley PetscCall(VecGetArray(coordinates, &coords)); 23578d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Geometry for rank %d:\n", rank)); 23588d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) vert[d] = 0; 2359cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2360cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert); 23618d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2362cfb853baSMatthew G. Knepley 23638d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23648d2ec52aSSatish Balay coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / edges[d]) * (vert[d] + vstart[d]); 23658d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 23668d2ec52aSSatish Balay } 23678d2ec52aSSatish Balay if (size > 1 && leaf) { 23688d2ec52aSSatish Balay PetscInt rnumCells = 1; 23698d2ec52aSSatish Balay 23708d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) rvert[d] = vert[d] + vstart[d]; 23718d2ec52aSSatish Balay TupleToRanks_Private(dim, edges, procs, rvert, rrank); 23728d2ec52aSSatish Balay leaves[Nl2] = vertex + numCells; 23738d2ec52aSSatish Balay remotes[Nl2].rank = TupleToIndex_Private(dim, procs, rrank); 23748d2ec52aSSatish Balay RanksToSizes_Private(dim, edges, procs, rrank, rvertices); 23758d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23768d2ec52aSSatish Balay rvertices[d] += 2 * overlap; // Add halo 23778d2ec52aSSatish Balay rnumCells *= rvertices[d]; 23788d2ec52aSSatish Balay } 23798d2ec52aSSatish Balay rnumCells *= dim; 23808d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23818d2ec52aSSatish Balay const PetscInt diff = rrank[d] - lrank[d]; 23828d2ec52aSSatish Balay 23838d2ec52aSSatish Balay if (!diff) rvert[d] = vert[d]; // Vertex is local 23848d2ec52aSSatish Balay else if (rvert[d] < 0) rvert[d] = rvertices[d] - 1 + rvert[d]; // Wrap around at the bottom 23858d2ec52aSSatish Balay else if (rvert[d] >= edges[d]) rvert[d] = rvert[d] - edges[d] + 1; // Wrap around at the top 23868d2ec52aSSatish Balay else if (diff == -1) rvert[d] = rvertices[d] - 1 + (vert[d] - overlap); 23878d2ec52aSSatish Balay else if (diff == 1) rvert[d] = (vertices[d] - vert[d] - 1) + overlap; 23888d2ec52aSSatish Balay else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Process distance %" PetscInt_FMT " in direction %" PetscInt_FMT " should not be possible", diff, d); 23898d2ec52aSSatish Balay } 23908d2ec52aSSatish Balay remotes[Nl2].index = TupleToIndex_Private(dim, rvertices, rvert) + rnumCells; 23918d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Shared Vertex %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", leaves[Nl2], remotes[Nl2].rank, remotes[Nl2].index)); 23928d2ec52aSSatish Balay ++Nl2; 23938d2ec52aSSatish Balay } 23948d2ec52aSSatish Balay if (debug) { 23958d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 23968d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d] + vstart[d])); 23978d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %g", (double)PetscRealPart(coords[vertex * dim + d]))); 23988d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 23998d2ec52aSSatish Balay } 2400cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2401cfb853baSMatthew G. Knepley } 24028d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2403cfb853baSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &coords)); 2404cfb853baSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 2405cfb853baSMatthew G. Knepley PetscCall(VecDestroy(&coordinates)); 24068d2ec52aSSatish Balay // Build SF 24078d2ec52aSSatish Balay PetscCheck(Nl == Nl2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Initial number of leaves %" PetscInt_FMT " != %" PetscInt_FMT " final number", Nl, Nl2); 24088d2ec52aSSatish Balay PetscCall(DMGetPointSF(dm, &sf)); 24098d2ec52aSSatish Balay PetscCall(PetscSFSetGraph(sf, numCells + numVertices, Nl, leaves, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 24108d2ec52aSSatish Balay if (debug) PetscCall(PetscSFView(sf, PETSC_VIEWER_STDOUT_WORLD)); 2411cfb853baSMatthew G. Knepley //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper)); 2412cfb853baSMatthew G. Knepley // Attach the extent 2413cfb853baSMatthew G. Knepley { 2414cfb853baSMatthew G. Knepley PetscContainer c; 24158d2ec52aSSatish Balay PetscInt *extent, *lextent; 2416cfb853baSMatthew G. Knepley 2417cfb853baSMatthew G. Knepley PetscCall(PetscMalloc1(dim, &extent)); 24188d2ec52aSSatish Balay PetscCall(PetscMalloc1(dim, &lextent)); 24198d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 24208d2ec52aSSatish Balay extent[d] = edges[d]; 24218d2ec52aSSatish Balay lextent[d] = ledges[d]; 24228d2ec52aSSatish Balay } 2423cfb853baSMatthew G. Knepley PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 242449abdd8aSBarry Smith PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 2425cfb853baSMatthew G. Knepley PetscCall(PetscContainerSetPointer(c, extent)); 2426cfb853baSMatthew G. Knepley PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c)); 2427cfb853baSMatthew G. Knepley PetscCall(PetscContainerDestroy(&c)); 24288d2ec52aSSatish Balay PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 24298d2ec52aSSatish Balay PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 24308d2ec52aSSatish Balay PetscCall(PetscContainerSetPointer(c, lextent)); 24318d2ec52aSSatish Balay PetscCall(PetscObjectCompose((PetscObject)dm, "_lextent", (PetscObject)c)); 24328d2ec52aSSatish Balay PetscCall(PetscContainerDestroy(&c)); 2433cfb853baSMatthew G. Knepley } 24348d2ec52aSSatish Balay PetscCall(PetscFree4(procs, lrank, rrank, supp)); 24358d2ec52aSSatish Balay PetscCall(PetscFree7(ledges, vertices, rvertices, vert, rvert, vstart, vtmp)); 24363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2437cfb853baSMatthew G. Knepley } 2438cfb853baSMatthew G. Knepley 2439cfb853baSMatthew G. Knepley /*@C 2440aaa8cc7dSPierre Jolivet DMPlexCreateHypercubicMesh - Creates a periodic mesh on the tensor product of unit intervals using only vertices and edges. 2441cfb853baSMatthew G. Knepley 2442cfb853baSMatthew G. Knepley Collective 2443cfb853baSMatthew G. Knepley 2444cfb853baSMatthew G. Knepley Input Parameters: 24458d2ec52aSSatish Balay + comm - The communicator for the `DM` object 2446cfb853baSMatthew G. Knepley . dim - The spatial dimension 244720f4b53cSBarry Smith . edges - Number of edges per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 244820f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 24498d2ec52aSSatish Balay . upper - The upper right corner, or `NULL` for (1, 1, 1) 24508d2ec52aSSatish Balay - overlap - The number of vertices in each direction to include in the overlap (default is 1) 2451cfb853baSMatthew G. Knepley 2452cfb853baSMatthew G. Knepley Output Parameter: 2453cfb853baSMatthew G. Knepley . dm - The DM object 2454cfb853baSMatthew G. Knepley 245520f4b53cSBarry Smith Level: beginner 245620f4b53cSBarry Smith 245720f4b53cSBarry Smith Note: 245820f4b53cSBarry Smith If you want to customize this mesh using options, you just need to 245920f4b53cSBarry Smith .vb 246020f4b53cSBarry Smith DMCreate(comm, &dm); 246120f4b53cSBarry Smith DMSetType(dm, DMPLEX); 246220f4b53cSBarry Smith DMSetFromOptions(dm); 246320f4b53cSBarry Smith .ve 246420f4b53cSBarry Smith and use the options on the `DMSetFromOptions()` page. 2465cfb853baSMatthew G. Knepley 2466cfb853baSMatthew G. Knepley The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively, 246720f4b53cSBarry Smith .vb 246820f4b53cSBarry Smith 18--0-19--2-20--4-18 246920f4b53cSBarry Smith | | | | 247020f4b53cSBarry Smith 13 15 17 13 247120f4b53cSBarry Smith | | | | 247220f4b53cSBarry Smith 24-12-25-14-26-16-24 247320f4b53cSBarry Smith | | | | 247420f4b53cSBarry Smith 7 9 11 7 247520f4b53cSBarry Smith | | | | 247620f4b53cSBarry Smith 21--6-22--8-23-10-21 247720f4b53cSBarry Smith | | | | 247820f4b53cSBarry Smith 1 3 5 1 247920f4b53cSBarry Smith | | | | 248020f4b53cSBarry Smith 18--0-19--2-20--4-18 248120f4b53cSBarry Smith .ve 2482cfb853baSMatthew G. Knepley 248376fbde31SPierre Jolivet .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 2484cfb853baSMatthew G. Knepley @*/ 24858d2ec52aSSatish Balay PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], PetscInt overlap, DM *dm) 2486cfb853baSMatthew G. Knepley { 2487cfb853baSMatthew G. Knepley PetscInt *edg; 2488cfb853baSMatthew G. Knepley PetscReal *low, *upp; 2489cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 2490cfb853baSMatthew G. Knepley PetscInt d; 2491cfb853baSMatthew G. Knepley 2492cfb853baSMatthew G. Knepley PetscFunctionBegin; 2493cfb853baSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 2494cfb853baSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 2495cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt)); 2496cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 2497cfb853baSMatthew G. Knepley edg[d] = edges ? edges[d] : 1; 2498cfb853baSMatthew G. Knepley low[d] = lower ? lower[d] : 0.; 2499cfb853baSMatthew G. Knepley upp[d] = upper ? upper[d] : 1.; 2500cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 2501cfb853baSMatthew G. Knepley } 25028d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, overlap, bdt)); 2503cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edg, low, upp, bdt)); 25043ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2505cfb853baSMatthew G. Knepley } 2506cfb853baSMatthew G. Knepley 2507cc4c1da9SBarry Smith /*@ 2508a1cb98faSBarry Smith DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database. 2509a9074c1eSMatthew G. Knepley 251020f4b53cSBarry Smith Logically Collective 2511a9074c1eSMatthew G. Knepley 2512a9074c1eSMatthew G. Knepley Input Parameters: 251320f4b53cSBarry Smith + dm - the `DM` context 2514a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 2515a9074c1eSMatthew G. Knepley 2516a1cb98faSBarry Smith Level: advanced 2517a1cb98faSBarry Smith 2518a1cb98faSBarry Smith Note: 2519a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 2520a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 2521a9074c1eSMatthew G. Knepley 25221cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()` 2523a9074c1eSMatthew G. Knepley @*/ 2524d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 2525d71ae5a4SJacob Faibussowitsch { 2526a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2527a9074c1eSMatthew G. Knepley 2528a9074c1eSMatthew G. Knepley PetscFunctionBegin; 2529a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25309566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 25319566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 25323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2533a9074c1eSMatthew G. Knepley } 2534a9074c1eSMatthew G. Knepley 25359318fe57SMatthew G. Knepley /* Remap geometry to cylinder 253661a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 253761a622f3SMatthew G. Knepley 25389318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 25399318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 25409318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 25410510c589SMatthew G. Knepley 25429318fe57SMatthew G. Knepley phi = arctan(y/x) 25439318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 25449318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 25450510c589SMatthew G. Knepley 25469318fe57SMatthew G. Knepley so we remap them using 25470510c589SMatthew G. Knepley 25489318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 25499318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 25500510c589SMatthew G. Knepley 25519318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 25529318fe57SMatthew G. Knepley */ 2553d71ae5a4SJacob 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[]) 2554d71ae5a4SJacob Faibussowitsch { 25559318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 25569318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 255722cc497dSMatthew G. Knepley 25589318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 25599318fe57SMatthew G. Knepley f0[0] = u[0]; 25609318fe57SMatthew G. Knepley f0[1] = u[1]; 25619318fe57SMatthew G. Knepley } else { 25629318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 25630510c589SMatthew G. Knepley 25649318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 25659318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 25669318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 25679318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 25689318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 25699318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 25709318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 25719318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 25729318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 25739318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 25749318fe57SMatthew G. Knepley } else { 25759318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 25769318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 25779318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 25789318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 25799318fe57SMatthew G. Knepley } 25809318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 25819318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 25829318fe57SMatthew G. Knepley } 25839318fe57SMatthew G. Knepley f0[2] = u[2]; 25849318fe57SMatthew G. Knepley } 25850510c589SMatthew G. Knepley 258649704ca5SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ, PetscInt Nr) 2587d71ae5a4SJacob Faibussowitsch { 25880510c589SMatthew G. Knepley const PetscInt dim = 3; 25899318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 2590d8c47e87SMatthew G. Knepley PetscMPIInt rank; 25910510c589SMatthew G. Knepley 25920510c589SMatthew G. Knepley PetscFunctionBegin; 259346139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 25949566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 25959566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 25960510c589SMatthew G. Knepley /* Create topology */ 25970510c589SMatthew G. Knepley { 25980510c589SMatthew G. Knepley PetscInt cone[8], c; 25990510c589SMatthew G. Knepley 2600dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 2601dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 2602006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 2603ae8bcbbbSMatthew G. Knepley numCells *= 3; 2604dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 2605006a8963SMatthew G. Knepley } 26069566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 26079566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 26089566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 2609dd400576SPatrick Sanan if (rank == 0) { 2610006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 26119371c9d4SSatish Balay cone[0] = 15; 26129371c9d4SSatish Balay cone[1] = 18; 26139371c9d4SSatish Balay cone[2] = 17; 26149371c9d4SSatish Balay cone[3] = 16; 26159371c9d4SSatish Balay cone[4] = 31; 26169371c9d4SSatish Balay cone[5] = 32; 26179371c9d4SSatish Balay cone[6] = 33; 26189371c9d4SSatish Balay cone[7] = 34; 26199566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 26209371c9d4SSatish Balay cone[0] = 16; 26219371c9d4SSatish Balay cone[1] = 17; 26229371c9d4SSatish Balay cone[2] = 24; 26239371c9d4SSatish Balay cone[3] = 23; 26249371c9d4SSatish Balay cone[4] = 32; 26259371c9d4SSatish Balay cone[5] = 36; 26269371c9d4SSatish Balay cone[6] = 37; 26279371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 26289566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 26299371c9d4SSatish Balay cone[0] = 18; 26309371c9d4SSatish Balay cone[1] = 27; 26319371c9d4SSatish Balay cone[2] = 24; 26329371c9d4SSatish Balay cone[3] = 17; 26339371c9d4SSatish Balay cone[4] = 34; 26349371c9d4SSatish Balay cone[5] = 33; 26359371c9d4SSatish Balay cone[6] = 37; 26369371c9d4SSatish Balay cone[7] = 38; 26379566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 26389371c9d4SSatish Balay cone[0] = 29; 26399371c9d4SSatish Balay cone[1] = 27; 26409371c9d4SSatish Balay cone[2] = 18; 26419371c9d4SSatish Balay cone[3] = 15; 26429371c9d4SSatish Balay cone[4] = 35; 26439371c9d4SSatish Balay cone[5] = 31; 26449371c9d4SSatish Balay cone[6] = 34; 26459371c9d4SSatish Balay cone[7] = 38; 26469566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 26479371c9d4SSatish Balay cone[0] = 29; 26489371c9d4SSatish Balay cone[1] = 15; 26499371c9d4SSatish Balay cone[2] = 16; 26509371c9d4SSatish Balay cone[3] = 23; 26519371c9d4SSatish Balay cone[4] = 35; 26529371c9d4SSatish Balay cone[5] = 36; 26539371c9d4SSatish Balay cone[6] = 32; 26549371c9d4SSatish Balay cone[7] = 31; 26559566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2656006a8963SMatthew G. Knepley 26579371c9d4SSatish Balay cone[0] = 31; 26589371c9d4SSatish Balay cone[1] = 34; 26599371c9d4SSatish Balay cone[2] = 33; 26609371c9d4SSatish Balay cone[3] = 32; 26619371c9d4SSatish Balay cone[4] = 19; 26629371c9d4SSatish Balay cone[5] = 22; 26639371c9d4SSatish Balay cone[6] = 21; 26649371c9d4SSatish Balay cone[7] = 20; 26659566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 26669371c9d4SSatish Balay cone[0] = 32; 26679371c9d4SSatish Balay cone[1] = 33; 26689371c9d4SSatish Balay cone[2] = 37; 26699371c9d4SSatish Balay cone[3] = 36; 26709371c9d4SSatish Balay cone[4] = 22; 26719371c9d4SSatish Balay cone[5] = 25; 26729371c9d4SSatish Balay cone[6] = 26; 26739371c9d4SSatish Balay cone[7] = 21; 26749566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 26759371c9d4SSatish Balay cone[0] = 34; 26769371c9d4SSatish Balay cone[1] = 38; 26779371c9d4SSatish Balay cone[2] = 37; 26789371c9d4SSatish Balay cone[3] = 33; 26799371c9d4SSatish Balay cone[4] = 20; 26809371c9d4SSatish Balay cone[5] = 21; 26819371c9d4SSatish Balay cone[6] = 26; 26829371c9d4SSatish Balay cone[7] = 28; 26839566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 26849371c9d4SSatish Balay cone[0] = 35; 26859371c9d4SSatish Balay cone[1] = 38; 26869371c9d4SSatish Balay cone[2] = 34; 26879371c9d4SSatish Balay cone[3] = 31; 26889371c9d4SSatish Balay cone[4] = 30; 26899371c9d4SSatish Balay cone[5] = 19; 26909371c9d4SSatish Balay cone[6] = 20; 26919371c9d4SSatish Balay cone[7] = 28; 26929566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 26939371c9d4SSatish Balay cone[0] = 35; 26949371c9d4SSatish Balay cone[1] = 31; 26959371c9d4SSatish Balay cone[2] = 32; 26969371c9d4SSatish Balay cone[3] = 36; 26979371c9d4SSatish Balay cone[4] = 30; 26989371c9d4SSatish Balay cone[5] = 25; 26999371c9d4SSatish Balay cone[6] = 22; 27009371c9d4SSatish Balay cone[7] = 19; 27019566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 2702ae8bcbbbSMatthew G. Knepley 27039371c9d4SSatish Balay cone[0] = 19; 27049371c9d4SSatish Balay cone[1] = 20; 27059371c9d4SSatish Balay cone[2] = 21; 27069371c9d4SSatish Balay cone[3] = 22; 27079371c9d4SSatish Balay cone[4] = 15; 27089371c9d4SSatish Balay cone[5] = 16; 27099371c9d4SSatish Balay cone[6] = 17; 27109371c9d4SSatish Balay cone[7] = 18; 27119566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 27129371c9d4SSatish Balay cone[0] = 22; 27139371c9d4SSatish Balay cone[1] = 21; 27149371c9d4SSatish Balay cone[2] = 26; 27159371c9d4SSatish Balay cone[3] = 25; 27169371c9d4SSatish Balay cone[4] = 16; 27179371c9d4SSatish Balay cone[5] = 23; 27189371c9d4SSatish Balay cone[6] = 24; 27199371c9d4SSatish Balay cone[7] = 17; 27209566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 27219371c9d4SSatish Balay cone[0] = 20; 27229371c9d4SSatish Balay cone[1] = 28; 27239371c9d4SSatish Balay cone[2] = 26; 27249371c9d4SSatish Balay cone[3] = 21; 27259371c9d4SSatish Balay cone[4] = 18; 27269371c9d4SSatish Balay cone[5] = 17; 27279371c9d4SSatish Balay cone[6] = 24; 27289371c9d4SSatish Balay cone[7] = 27; 27299566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 27309371c9d4SSatish Balay cone[0] = 30; 27319371c9d4SSatish Balay cone[1] = 28; 27329371c9d4SSatish Balay cone[2] = 20; 27339371c9d4SSatish Balay cone[3] = 19; 27349371c9d4SSatish Balay cone[4] = 29; 27359371c9d4SSatish Balay cone[5] = 15; 27369371c9d4SSatish Balay cone[6] = 18; 27379371c9d4SSatish Balay cone[7] = 27; 27389566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 27399371c9d4SSatish Balay cone[0] = 30; 27409371c9d4SSatish Balay cone[1] = 19; 27419371c9d4SSatish Balay cone[2] = 22; 27429371c9d4SSatish Balay cone[3] = 25; 27439371c9d4SSatish Balay cone[4] = 29; 27449371c9d4SSatish Balay cone[5] = 23; 27459371c9d4SSatish Balay cone[6] = 16; 27469371c9d4SSatish Balay cone[7] = 15; 27479566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 2748006a8963SMatthew G. Knepley } else { 27499371c9d4SSatish Balay cone[0] = 5; 27509371c9d4SSatish Balay cone[1] = 8; 27519371c9d4SSatish Balay cone[2] = 7; 27529371c9d4SSatish Balay cone[3] = 6; 27539371c9d4SSatish Balay cone[4] = 9; 27549371c9d4SSatish Balay cone[5] = 12; 27559371c9d4SSatish Balay cone[6] = 11; 27569371c9d4SSatish Balay cone[7] = 10; 27579566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 27589371c9d4SSatish Balay cone[0] = 6; 27599371c9d4SSatish Balay cone[1] = 7; 27609371c9d4SSatish Balay cone[2] = 14; 27619371c9d4SSatish Balay cone[3] = 13; 27629371c9d4SSatish Balay cone[4] = 12; 27639371c9d4SSatish Balay cone[5] = 15; 27649371c9d4SSatish Balay cone[6] = 16; 27659371c9d4SSatish Balay cone[7] = 11; 27669566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 27679371c9d4SSatish Balay cone[0] = 8; 27689371c9d4SSatish Balay cone[1] = 17; 27699371c9d4SSatish Balay cone[2] = 14; 27709371c9d4SSatish Balay cone[3] = 7; 27719371c9d4SSatish Balay cone[4] = 10; 27729371c9d4SSatish Balay cone[5] = 11; 27739371c9d4SSatish Balay cone[6] = 16; 27749371c9d4SSatish Balay cone[7] = 18; 27759566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 27769371c9d4SSatish Balay cone[0] = 19; 27779371c9d4SSatish Balay cone[1] = 17; 27789371c9d4SSatish Balay cone[2] = 8; 27799371c9d4SSatish Balay cone[3] = 5; 27809371c9d4SSatish Balay cone[4] = 20; 27819371c9d4SSatish Balay cone[5] = 9; 27829371c9d4SSatish Balay cone[6] = 10; 27839371c9d4SSatish Balay cone[7] = 18; 27849566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 27859371c9d4SSatish Balay cone[0] = 19; 27869371c9d4SSatish Balay cone[1] = 5; 27879371c9d4SSatish Balay cone[2] = 6; 27889371c9d4SSatish Balay cone[3] = 13; 27899371c9d4SSatish Balay cone[4] = 20; 27909371c9d4SSatish Balay cone[5] = 15; 27919371c9d4SSatish Balay cone[6] = 12; 27929371c9d4SSatish Balay cone[7] = 9; 27939566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2794006a8963SMatthew G. Knepley } 2795d8c47e87SMatthew G. Knepley } 27969566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 27979566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 27980510c589SMatthew G. Knepley } 2799dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 28000510c589SMatthew G. Knepley { 28010510c589SMatthew G. Knepley Vec coordinates; 28020510c589SMatthew G. Knepley PetscSection coordSection; 28030510c589SMatthew G. Knepley PetscScalar *coords; 28040510c589SMatthew G. Knepley PetscInt coordSize, v; 28050510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 28060510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 28070510c589SMatthew G. Knepley 28080510c589SMatthew G. Knepley /* Build coordinates */ 28099566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 28109566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 28119566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 28129566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 28130510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 28149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 28159566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 28160510c589SMatthew G. Knepley } 28179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 28189566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 28199566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 28209566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 28219566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 28229566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 28239566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 28249566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 2825dd400576SPatrick Sanan if (rank == 0) { 28269371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 28279371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 28289371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 28299371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 28309371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 28319371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 28329371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 28339371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 28349371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 28359371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 28369371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 28379371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 28389371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 28399371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 28409371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 28419371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 28429371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 28439371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 28449371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 28459371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 28469371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 28479371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 28489371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 28499371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 28509371c9d4SSatish Balay coords[8 * dim + 0] = dis; 28519371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 28529371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 28539371c9d4SSatish Balay coords[9 * dim + 0] = dis; 28549371c9d4SSatish Balay coords[9 * dim + 1] = dis; 28559371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 28569371c9d4SSatish Balay coords[10 * dim + 0] = dis; 28579371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 28589371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 28599371c9d4SSatish Balay coords[11 * dim + 0] = dis; 28609371c9d4SSatish Balay coords[11 * dim + 1] = dis; 28619371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 28629371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 28639371c9d4SSatish Balay coords[12 * dim + 1] = dis; 28649371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 28659371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 28669371c9d4SSatish Balay coords[13 * dim + 1] = dis; 28679371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 28689371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 28699371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 28709371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 28719371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 28729371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 28739371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 2874ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 28759371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 28769371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 28779371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 28789371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 28799371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 28809371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 28819371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 28829371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 28839371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 28849371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 28859371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 28869371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 28879371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 28889371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 28899371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 28909371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 28919371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 28929371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 28939371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 28949371c9d4SSatish Balay coords[22 * dim + 1] = dis; 28959371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 28969371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 28979371c9d4SSatish Balay coords[23 * dim + 1] = dis; 28989371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 2899ae8bcbbbSMatthew G. Knepley } 2900d8c47e87SMatthew G. Knepley } 29019566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 29029566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 29039566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 29040510c589SMatthew G. Knepley } 2905006a8963SMatthew G. Knepley /* Create periodicity */ 2906006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 29076858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 29086858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 2909006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 2910ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 29116858538eSMatthew G. Knepley PetscInt numZCells = 3; 2912006a8963SMatthew G. Knepley 29136858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 29146858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 29154fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 2916006a8963SMatthew G. Knepley } 2917dbc1dc17SMatthew G. Knepley { 29189318fe57SMatthew G. Knepley DM cdm; 29199318fe57SMatthew G. Knepley PetscDS cds; 29209318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 2921dbc1dc17SMatthew G. Knepley 2922e65c294aSksagiyam PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE)); 29239566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 29249566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 29259566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 2926dbc1dc17SMatthew G. Knepley } 292746139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 292846139095SJed Brown 29299318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 29309566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 293149704ca5SMatthew G. Knepley 293249704ca5SMatthew G. Knepley char oldprefix[PETSC_MAX_PATH_LEN]; 293349704ca5SMatthew G. Knepley const char *prefix; 293449704ca5SMatthew G. Knepley 293549704ca5SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 293649704ca5SMatthew G. Knepley PetscCall(PetscStrncpy(oldprefix, prefix, PETSC_MAX_PATH_LEN)); 293749704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, "petsc_cyl_ref_")); 293849704ca5SMatthew G. Knepley for (PetscInt r = 0; r < PetscMax(0, Nr); ++r) { 293949704ca5SMatthew G. Knepley DM rdm; 294049704ca5SMatthew G. Knepley 294149704ca5SMatthew G. Knepley PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 294249704ca5SMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &rdm)); 294349704ca5SMatthew G. Knepley } 294449704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldprefix)); 294549704ca5SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, snapToCylinder)); 294649704ca5SMatthew G. Knepley 294749704ca5SMatthew G. Knepley DMLabel bdlabel, edgelabel; 294849704ca5SMatthew G. Knepley IS faceIS; 294949704ca5SMatthew G. Knepley const PetscInt *faces; 295049704ca5SMatthew G. Knepley PetscInt Nf; 295149704ca5SMatthew G. Knepley 295249704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 295349704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 295449704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "generatrix")); 295549704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "generatrix", &edgelabel)); 295649704ca5SMatthew G. Knepley PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 295749704ca5SMatthew G. Knepley // Remove faces on top and bottom 295849704ca5SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(bdlabel, 1, &faceIS)); 2959ba1b3593SJeremy L Thompson if (faceIS) { 296049704ca5SMatthew G. Knepley PetscCall(ISGetLocalSize(faceIS, &Nf)); 296149704ca5SMatthew G. Knepley PetscCall(ISGetIndices(faceIS, &faces)); 296249704ca5SMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 296349704ca5SMatthew G. Knepley PetscReal vol, normal[3]; 296449704ca5SMatthew G. Knepley 296549704ca5SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFVM(dm, faces[f], &vol, NULL, normal)); 296649704ca5SMatthew G. Knepley if (PetscAbsReal(normal[2]) < PETSC_SMALL) PetscCall(DMLabelSetValue(edgelabel, faces[f], 1)); 296749704ca5SMatthew G. Knepley } 296849704ca5SMatthew G. Knepley PetscCall(ISRestoreIndices(faceIS, &faces)); 296949704ca5SMatthew G. Knepley PetscCall(ISDestroy(&faceIS)); 2970ba1b3593SJeremy L Thompson } 297149704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, bdlabel)); 297249704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, edgelabel)); 29733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29740510c589SMatthew G. Knepley } 29750510c589SMatthew G. Knepley 297624119c2aSMatthew G. Knepley /*@ 29779318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 297824119c2aSMatthew G. Knepley 2979d083f849SBarry Smith Collective 298024119c2aSMatthew G. Knepley 298124119c2aSMatthew G. Knepley Input Parameters: 2982a1cb98faSBarry Smith + comm - The communicator for the `DM` object 298349704ca5SMatthew G. Knepley . periodicZ - The boundary type for the Z direction 298449704ca5SMatthew G. Knepley - Nr - The number of refinements to carry out 298524119c2aSMatthew G. Knepley 298624119c2aSMatthew G. Knepley Output Parameter: 298720f4b53cSBarry Smith . dm - The `DM` object 298824119c2aSMatthew G. Knepley 298924119c2aSMatthew G. Knepley Level: beginner 299024119c2aSMatthew G. Knepley 2991a1cb98faSBarry Smith Note: 2992a4e35b19SJacob Faibussowitsch Here is the output numbering looking from the bottom of the cylinder\: 2993a1cb98faSBarry Smith .vb 2994a1cb98faSBarry Smith 17-----14 2995a1cb98faSBarry Smith | | 2996a1cb98faSBarry Smith | 2 | 2997a1cb98faSBarry Smith | | 2998a1cb98faSBarry Smith 17-----8-----7-----14 2999a1cb98faSBarry Smith | | | | 3000a1cb98faSBarry Smith | 3 | 0 | 1 | 3001a1cb98faSBarry Smith | | | | 3002a1cb98faSBarry Smith 19-----5-----6-----13 3003a1cb98faSBarry Smith | | 3004a1cb98faSBarry Smith | 4 | 3005a1cb98faSBarry Smith | | 3006a1cb98faSBarry Smith 19-----13 3007a1cb98faSBarry Smith 3008a1cb98faSBarry Smith and up through the top 3009a1cb98faSBarry Smith 3010a1cb98faSBarry Smith 18-----16 3011a1cb98faSBarry Smith | | 3012a1cb98faSBarry Smith | 2 | 3013a1cb98faSBarry Smith | | 3014a1cb98faSBarry Smith 18----10----11-----16 3015a1cb98faSBarry Smith | | | | 3016a1cb98faSBarry Smith | 3 | 0 | 1 | 3017a1cb98faSBarry Smith | | | | 3018a1cb98faSBarry Smith 20-----9----12-----15 3019a1cb98faSBarry Smith | | 3020a1cb98faSBarry Smith | 4 | 3021a1cb98faSBarry Smith | | 3022a1cb98faSBarry Smith 20-----15 3023a1cb98faSBarry Smith .ve 3024a1cb98faSBarry Smith 30251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 302624119c2aSMatthew G. Knepley @*/ 302749704ca5SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, PetscInt Nr, DM *dm) 3028d71ae5a4SJacob Faibussowitsch { 30299318fe57SMatthew G. Knepley PetscFunctionBegin; 303049704ca5SMatthew G. Knepley PetscAssertPointer(dm, 4); 30319566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 30329566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 303349704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ, Nr)); 30343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30359318fe57SMatthew G. Knepley } 30369318fe57SMatthew G. Knepley 3037d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 3038d71ae5a4SJacob Faibussowitsch { 303924119c2aSMatthew G. Knepley const PetscInt dim = 3; 3040412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 30419fe9f049SMatthew G. Knepley PetscMPIInt rank; 304224119c2aSMatthew G. Knepley 304324119c2aSMatthew G. Knepley PetscFunctionBegin; 304463a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 304546139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 30469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 30479566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 3048412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 30499566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 305024119c2aSMatthew G. Knepley /* Create topology */ 305124119c2aSMatthew G. Knepley { 305224119c2aSMatthew G. Knepley PetscInt cone[6], c; 305324119c2aSMatthew G. Knepley 3054dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 3055dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 30569566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 30579566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 30589566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 305924119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 30609371c9d4SSatish Balay cone[0] = c + n * 1; 30619371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 30629371c9d4SSatish Balay cone[2] = 0 + 3 * n; 30639371c9d4SSatish Balay cone[3] = c + n * 2; 30649371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 30659371c9d4SSatish Balay cone[5] = 1 + 3 * n; 30669566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 30679566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 306824119c2aSMatthew G. Knepley } 30699566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 30709566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 307124119c2aSMatthew G. Knepley } 307248a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 307324119c2aSMatthew G. Knepley /* Create cylinder geometry */ 307424119c2aSMatthew G. Knepley { 307524119c2aSMatthew G. Knepley Vec coordinates; 307624119c2aSMatthew G. Knepley PetscSection coordSection; 307724119c2aSMatthew G. Knepley PetscScalar *coords; 3078412e9a14SMatthew G. Knepley PetscInt coordSize, c; 307924119c2aSMatthew G. Knepley 308024119c2aSMatthew G. Knepley /* Build coordinates */ 30819566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 30829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 30839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 30849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 308524119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 30869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 30879566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 308824119c2aSMatthew G. Knepley } 30899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 30909566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 30919566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 30929566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 30939566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 30949566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 30959566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 30969566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 309724119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 30989371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 30999371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 31009371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 31019371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 31029371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 31039371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 310424119c2aSMatthew G. Knepley } 3105dd400576SPatrick Sanan if (rank == 0) { 31069371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 31079371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 31089371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 31099371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 31109371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 31119371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 31129fe9f049SMatthew G. Knepley } 31139566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 31149566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 31159566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 311624119c2aSMatthew G. Knepley } 311746139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 31189318fe57SMatthew G. Knepley /* Interpolate */ 31199566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 31203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31219318fe57SMatthew G. Knepley } 31229318fe57SMatthew G. Knepley 31239318fe57SMatthew G. Knepley /*@ 31249318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 31259318fe57SMatthew G. Knepley 31269318fe57SMatthew G. Knepley Collective 31279318fe57SMatthew G. Knepley 31289318fe57SMatthew G. Knepley Input Parameters: 3129a1cb98faSBarry Smith + comm - The communicator for the `DM` object 31309318fe57SMatthew G. Knepley . n - The number of wedges around the origin 31319318fe57SMatthew G. Knepley - interpolate - Create edges and faces 31329318fe57SMatthew G. Knepley 31339318fe57SMatthew G. Knepley Output Parameter: 3134a1cb98faSBarry Smith . dm - The `DM` object 31359318fe57SMatthew G. Knepley 31369318fe57SMatthew G. Knepley Level: beginner 31379318fe57SMatthew G. Knepley 31381cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 31399318fe57SMatthew G. Knepley @*/ 3140d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 3141d71ae5a4SJacob Faibussowitsch { 31429318fe57SMatthew G. Knepley PetscFunctionBegin; 31434f572ea9SToby Isaac PetscAssertPointer(dm, 4); 31449566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 31459566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 31469566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 31473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 314824119c2aSMatthew G. Knepley } 314924119c2aSMatthew G. Knepley 3150d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 3151d71ae5a4SJacob Faibussowitsch { 315265a81367SMatthew G. Knepley PetscReal prod = 0.0; 315365a81367SMatthew G. Knepley PetscInt i; 315465a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 315565a81367SMatthew G. Knepley return PetscSqrtReal(prod); 315665a81367SMatthew G. Knepley } 3157dd2b43ebSStefano Zampini 3158d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 3159d71ae5a4SJacob Faibussowitsch { 316065a81367SMatthew G. Knepley PetscReal prod = 0.0; 316165a81367SMatthew G. Knepley PetscInt i; 316265a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += x[i] * y[i]; 316365a81367SMatthew G. Knepley return prod; 316465a81367SMatthew G. Knepley } 316565a81367SMatthew G. Knepley 316651a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 3167d71ae5a4SJacob 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[]) 3168d71ae5a4SJacob Faibussowitsch { 316951a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 317051a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 317151a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 317251a74b61SMatthew G. Knepley 317351a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 317451a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 317551a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 317651a74b61SMatthew G. Knepley } 317751a74b61SMatthew G. Knepley 3178d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 3179d71ae5a4SJacob Faibussowitsch { 318065a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 318165a81367SMatthew G. Knepley PetscSection coordSection; 318265a81367SMatthew G. Knepley Vec coordinates; 318365a81367SMatthew G. Knepley PetscScalar *coords; 318465a81367SMatthew G. Knepley PetscReal *coordsIn; 318507c565c5SJose E. Roman PetscInt numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, e; 318665a81367SMatthew G. Knepley PetscMPIInt rank; 318765a81367SMatthew G. Knepley 318865a81367SMatthew G. Knepley PetscFunctionBegin; 31899318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 319046139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 31919566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 31929566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 31939566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 319465a81367SMatthew G. Knepley switch (dim) { 31955c344501SMatthew G. Knepley case 1: 31965c344501SMatthew G. Knepley numCells = 16; 31975c344501SMatthew G. Knepley numVerts = numCells; 31985c344501SMatthew G. Knepley 31995c344501SMatthew G. Knepley // Build Topology 32005c344501SMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 32015c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 32025c344501SMatthew G. Knepley PetscCall(DMSetUp(dm)); 32035c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 32045c344501SMatthew G. Knepley PetscInt cone[2]; 32055c344501SMatthew G. Knepley 32065c344501SMatthew G. Knepley cone[0] = c + numCells; 32075c344501SMatthew G. Knepley cone[1] = (c + 1) % numVerts + numCells; 32085c344501SMatthew G. Knepley PetscCall(DMPlexSetCone(dm, c, cone)); 32095c344501SMatthew G. Knepley } 32105c344501SMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 32115c344501SMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 32125c344501SMatthew G. Knepley PetscCall(PetscMalloc1(numVerts * embedDim, &coordsIn)); 32135c344501SMatthew G. Knepley for (PetscInt v = 0; v < numVerts; ++v) { 32145c344501SMatthew G. Knepley const PetscReal rad = 2. * PETSC_PI * v / numVerts; 32155c344501SMatthew G. Knepley 32165c344501SMatthew G. Knepley coordsIn[v * embedDim + 0] = PetscCosReal(rad); 32175c344501SMatthew G. Knepley coordsIn[v * embedDim + 1] = PetscSinReal(rad); 32185c344501SMatthew G. Knepley } 32195c344501SMatthew G. Knepley break; 322065a81367SMatthew G. Knepley case 2: 322165a81367SMatthew G. Knepley if (simplex) { 322251a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 322351a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 322465a81367SMatthew G. Knepley const PetscInt degree = 5; 322551a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 322665a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 322765a81367SMatthew G. Knepley PetscInt cone[3]; 322807c565c5SJose E. Roman PetscInt *graph; 322965a81367SMatthew G. Knepley 32309371c9d4SSatish Balay vertex[0] *= R / radius; 32319371c9d4SSatish Balay vertex[1] *= R / radius; 32329371c9d4SSatish Balay vertex[2] *= R / radius; 3233dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 3234dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 323565a81367SMatthew G. Knepley firstVertex = numCells; 323651a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 323765a81367SMatthew G. Knepley 323865a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 323965a81367SMatthew G. Knepley 324065a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 324151a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 324265a81367SMatthew G. Knepley */ 324365a81367SMatthew G. Knepley /* Construct vertices */ 32449566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3245dd400576SPatrick Sanan if (rank == 0) { 324607c565c5SJose E. Roman for (PetscInt p = 0, i = 0; p < embedDim; ++p) { 324765a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 324865a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 324965a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 325065a81367SMatthew G. Knepley ++i; 325165a81367SMatthew G. Knepley } 325265a81367SMatthew G. Knepley } 325365a81367SMatthew G. Knepley } 325445da822fSValeria Barra } 325565a81367SMatthew G. Knepley /* Construct graph */ 32569566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 325707c565c5SJose E. Roman for (PetscInt i = 0; i < numVerts; ++i) { 325807c565c5SJose E. Roman PetscInt k = 0; 325907c565c5SJose E. Roman for (PetscInt j = 0; j < numVerts; ++j) { 32609371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 32619371c9d4SSatish Balay graph[i * numVerts + j] = 1; 32629371c9d4SSatish Balay ++k; 32639371c9d4SSatish Balay } 326465a81367SMatthew G. Knepley } 326563a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 326665a81367SMatthew G. Knepley } 326765a81367SMatthew G. Knepley /* Build Topology */ 32689566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 326907c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 32709566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 327165a81367SMatthew G. Knepley /* Cells */ 327207c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 327307c565c5SJose E. Roman for (PetscInt j = 0; j < i; ++j) { 327407c565c5SJose E. Roman for (PetscInt k = 0; k < j; ++k) { 327565a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 32769371c9d4SSatish Balay cone[0] = firstVertex + i; 32779371c9d4SSatish Balay cone[1] = firstVertex + j; 32789371c9d4SSatish Balay cone[2] = firstVertex + k; 327965a81367SMatthew G. Knepley /* Check orientation */ 328065a81367SMatthew G. Knepley { 32819371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 32829371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 32839371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 32849371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 32859371c9d4SSatish Balay }; 328665a81367SMatthew G. Knepley PetscReal normal[3]; 328765a81367SMatthew G. Knepley PetscInt e, f; 328865a81367SMatthew G. Knepley 328965a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 329065a81367SMatthew G. Knepley normal[d] = 0.0; 329165a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3292ad540459SPierre 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]); 329365a81367SMatthew G. Knepley } 329465a81367SMatthew G. Knepley } 32959371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 32969371c9d4SSatish Balay PetscInt tmp = cone[1]; 32979371c9d4SSatish Balay cone[1] = cone[2]; 32989371c9d4SSatish Balay cone[2] = tmp; 329965a81367SMatthew G. Knepley } 330065a81367SMatthew G. Knepley } 33019566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 330265a81367SMatthew G. Knepley } 330365a81367SMatthew G. Knepley } 330465a81367SMatthew G. Knepley } 330565a81367SMatthew G. Knepley } 33069566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 33079566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 33089566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 330965a81367SMatthew G. Knepley } else { 33102829fed8SMatthew G. Knepley /* 33112829fed8SMatthew G. Knepley 12-21--13 33122829fed8SMatthew G. Knepley | | 33132829fed8SMatthew G. Knepley 25 4 24 33142829fed8SMatthew G. Knepley | | 33152829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 33162829fed8SMatthew G. Knepley | | | | 33172829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 33182829fed8SMatthew G. Knepley | | | | 33192829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 33202829fed8SMatthew G. Knepley | | 33212829fed8SMatthew G. Knepley 20 1 19 33222829fed8SMatthew G. Knepley | | 33232829fed8SMatthew G. Knepley 10-18--11 33242829fed8SMatthew G. Knepley | | 33252829fed8SMatthew G. Knepley 23 2 22 33262829fed8SMatthew G. Knepley | | 33272829fed8SMatthew G. Knepley 12-21--13 33282829fed8SMatthew G. Knepley */ 33292829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 33302829fed8SMatthew G. Knepley 3331dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 3332dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 3333dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 333465a81367SMatthew G. Knepley firstVertex = numCells; 333565a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 33362829fed8SMatthew G. Knepley /* Build Topology */ 33379566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 333807c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 333948a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 33409566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3341dd400576SPatrick Sanan if (rank == 0) { 33422829fed8SMatthew G. Knepley /* Cell 0 */ 33439371c9d4SSatish Balay cone[0] = 14; 33449371c9d4SSatish Balay cone[1] = 15; 33459371c9d4SSatish Balay cone[2] = 16; 33469371c9d4SSatish Balay cone[3] = 17; 33479566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 33489371c9d4SSatish Balay ornt[0] = 0; 33499371c9d4SSatish Balay ornt[1] = 0; 33509371c9d4SSatish Balay ornt[2] = 0; 33519371c9d4SSatish Balay ornt[3] = 0; 33529566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 33532829fed8SMatthew G. Knepley /* Cell 1 */ 33549371c9d4SSatish Balay cone[0] = 18; 33559371c9d4SSatish Balay cone[1] = 19; 33569371c9d4SSatish Balay cone[2] = 14; 33579371c9d4SSatish Balay cone[3] = 20; 33589566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 33599371c9d4SSatish Balay ornt[0] = 0; 33609371c9d4SSatish Balay ornt[1] = 0; 33619371c9d4SSatish Balay ornt[2] = -1; 33629371c9d4SSatish Balay ornt[3] = 0; 33639566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 33642829fed8SMatthew G. Knepley /* Cell 2 */ 33659371c9d4SSatish Balay cone[0] = 21; 33669371c9d4SSatish Balay cone[1] = 22; 33679371c9d4SSatish Balay cone[2] = 18; 33689371c9d4SSatish Balay cone[3] = 23; 33699566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 33709371c9d4SSatish Balay ornt[0] = 0; 33719371c9d4SSatish Balay ornt[1] = 0; 33729371c9d4SSatish Balay ornt[2] = -1; 33739371c9d4SSatish Balay ornt[3] = 0; 33749566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 33752829fed8SMatthew G. Knepley /* Cell 3 */ 33769371c9d4SSatish Balay cone[0] = 19; 33779371c9d4SSatish Balay cone[1] = 22; 33789371c9d4SSatish Balay cone[2] = 24; 33799371c9d4SSatish Balay cone[3] = 15; 33809566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 33819371c9d4SSatish Balay ornt[0] = -1; 33829371c9d4SSatish Balay ornt[1] = -1; 33839371c9d4SSatish Balay ornt[2] = 0; 33849371c9d4SSatish Balay ornt[3] = -1; 33859566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 33862829fed8SMatthew G. Knepley /* Cell 4 */ 33879371c9d4SSatish Balay cone[0] = 16; 33889371c9d4SSatish Balay cone[1] = 24; 33899371c9d4SSatish Balay cone[2] = 21; 33909371c9d4SSatish Balay cone[3] = 25; 33919566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 33929371c9d4SSatish Balay ornt[0] = -1; 33939371c9d4SSatish Balay ornt[1] = -1; 33949371c9d4SSatish Balay ornt[2] = -1; 33959371c9d4SSatish Balay ornt[3] = 0; 33969566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 33972829fed8SMatthew G. Knepley /* Cell 5 */ 33989371c9d4SSatish Balay cone[0] = 20; 33999371c9d4SSatish Balay cone[1] = 17; 34009371c9d4SSatish Balay cone[2] = 25; 34019371c9d4SSatish Balay cone[3] = 23; 34029566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 34039371c9d4SSatish Balay ornt[0] = -1; 34049371c9d4SSatish Balay ornt[1] = -1; 34059371c9d4SSatish Balay ornt[2] = -1; 34069371c9d4SSatish Balay ornt[3] = -1; 34079566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 34082829fed8SMatthew G. Knepley /* Edges */ 34099371c9d4SSatish Balay cone[0] = 6; 34109371c9d4SSatish Balay cone[1] = 7; 34119566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 34129371c9d4SSatish Balay cone[0] = 7; 34139371c9d4SSatish Balay cone[1] = 8; 34149566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 34159371c9d4SSatish Balay cone[0] = 8; 34169371c9d4SSatish Balay cone[1] = 9; 34179566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 34189371c9d4SSatish Balay cone[0] = 9; 34199371c9d4SSatish Balay cone[1] = 6; 34209566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 34219371c9d4SSatish Balay cone[0] = 10; 34229371c9d4SSatish Balay cone[1] = 11; 34239566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 34249371c9d4SSatish Balay cone[0] = 11; 34259371c9d4SSatish Balay cone[1] = 7; 34269566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 34279371c9d4SSatish Balay cone[0] = 6; 34289371c9d4SSatish Balay cone[1] = 10; 34299566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 34309371c9d4SSatish Balay cone[0] = 12; 34319371c9d4SSatish Balay cone[1] = 13; 34329566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 34339371c9d4SSatish Balay cone[0] = 13; 34349371c9d4SSatish Balay cone[1] = 11; 34359566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 34369371c9d4SSatish Balay cone[0] = 10; 34379371c9d4SSatish Balay cone[1] = 12; 34389566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 34399371c9d4SSatish Balay cone[0] = 13; 34409371c9d4SSatish Balay cone[1] = 8; 34419566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 34429371c9d4SSatish Balay cone[0] = 12; 34439371c9d4SSatish Balay cone[1] = 9; 34449566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 344545da822fSValeria Barra } 34469566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 34479566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 34482829fed8SMatthew G. Knepley /* Build coordinates */ 34499566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3450dd400576SPatrick Sanan if (rank == 0) { 34519371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 34529371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 34539371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 34549371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 34559371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 34569371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 34579371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 34589371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 34599371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 34609371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 34619371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 34629371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 34639371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 34649371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 34659371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 34669371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 34679371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 34689371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 34699371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 34709371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 34719371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 34729371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 34739371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 34749371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 347565a81367SMatthew G. Knepley } 347645da822fSValeria Barra } 347765a81367SMatthew G. Knepley break; 347865a81367SMatthew G. Knepley case 3: 3479116ded15SMatthew G. Knepley if (simplex) { 3480116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 348151a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 348251a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 348351a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 3484116ded15SMatthew G. Knepley const PetscInt degree = 12; 3485116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 34869371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 34879371c9d4SSatish Balay {0, 1, 2, 3}, 34889371c9d4SSatish Balay {0, 2, 3, 1}, 34899371c9d4SSatish Balay {0, 3, 1, 2}, 34909371c9d4SSatish Balay {1, 0, 3, 2}, 34919371c9d4SSatish Balay {1, 2, 0, 3}, 34929371c9d4SSatish Balay {1, 3, 2, 0}, 34939371c9d4SSatish Balay {2, 0, 1, 3}, 34949371c9d4SSatish Balay {2, 1, 3, 0}, 34959371c9d4SSatish Balay {2, 3, 0, 1}, 34969371c9d4SSatish Balay {3, 0, 2, 1}, 34979371c9d4SSatish Balay {3, 1, 0, 2}, 34989371c9d4SSatish Balay {3, 2, 1, 0} 34999371c9d4SSatish Balay }; 3500116ded15SMatthew G. Knepley PetscInt cone[4]; 3501116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 3502116ded15SMatthew G. Knepley 35039371c9d4SSatish Balay vertexA[0] *= R; 35049371c9d4SSatish Balay vertexA[1] *= R; 35059371c9d4SSatish Balay vertexA[2] *= R; 35069371c9d4SSatish Balay vertexA[3] *= R; 35079371c9d4SSatish Balay vertexB[0] *= R; 35089371c9d4SSatish Balay vertexB[1] *= R; 35099371c9d4SSatish Balay vertexB[2] *= R; 35109371c9d4SSatish Balay vertexB[3] *= R; 35119371c9d4SSatish Balay vertexC[0] *= R; 35129371c9d4SSatish Balay vertexC[1] *= R; 35139371c9d4SSatish Balay vertexC[2] *= R; 35149371c9d4SSatish Balay vertexC[3] *= R; 3515dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 3516dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 3517116ded15SMatthew G. Knepley firstVertex = numCells; 3518116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 3519116ded15SMatthew G. Knepley 3520116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 3521116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 3522116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 3523116ded15SMatthew G. Knepley 3524116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 35256333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 3526116ded15SMatthew G. Knepley 3527116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 3528116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 3529116ded15SMatthew G. Knepley */ 3530116ded15SMatthew G. Knepley /* Construct vertices */ 35319566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3532116ded15SMatthew G. Knepley i = 0; 3533dd400576SPatrick Sanan if (rank == 0) { 3534116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3535116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3536116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3537116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 3538116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 3539116ded15SMatthew G. Knepley ++i; 3540116ded15SMatthew G. Knepley } 3541116ded15SMatthew G. Knepley } 3542116ded15SMatthew G. Knepley } 3543116ded15SMatthew G. Knepley } 3544116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 3545116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 3546116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3547116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 3548116ded15SMatthew G. Knepley ++i; 3549116ded15SMatthew G. Knepley } 3550116ded15SMatthew G. Knepley } 3551116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 3552116ded15SMatthew G. Knepley s[3] = 1; 3553116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3554116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3555116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3556116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 3557116ded15SMatthew G. Knepley ++i; 3558116ded15SMatthew G. Knepley } 3559116ded15SMatthew G. Knepley } 3560116ded15SMatthew G. Knepley } 3561116ded15SMatthew G. Knepley } 356245da822fSValeria Barra } 356363a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 3564116ded15SMatthew G. Knepley /* Construct graph */ 35659566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 3566116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 3567116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 35689371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 35699371c9d4SSatish Balay graph[i * numVerts + j] = 1; 35709371c9d4SSatish Balay ++k; 35719371c9d4SSatish Balay } 3572116ded15SMatthew G. Knepley } 357363a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 3574116ded15SMatthew G. Knepley } 3575116ded15SMatthew G. Knepley /* Build Topology */ 35769566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 357707c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 35789566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3579116ded15SMatthew G. Knepley /* Cells */ 3580dd400576SPatrick Sanan if (rank == 0) { 358107c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 3582116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 3583116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 3584116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 35859371c9d4SSatish 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]) { 35869371c9d4SSatish Balay cone[0] = firstVertex + i; 35879371c9d4SSatish Balay cone[1] = firstVertex + j; 35889371c9d4SSatish Balay cone[2] = firstVertex + k; 35899371c9d4SSatish Balay cone[3] = firstVertex + l; 3590116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 3591116ded15SMatthew G. Knepley { 35929371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 35939371c9d4SSatish 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}}}, 3594116ded15SMatthew G. Knepley 35959371c9d4SSatish 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}}}, 3596116ded15SMatthew G. Knepley 35979371c9d4SSatish 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}}}, 3598116ded15SMatthew G. Knepley 35999371c9d4SSatish 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}} } 36009371c9d4SSatish Balay }; 3601116ded15SMatthew G. Knepley PetscReal normal[4]; 3602116ded15SMatthew G. Knepley PetscInt e, f, g; 3603116ded15SMatthew G. Knepley 3604116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 3605116ded15SMatthew G. Knepley normal[d] = 0.0; 3606116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3607116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 3608116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 3609116ded15SMatthew 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]); 3610116ded15SMatthew G. Knepley } 3611116ded15SMatthew G. Knepley } 3612116ded15SMatthew G. Knepley } 3613116ded15SMatthew G. Knepley } 36149371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 36159371c9d4SSatish Balay PetscInt tmp = cone[1]; 36169371c9d4SSatish Balay cone[1] = cone[2]; 36179371c9d4SSatish Balay cone[2] = tmp; 36189371c9d4SSatish Balay } 3619116ded15SMatthew G. Knepley } 36209566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 3621116ded15SMatthew G. Knepley } 3622116ded15SMatthew G. Knepley } 3623116ded15SMatthew G. Knepley } 3624116ded15SMatthew G. Knepley } 3625116ded15SMatthew G. Knepley } 362645da822fSValeria Barra } 36279566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 36289566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 36299566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 3630116ded15SMatthew G. Knepley } 3631f4d061e9SPierre Jolivet break; 3632d71ae5a4SJacob Faibussowitsch default: 3633d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 363465a81367SMatthew G. Knepley } 363565a81367SMatthew G. Knepley /* Create coordinates */ 36369566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 36379566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 36389566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 36399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 36402829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 36419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 36429566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 36432829fed8SMatthew G. Knepley } 36449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 36459566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 36469566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 36479566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 36489566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 36499566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 36509566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 36519566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 36529371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 3653ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 36549566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 36559566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 36569566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 36579566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 365851a74b61SMatthew G. Knepley { 365951a74b61SMatthew G. Knepley DM cdm; 366051a74b61SMatthew G. Knepley PetscDS cds; 36619318fe57SMatthew G. Knepley PetscScalar c = R; 366251a74b61SMatthew G. Knepley 3663509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, snapToSphere)); 3664e65c294aSksagiyam PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE)); 36659566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 36669566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 36679566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 366851a74b61SMatthew G. Knepley } 366946139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 36709318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 36719566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 36723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36739318fe57SMatthew G. Knepley } 36749318fe57SMatthew G. Knepley 3675b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 3676b7f5c055SJed Brown 3677b7f5c055SJed Brown /* 3678b7f5c055SJed Brown The Schwarz P implicit surface is 3679b7f5c055SJed Brown 3680b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 3681b7f5c055SJed Brown */ 3682d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3683d71ae5a4SJacob Faibussowitsch { 3684b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 3685b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 3686b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 3687b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3688b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 3689ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 3690b7f5c055SJed Brown } 3691b7f5c055SJed Brown } 3692b7f5c055SJed Brown 36934663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3694d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3695d71ae5a4SJacob Faibussowitsch { 3696ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 36973ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 36984663dae6SJed Brown } 36994663dae6SJed Brown 3700b7f5c055SJed Brown /* 3701b7f5c055SJed Brown The Gyroid implicit surface is 3702b7f5c055SJed Brown 3703b7f5c055SJed 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) 3704b7f5c055SJed Brown 3705b7f5c055SJed Brown */ 3706d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3707d71ae5a4SJacob Faibussowitsch { 3708b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 3709b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 3710b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 3711b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 3712b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 3713b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 3714b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 3715b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3716b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3717b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 3718b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3719b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3720b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 3721b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3722b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3723b7f5c055SJed Brown } 3724b7f5c055SJed Brown 37254663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3726d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3727d71ae5a4SJacob Faibussowitsch { 37284663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 37294663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 37304663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 37314663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 37324663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 37333ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 37344663dae6SJed Brown } 37354663dae6SJed Brown 3736b7f5c055SJed Brown /* 3737b7f5c055SJed Brown We wish to solve 3738b7f5c055SJed Brown 3739b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 3740b7f5c055SJed Brown 3741b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 3742b7f5c055SJed 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 3743b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 3744b7f5c055SJed Brown 3745b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 3746b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 3747b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 3748b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 3749da81f932SPierre Jolivet Since Q is symmetric, this is equivalent to multiplying by Q and taking the last two entries. 3750b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 3751b7f5c055SJed Brown 3752b7f5c055SJed Brown f(y) = 0 1 equation 3753b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 3754b7f5c055SJed Brown 3755b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 3756b7f5c055SJed Brown */ 3757d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 3758d71ae5a4SJacob Faibussowitsch { 3759b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 3760b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 37612f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 37629371c9d4SSatish Balay PetscReal n_y[3][3] = { 37639371c9d4SSatish Balay {0, 0, 0}, 37649371c9d4SSatish Balay {0, 0, 0}, 37659371c9d4SSatish Balay {0, 0, 0} 37669371c9d4SSatish Balay }; 3767b7f5c055SJed Brown 3768b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 3769b7f5c055SJed Brown 3770b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 3771b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3772ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 3773b7f5c055SJed Brown 3774b7f5c055SJed Brown // Define the Householder reflector 3775b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 3776b7f5c055SJed Brown n[0] += norm * sign; 3777b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 3778b7f5c055SJed Brown 3779b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3780b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 3781b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 3782b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 3783b7f5c055SJed Brown 3784b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3785b7f5c055SJed Brown n[i] /= norm; 3786b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3787b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 3788b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 3789b7f5c055SJed Brown } 3790b7f5c055SJed Brown } 3791b7f5c055SJed Brown 3792b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 3793b7f5c055SJed 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]; 3794b7f5c055SJed Brown 3795b7f5c055SJed Brown res[0] = f; 3796b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 3797b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 3798b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 3799b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3800b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 3801b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 3802b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 3803b7f5c055SJed Brown } 3804b7f5c055SJed Brown } 3805b7f5c055SJed Brown 3806b7f5c055SJed Brown /* 3807b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 3808b7f5c055SJed Brown */ 3809d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 3810d71ae5a4SJacob Faibussowitsch { 3811b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 3812b7f5c055SJed Brown 3813b7f5c055SJed Brown PetscFunctionBegin; 3814b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 3815b7f5c055SJed Brown PetscScalar res[3], J[9]; 3816b7f5c055SJed Brown PetscReal resnorm; 3817b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 3818b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 3819b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 382063a3b9bcSJacob 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]))); 3821b7f5c055SJed Brown } 3822b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 3823b7f5c055SJed Brown 3824b7f5c055SJed Brown // Take the Newton step 38259566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 3826b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 3827b7f5c055SJed Brown } 3828b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 38293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3830b7f5c055SJed Brown } 3831b7f5c055SJed Brown 3832b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 3833b7f5c055SJed Brown 3834d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 3835d71ae5a4SJacob Faibussowitsch { 3836b7f5c055SJed Brown PetscMPIInt rank; 3837b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 3838b7f5c055SJed Brown PetscInt (*edges)[2] = NULL, *edgeSets = NULL; 3839b7f5c055SJed Brown PetscInt *cells_flat = NULL; 3840b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 3841b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 38428434afd1SBarry Smith PetscSimplePointFn *normalFunc = NULL; 3843b7f5c055SJed Brown DMLabel label; 3844b7f5c055SJed Brown 3845b7f5c055SJed Brown PetscFunctionBegin; 384646139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 38479566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 384863a3b9bcSJacob 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); 3849b7f5c055SJed Brown switch (tpstype) { 3850b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 3851b7f5c055SJed 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"); 3852c5853193SPierre Jolivet if (rank == 0) { 3853b7f5c055SJed Brown PetscInt (*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 3854b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 3855b7f5c055SJed Brown PetscReal L = 1; 3856b7f5c055SJed Brown 3857b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 3858b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 3859b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 3860b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 3861b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 3862b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 38639566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 38649566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 38659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 38669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 3867b7f5c055SJed Brown // x-normal pipes 3868b7f5c055SJed Brown vcount = 0; 3869b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 3870b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3871b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3872b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3873b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 3874b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3875b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3876b7f5c055SJed Brown } 3877b7f5c055SJed Brown } 3878b7f5c055SJed Brown } 3879b7f5c055SJed Brown } 3880b7f5c055SJed Brown // y-normal pipes 3881b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3882b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 3883b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3884b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3885b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3886b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 3887b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3888b7f5c055SJed Brown } 3889b7f5c055SJed Brown } 3890b7f5c055SJed Brown } 3891b7f5c055SJed Brown } 3892b7f5c055SJed Brown // z-normal pipes 3893b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3894b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3895b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 3896b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3897b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3898b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3899b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 3900b7f5c055SJed Brown } 3901b7f5c055SJed Brown } 3902b7f5c055SJed Brown } 3903b7f5c055SJed Brown } 3904b7f5c055SJed Brown // junctions 3905b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3906b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3907b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3908b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 3909b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 3910b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 3911b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 3912b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 3913b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 3914b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 3915b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 3916b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 3917b7f5c055SJed Brown } 3918b7f5c055SJed Brown } 3919b7f5c055SJed Brown } 3920b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 3921b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 3922b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 3923b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 3924b7f5c055SJed Brown }; 3925b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 39269371c9d4SSatish 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}; 3927b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 39289371c9d4SSatish 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}; 3929b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 3930b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 3931b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 3932b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 3933b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 3934b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 3935b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 3936b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 3937b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 3938b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 3939b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 3940b7f5c055SJed Brown if (ijk[dir] == 0) { 3941b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 3942b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 3943b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 3944b7f5c055SJed Brown numEdges++; 3945b7f5c055SJed Brown } 3946b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 3947b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 3948b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 3949b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 3950b7f5c055SJed Brown numEdges++; 3951b7f5c055SJed Brown } 3952b7f5c055SJed Brown } 3953b7f5c055SJed Brown } 3954b7f5c055SJed Brown } 3955b7f5c055SJed Brown } 3956b7f5c055SJed Brown } 395763a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 3958b7f5c055SJed Brown numFaces = 24 * Njunctions; 3959b7f5c055SJed Brown cells_flat = cells[0][0][0]; 3960b7f5c055SJed Brown } 3961b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 39624663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 3963b7f5c055SJed Brown break; 3964b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 3965c5853193SPierre Jolivet if (rank == 0) { 3966b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 3967b7f5c055SJed Brown // 3968b7f5c055SJed 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) 3969b7f5c055SJed Brown // 3970b7f5c055SJed Brown // on the cell [0,2]^3. 3971b7f5c055SJed Brown // 3972b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 3973b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 3974b7f5c055SJed Brown // like a boomerang: 3975b7f5c055SJed Brown // 3976b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 3977b7f5c055SJed Brown // ----- ------- ------- ------- // 3978b7f5c055SJed Brown // // 3979b7f5c055SJed Brown // + + + + + + + \ + // 3980b7f5c055SJed Brown // \ / \ // 3981b7f5c055SJed Brown // \ `-_ _-' / } // 3982b7f5c055SJed Brown // *-_ `-' _-' / // 3983b7f5c055SJed Brown // + `-+ + + +-' + + / + // 3984b7f5c055SJed Brown // // 3985b7f5c055SJed Brown // // 3986b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 3987b7f5c055SJed Brown // ----- ------- ------- ------- // 3988b7f5c055SJed Brown // // 3989b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 3990b7f5c055SJed Brown // `-_ _-_ _-` / // 3991b7f5c055SJed Brown // \ _-' `-_ / { // 3992b7f5c055SJed Brown // \ / \ // 3993b7f5c055SJed Brown // + + + + + + + \ + // 3994b7f5c055SJed Brown // 3995b7f5c055SJed Brown // 3996b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 3997b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 3998b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 3999b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 4000b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 4001b7f5c055SJed Brown // 4002b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 4003b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 4004b7f5c055SJed Brown // 4005b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 4006b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 4007b7f5c055SJed Brown 4008b7f5c055SJed Brown PetscInt facesPerBlock = 64; 4009b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 4010b7f5c055SJed Brown PetscInt extentPlus[3]; 4011b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 40129371c9d4SSatish 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; 40139371c9d4SSatish Balay const PetscInt pattern[64][4] = { 40149371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 4015b7f5c055SJed Brown /* layer 0 */ 40169371c9d4SSatish Balay {A, C, K, G }, 40179371c9d4SSatish Balay {C, B, II, K }, 40189371c9d4SSatish Balay {D, A, H, L }, 40199371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 40209371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 40219371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 40229371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 40239371c9d4SSatish Balay {B, F, M, II }, 4024b7f5c055SJed Brown /* layer 1 */ 40259371c9d4SSatish Balay {G, K, Q, O }, 40269371c9d4SSatish Balay {K, II, P, Q }, 40279371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 40289371c9d4SSatish Balay {J, L, R, P }, 40299371c9d4SSatish Balay {N, J, P, S }, 40309371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 40319371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 40329371c9d4SSatish Balay {II, M, T, P }, 4033b7f5c055SJed Brown /* layer 2 */ 40349371c9d4SSatish Balay {O, Q, Y, U }, 40359371c9d4SSatish Balay {Q, P, W, Y }, 40369371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 40379371c9d4SSatish Balay {P, R, Ap, W }, 40389371c9d4SSatish Balay {S, P, X, Bp }, 40399371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 40409371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 40419371c9d4SSatish Balay {P, T, Z, X }, 4042b7f5c055SJed Brown /* layer 3 */ 40439371c9d4SSatish Balay {U, Y, Ep, Dp }, 40449371c9d4SSatish Balay {Y, W, Cp, Ep }, 40459371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 40469371c9d4SSatish Balay {W, Ap, Gp, Cp }, 40479371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 40489371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 40499371c9d4SSatish Balay {Z, V, Dp, Hp }, 40509371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 4051b7f5c055SJed Brown /* layer 4 */ 40529371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 40539371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 40549371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 40559371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 40569371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 40579371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 40589371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 40599371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 4060b7f5c055SJed Brown /* layer 5 */ 40619371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 40629371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 40639371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 40649371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 40659371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 40669371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 40679371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 40689371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 4069b7f5c055SJed Brown /* layer 6 */ 40709371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 40719371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 40729371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 40739371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 40749371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 40759371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 40769371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 40779371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 4078b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 40799371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 40809371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 40819371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 40829371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 40839371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 40849371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 40859371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 40869371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 4087b7f5c055SJed Brown }; 4088b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 40899371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 4090bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 4091bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 4092bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 4093bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 4094bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 4095bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 4096b7f5c055SJed Brown 4097bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 4098bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 4099bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 4100bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 4101bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 4102bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 4103bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 4104bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 4105b7f5c055SJed Brown 4106bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 4107bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 4108bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 4109bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 4110bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 4111bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 4112b7f5c055SJed Brown 4113bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 4114bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 4115bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 4116bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 4117bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 4118bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 4119bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 4120bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 4121b7f5c055SJed Brown 4122bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 4123bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 4124bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 4125bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 4126bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 4127bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 4128b7f5c055SJed Brown 4129bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 4130bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 4131bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 4132bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 4133bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 4134bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 4135bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 4136bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 4137b7f5c055SJed Brown 4138bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 4139bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 4140bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 4141bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 4142bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 4143bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 4144b7f5c055SJed Brown 4145bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 4146bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 4147bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 4148bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 4149bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 4150bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 4151bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 4152bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 4153b7f5c055SJed Brown }; 4154b7f5c055SJed Brown PetscInt (*cells)[64][4] = NULL; 4155b7f5c055SJed Brown PetscBool *seen; 4156b7f5c055SJed Brown PetscInt *vertToTrueVert; 4157b7f5c055SJed Brown PetscInt count; 4158b7f5c055SJed Brown 4159b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 4160b7f5c055SJed Brown numBlocks = 1; 4161b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 4162b7f5c055SJed Brown numBlocksPlus = 1; 4163b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 4164b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 41659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 41669566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 4167b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 4168b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 4169b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 4170b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 4171b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 4172b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 4173b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 4174b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 4175b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 4176b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 4177b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 4178b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 4179b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 4180b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 4181b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 4182b7f5c055SJed Brown 4183b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 4184b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 4185b7f5c055SJed Brown } 4186b7f5c055SJed Brown } 4187b7f5c055SJed Brown } 4188b7f5c055SJed Brown } 4189b7f5c055SJed Brown } 41909371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 41919371c9d4SSatish Balay if (seen[i]) numVertices++; 4192b7f5c055SJed Brown count = 0; 41939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 41949566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 4195b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 4196b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 4197b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 4198b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 4199b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 4200b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 4201b7f5c055SJed Brown 4202b7f5c055SJed Brown if (seen[vIdx]) { 4203b7f5c055SJed Brown PetscInt thisVert; 4204b7f5c055SJed Brown 4205b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 4206b7f5c055SJed Brown 4207b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 4208b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 4209b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 4210b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 4211b7f5c055SJed Brown } 4212b7f5c055SJed Brown } 4213b7f5c055SJed Brown } 4214b7f5c055SJed Brown } 4215b7f5c055SJed Brown } 4216b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 4217b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 4218ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 4219b7f5c055SJed Brown } 4220b7f5c055SJed Brown } 42219566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 42229566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 4223b7f5c055SJed Brown cells_flat = cells[0][0]; 4224b7f5c055SJed Brown numEdges = 0; 4225b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 4226b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 4227b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 4228b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 4229b7f5c055SJed Brown 4230b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 4231b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 4232b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 4233b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 4234b7f5c055SJed Brown } 4235b7f5c055SJed Brown } 4236b7f5c055SJed Brown } 4237b7f5c055SJed Brown } 42389566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 42399566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 4240b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 4241b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 4242b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 4243b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 4244b7f5c055SJed Brown 4245b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 4246b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 4247b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 4248b7f5c055SJed Brown edges[edge][0] = ev[0]; 4249b7f5c055SJed Brown edges[edge][1] = ev[1]; 4250b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 4251b7f5c055SJed Brown } 4252b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 4253b7f5c055SJed Brown edges[edge][0] = ev[0]; 4254b7f5c055SJed Brown edges[edge][1] = ev[1]; 4255b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 4256b7f5c055SJed Brown } 4257b7f5c055SJed Brown } 4258b7f5c055SJed Brown } 4259b7f5c055SJed Brown } 4260b7f5c055SJed Brown } 4261b7f5c055SJed Brown } 4262b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 42634663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 4264b7f5c055SJed Brown break; 4265b7f5c055SJed Brown } 4266b7f5c055SJed Brown 42679566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 4268c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 42699566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 42709566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 4271b7f5c055SJed Brown { 4272b7f5c055SJed Brown DM idm; 42739566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 427469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 4275b7f5c055SJed Brown } 4276c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 42779566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 42789566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 4279b7f5c055SJed Brown 42809566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 42819566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 4282b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 4283b7f5c055SJed Brown PetscInt njoin; 4284b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 42859566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 428663a3b9bcSJacob 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]); 42879566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 42889566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 4289b7f5c055SJed Brown } 42909566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 42919566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 42921436d7faSJed Brown if (tps_distribute) { 42931436d7faSJed Brown DM pdm = NULL; 42941436d7faSJed Brown PetscPartitioner part; 42951436d7faSJed Brown 42969566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 42979566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 42989566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 429948a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 43001436d7faSJed Brown // Do not auto-distribute again 43019566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 43021436d7faSJed Brown } 4303b7f5c055SJed Brown 43049566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 4305b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 4306b7f5c055SJed Brown PetscInt m; 4307f1d4225fSZach Atkins DM dmf, cdm, cdmf; 4308b7f5c055SJed Brown Vec X; 4309b7f5c055SJed Brown PetscScalar *x; 4310f1d4225fSZach Atkins 43119566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 4312f1d4225fSZach Atkins PetscCall(DMGetCoordinateDM(dm, &cdm)); 4313f1d4225fSZach Atkins PetscCall(DMGetCoordinateDM(dmf, &cdmf)); 4314f1d4225fSZach Atkins PetscCall(DMCopyDisc(cdm, cdmf)); 431569d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 4316b7f5c055SJed Brown 43179566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 43189566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 43199566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 432048a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 43219566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 4322b7f5c055SJed Brown } 4323b7f5c055SJed Brown 4324b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 43259566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 43269566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 4327b7f5c055SJed Brown 432846139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 432946139095SJed Brown 4330b7f5c055SJed Brown if (thickness > 0) { 43314663dae6SJed Brown DM edm, cdm, ecdm; 43324663dae6SJed Brown DMPlexTransform tr; 43334663dae6SJed Brown const char *prefix; 43344663dae6SJed Brown PetscOptions options; 43354663dae6SJed Brown // Code from DMPlexExtrude 43364663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 43374663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 4338ce78bad3SBarry Smith PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDETYPE)); 43394663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 43404663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 43414663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 43424663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 43434663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 43444663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 43454663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 43464663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 43474663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 43484663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 43494663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 43504663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 43514663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 43524663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 43534663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 43544663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 43554663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 43564663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 43574663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 43584663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 4359a77a5016SMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, edm)); 436069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 4361b7f5c055SJed Brown } 43623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4363b7f5c055SJed Brown } 4364b7f5c055SJed Brown 4365b7f5c055SJed Brown /*@ 4366b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 4367b7f5c055SJed Brown 4368b7f5c055SJed Brown Collective 4369b7f5c055SJed Brown 4370b7f5c055SJed Brown Input Parameters: 4371a1cb98faSBarry Smith + comm - The communicator for the `DM` object 4372b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 4373b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 437420f4b53cSBarry Smith . periodic - array of length 3 with periodicity, or `NULL` for non-periodic 43751436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 4376817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 43771436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 4378817da375SSatish Balay - thickness - Thickness in normal direction 4379b7f5c055SJed Brown 4380b7f5c055SJed Brown Output Parameter: 4381a1cb98faSBarry Smith . dm - The `DM` object 4382a1cb98faSBarry Smith 4383a1cb98faSBarry Smith Level: beginner 4384b7f5c055SJed Brown 4385b7f5c055SJed Brown Notes: 438615229ffcSPierre Jolivet This meshes the surface of the Schwarz P or Gyroid surfaces. Schwarz P is the simplest member of the triply-periodic minimal surfaces. 43871d27aa22SBarry Smith <https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22)> and can be cut with "clean" boundaries. 43881d27aa22SBarry 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. 4389b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 4390b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 4391b7f5c055SJed Brown This projection could readily be extended to related surfaces. 4392b7f5c055SJed Brown 43931d27aa22SBarry Smith See {cite}`maskery2018insights` 43941d27aa22SBarry Smith 43951d27aa22SBarry Smith The face (edge) sets for the Schwarz P surface are numbered $1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z)$. 43961d27aa22SBarry Smith When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). 43971d27aa22SBarry Smith Use `DMPlexLabelComplete()` to propagate to coarse-level vertices. 4398b7f5c055SJed Brown 439960225df5SJacob Faibussowitsch Developer Notes: 4400b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 4401b7f5c055SJed Brown 44021cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 4403b7f5c055SJed Brown @*/ 4404d71ae5a4SJacob 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) 4405d71ae5a4SJacob Faibussowitsch { 4406b7f5c055SJed Brown PetscFunctionBegin; 44079566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44089566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 44099566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 44103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4411b7f5c055SJed Brown } 4412b7f5c055SJed Brown 44139318fe57SMatthew G. Knepley /*@ 44149318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 44159318fe57SMatthew G. Knepley 44169318fe57SMatthew G. Knepley Collective 44179318fe57SMatthew G. Knepley 44189318fe57SMatthew G. Knepley Input Parameters: 4419a1cb98faSBarry Smith + comm - The communicator for the `DM` object 44209318fe57SMatthew G. Knepley . dim - The dimension 44219318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 44229318fe57SMatthew G. Knepley - R - The radius 44239318fe57SMatthew G. Knepley 44249318fe57SMatthew G. Knepley Output Parameter: 4425a1cb98faSBarry Smith . dm - The `DM` object 44269318fe57SMatthew G. Knepley 44279318fe57SMatthew G. Knepley Level: beginner 44289318fe57SMatthew G. Knepley 44291cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 44309318fe57SMatthew G. Knepley @*/ 4431d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 4432d71ae5a4SJacob Faibussowitsch { 44339318fe57SMatthew G. Knepley PetscFunctionBegin; 44344f572ea9SToby Isaac PetscAssertPointer(dm, 5); 44359566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44369566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 44379566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 44383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44399318fe57SMatthew G. Knepley } 44409318fe57SMatthew G. Knepley 4441d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 4442d71ae5a4SJacob Faibussowitsch { 44439318fe57SMatthew G. Knepley DM sdm, vol; 44449318fe57SMatthew G. Knepley DMLabel bdlabel; 4445dd2b43ebSStefano Zampini const char *prefix; 44469318fe57SMatthew G. Knepley 44479318fe57SMatthew G. Knepley PetscFunctionBegin; 44489566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 44499566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 4450dd2b43ebSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 4451dd2b43ebSStefano Zampini PetscCall(DMSetOptionsPrefix(sdm, prefix)); 4452dd2b43ebSStefano Zampini PetscCall(DMAppendOptionsPrefix(sdm, "bd_")); 4453dd2b43ebSStefano Zampini PetscCall(DMPlexDistributeSetDefault(sdm, PETSC_FALSE)); 44549566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 44559566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 44569566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 44579566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 44589566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 445969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 44609566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 44619566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 44629566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 44639566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 44643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 446551a74b61SMatthew G. Knepley } 446651a74b61SMatthew G. Knepley 446751a74b61SMatthew G. Knepley /*@ 446851a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 446951a74b61SMatthew G. Knepley 447051a74b61SMatthew G. Knepley Collective 447151a74b61SMatthew G. Knepley 447251a74b61SMatthew G. Knepley Input Parameters: 4473a1cb98faSBarry Smith + comm - The communicator for the `DM` object 447451a74b61SMatthew G. Knepley . dim - The dimension 447551a74b61SMatthew G. Knepley - R - The radius 447651a74b61SMatthew G. Knepley 447751a74b61SMatthew G. Knepley Output Parameter: 4478a1cb98faSBarry Smith . dm - The `DM` object 447951a74b61SMatthew G. Knepley 4480a1cb98faSBarry Smith Options Database Key: 448160225df5SJacob Faibussowitsch . bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 448251a74b61SMatthew G. Knepley 448351a74b61SMatthew G. Knepley Level: beginner 448451a74b61SMatthew G. Knepley 44851cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 448651a74b61SMatthew G. Knepley @*/ 4487d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 4488d71ae5a4SJacob Faibussowitsch { 448951a74b61SMatthew G. Knepley PetscFunctionBegin; 44909566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44919566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 44929566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 44933ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44942829fed8SMatthew G. Knepley } 44952829fed8SMatthew G. Knepley 4496d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 4497d71ae5a4SJacob Faibussowitsch { 44980a6ba040SMatthew G. Knepley PetscFunctionBegin; 44999318fe57SMatthew G. Knepley switch (ct) { 45009371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 45019318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 45029318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 45039318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 45049318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 45059318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 45069318fe57SMatthew G. Knepley 45079566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 45089566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45099371c9d4SSatish Balay } break; 45109371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 45119318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 45129318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 45139318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 45149318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 45159318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 45169318fe57SMatthew G. Knepley 45179566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 45189566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45199371c9d4SSatish Balay } break; 45209371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 4521b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 4522b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 4523b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 4524b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 4525b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 4526b5a892a1SMatthew G. Knepley 45279566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 45289566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45299371c9d4SSatish Balay } break; 45309371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 45319318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 45329318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 45339318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 45349318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 45359318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 45369318fe57SMatthew G. Knepley 45379566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45389566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45399371c9d4SSatish Balay } break; 45409371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 45419318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45429318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 45439318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45449318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 45459318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 45469318fe57SMatthew G. Knepley 45479566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45489566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45499371c9d4SSatish Balay } break; 45509371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 45519318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45529318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 45539318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45549318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 45559318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 45569318fe57SMatthew G. Knepley 45579566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45589566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45599371c9d4SSatish Balay } break; 45609371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 45619318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45629318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 4563f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45649318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 4565f0edb160SMatthew 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}; 45669318fe57SMatthew G. Knepley 45679566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45689566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45699371c9d4SSatish Balay } break; 45709371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 45719318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 45729318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 4573f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 45749318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 45759371c9d4SSatish 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}; 45769318fe57SMatthew G. Knepley 45779566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45789566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45799371c9d4SSatish Balay } break; 45809371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 45819318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 45829318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 4583f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 45849318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 45859371c9d4SSatish 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}; 45869318fe57SMatthew G. Knepley 45879566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45889566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45899371c9d4SSatish Balay } break; 45909371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 45919318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 45929318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 45939318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 45949318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 45959371c9d4SSatish 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}; 45969318fe57SMatthew G. Knepley 45979566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45989566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45999371c9d4SSatish Balay } break; 46009371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 46019318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 46029318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 46039318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 46049318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 46059371c9d4SSatish 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}; 46069318fe57SMatthew G. Knepley 46079566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 46089566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 46099371c9d4SSatish Balay } break; 46109371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 46119318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 46129318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 4613f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 46149318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 46159371c9d4SSatish 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}; 46169318fe57SMatthew G. Knepley 46179566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 46189566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 46199371c9d4SSatish Balay } break; 4620d71ae5a4SJacob Faibussowitsch default: 4621d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 46229318fe57SMatthew G. Knepley } 46239318fe57SMatthew G. Knepley { 46249318fe57SMatthew G. Knepley PetscInt Nv, v; 46259318fe57SMatthew G. Knepley 46269318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 46279566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 46289566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 46299566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 46309566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 46319318fe57SMatthew G. Knepley } 46329566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 46339566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 46343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46350a6ba040SMatthew G. Knepley } 46360a6ba040SMatthew G. Knepley 46379318fe57SMatthew G. Knepley /*@ 4638a1cb98faSBarry Smith DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell 46399318fe57SMatthew G. Knepley 46409318fe57SMatthew G. Knepley Collective 46419318fe57SMatthew G. Knepley 46429318fe57SMatthew G. Knepley Input Parameters: 46439318fe57SMatthew G. Knepley + comm - The communicator 46449318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 46459318fe57SMatthew G. Knepley 46469318fe57SMatthew G. Knepley Output Parameter: 46479318fe57SMatthew G. Knepley . refdm - The reference cell 46489318fe57SMatthew G. Knepley 46499318fe57SMatthew G. Knepley Level: intermediate 46509318fe57SMatthew G. Knepley 465142747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()` 46529318fe57SMatthew G. Knepley @*/ 4653d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 4654d71ae5a4SJacob Faibussowitsch { 46550a6ba040SMatthew G. Knepley PetscFunctionBegin; 46569566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 46579566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 46589566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 46593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46609318fe57SMatthew G. Knepley } 466179a015ccSMatthew G. Knepley 4662d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 4663d71ae5a4SJacob Faibussowitsch { 46649318fe57SMatthew G. Knepley DM plex; 46659318fe57SMatthew G. Knepley DMLabel label; 46669318fe57SMatthew G. Knepley PetscBool hasLabel; 46670a6ba040SMatthew G. Knepley 4668c22d3578SMatthew G. Knepley PetscFunctionBegin; 46699566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 46703ba16761SJacob Faibussowitsch if (hasLabel) PetscFunctionReturn(PETSC_SUCCESS); 46719566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 46729566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 46739566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 46749566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 46751c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 46769566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 46773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46789318fe57SMatthew G. Knepley } 4679acdc6f61SToby Isaac 4680669647acSMatthew G. Knepley /* 4681669647acSMatthew 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. 4682669647acSMatthew G. Knepley 4683669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 4684669647acSMatthew G. Knepley */ 4685d71ae5a4SJacob 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[]) 4686d71ae5a4SJacob Faibussowitsch { 4687669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 4688669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 4689669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 4690669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 4691669647acSMatthew G. Knepley 4692669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 4693669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 4694669647acSMatthew G. Knepley } 4695669647acSMatthew G. Knepley 46965390be7dSMatthew G. Knepley // Insert vertices and their joins, marked by depth 46975390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Vertices(DM dm, DMLabel label, DMLabel vlabel, PetscInt val, PetscInt n, const PetscInt vertices[]) 46985390be7dSMatthew G. Knepley { 46995390be7dSMatthew G. Knepley PetscFunctionBegin; 47005390be7dSMatthew G. Knepley PetscCall(DMPlexMarkSubmesh_Interpolated(dm, vlabel, val, PETSC_FALSE, PETSC_FALSE, label, NULL)); 47015390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 47025390be7dSMatthew G. Knepley } 47035390be7dSMatthew G. Knepley 47045390be7dSMatthew G. Knepley // Insert faces and their closures, marked by depth 47055390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Faces(DM dm, DMLabel label, PetscInt n, const PetscInt faces[]) 47065390be7dSMatthew G. Knepley { 47075390be7dSMatthew G. Knepley PetscFunctionBegin; 47085390be7dSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) { 47095390be7dSMatthew G. Knepley const PetscInt point = faces[p]; 47105390be7dSMatthew G. Knepley PetscInt *closure = NULL; 47115390be7dSMatthew G. Knepley PetscInt clSize, pdepth; 47125390be7dSMatthew G. Knepley 47135390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, point, &pdepth)); 47145390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, point, pdepth)); 47155390be7dSMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 47165390be7dSMatthew G. Knepley for (PetscInt cl = 0; cl < clSize * 2; cl += 2) { 47175390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, closure[cl], &pdepth)); 47185390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, closure[cl], pdepth)); 47195390be7dSMatthew G. Knepley } 47205390be7dSMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 47215390be7dSMatthew G. Knepley } 47225390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 47235390be7dSMatthew G. Knepley } 47245390be7dSMatthew G. Knepley 47254e22dd4cSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *flg); 47264e22dd4cSMatthew G. Knepley 47275dca41c3SJed Brown const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "zbox", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 47289318fe57SMatthew G. Knepley 4729ce78bad3SBarry Smith static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 4730d71ae5a4SJacob Faibussowitsch { 47319318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 47329318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 47339318fe57SMatthew G. Knepley PetscInt dim = 2; 4734b9da1bb3SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, orient = PETSC_FALSE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 4735d0812dedSMatthew G. Knepley PetscBool flg, flg2, fflg, strflg, bdfflg, nameflg; 47369318fe57SMatthew G. Knepley MPI_Comm comm; 4737ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4738ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4739ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 47404e22dd4cSMatthew G. Knepley const char *option; 47419318fe57SMatthew G. Knepley 47429318fe57SMatthew G. Knepley PetscFunctionBegin; 4743708be2fdSJed Brown PetscCall(PetscLogEventBegin(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 47449566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 47459318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 47469566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 4747d0812dedSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_file_contents", "Contents of a file format in a string", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &strflg)); 47489566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 47499566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 47509566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 47519566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 47529566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 47539566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 47549566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 47559566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 4756b9da1bb3SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_orient", "Orient the constructed mesh", "DMPlexOrient", orient, &orient, &flg)); 47579566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 47589566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 47599566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 47603f3e541fSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_adj", "Debug output level all adjacency computations", "", 0, &((DM_Plex *)dm->data)->printAdj, NULL, 0)); 47619318fe57SMatthew G. Knepley 476261a622f3SMatthew G. Knepley switch (cell) { 476361a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 476461a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 476561a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 476661a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 476761a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 476861a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 4769d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 4770d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_TRUE; 4771d71ae5a4SJacob Faibussowitsch break; 4772d71ae5a4SJacob Faibussowitsch default: 4773d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_FALSE; 4774d71ae5a4SJacob Faibussowitsch break; 477561a622f3SMatthew G. Knepley } 477661a622f3SMatthew G. Knepley 47779318fe57SMatthew G. Knepley if (fflg) { 47789318fe57SMatthew G. Knepley DM dmnew; 47791e4a82c4SMatthew G. Knepley const char *name; 47809318fe57SMatthew G. Knepley 47811e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 47821e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, nameflg ? plexname : name, interpolate, &dmnew)); 47835de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 478469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 47859318fe57SMatthew G. Knepley } else if (refDomain) { 47869566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 47879318fe57SMatthew G. Knepley } else if (bdfflg) { 47889318fe57SMatthew G. Knepley DM bdm, dmnew; 47891e4a82c4SMatthew G. Knepley const char *name; 47909318fe57SMatthew G. Knepley 47911e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 47921e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, nameflg ? plexname : name, interpolate, &bdm)); 47939566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 47949566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 47959566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 47969566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 47975de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 479869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 4799d0812dedSMatthew G. Knepley } else if (strflg) { 4800d0812dedSMatthew G. Knepley DM dmnew; 4801d0812dedSMatthew G. Knepley PetscViewer viewer; 4802d0812dedSMatthew G. Knepley const char *contents; 4803d0812dedSMatthew G. Knepley char *strname; 4804d0812dedSMatthew G. Knepley char tmpdir[PETSC_MAX_PATH_LEN]; 4805d0812dedSMatthew G. Knepley char tmpfilename[PETSC_MAX_PATH_LEN]; 4806d0812dedSMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 4807d0812dedSMatthew G. Knepley MPI_Comm comm; 4808d0812dedSMatthew G. Knepley PetscMPIInt rank; 4809d0812dedSMatthew G. Knepley 4810d0812dedSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4811d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 4812d0812dedSMatthew G. Knepley PetscCall(PetscStrchr(filename, ':', &strname)); 4813d0812dedSMatthew G. Knepley PetscCheck(strname, comm, PETSC_ERR_ARG_WRONG, "File contents must have the form \"ext:string_name\", not %s", filename); 4814d0812dedSMatthew G. Knepley strname[0] = '\0'; 4815d0812dedSMatthew G. Knepley ++strname; 4816d0812dedSMatthew G. Knepley PetscCall(PetscDLSym(NULL, strname, (void **)&contents)); 4817d0812dedSMatthew G. Knepley PetscCheck(contents, comm, PETSC_ERR_ARG_WRONG, "Could not locate mesh string %s", strname); 4818d0812dedSMatthew G. Knepley PetscCall(PetscGetTmp(comm, tmpdir, PETSC_MAX_PATH_LEN)); 4819ed32af8cSMatthew G. Knepley PetscCall(PetscStrlcat(tmpdir, "/meshXXXXXX", PETSC_MAX_PATH_LEN)); 4820ed32af8cSMatthew G. Knepley PetscCall(PetscMkdtemp(tmpdir)); 4821ed32af8cSMatthew G. Knepley PetscCall(PetscSNPrintf(tmpfilename, PETSC_MAX_PATH_LEN, "%s/mesh.%s", tmpdir, filename)); 4822d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIOpen(comm, tmpfilename, &viewer)); 4823d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", contents)); 4824d0812dedSMatthew G. Knepley PetscCall(PetscViewerDestroy(&viewer)); 4825d0812dedSMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), tmpfilename, plexname, interpolate, &dmnew)); 4826ed32af8cSMatthew G. Knepley PetscCall(PetscRMTree(tmpdir)); 4827d0812dedSMatthew G. Knepley PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%s Mesh", strname)); 4828d0812dedSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, name)); 4829d0812dedSMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 4830d0812dedSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 48319318fe57SMatthew G. Knepley } else { 48329566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 48339318fe57SMatthew G. Knepley switch (shape) { 4834669647acSMatthew G. Knepley case DM_SHAPE_BOX: 48355dca41c3SJed Brown case DM_SHAPE_ZBOX: 4836669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 48379318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 48389318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 48399318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 48409318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4841669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 48429318fe57SMatthew G. Knepley PetscInt i, n; 48439318fe57SMatthew G. Knepley 48449318fe57SMatthew G. Knepley n = dim; 48459318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 48469566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 48479318fe57SMatthew G. Knepley n = 3; 48489566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 484963a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 48509318fe57SMatthew G. Knepley n = 3; 48519566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 485263a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 48539318fe57SMatthew G. Knepley n = 3; 48549566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 485563a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 4856669647acSMatthew G. Knepley 4857669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 4858669647acSMatthew G. Knepley if (isAnnular) 4859669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 4860669647acSMatthew G. Knepley 48619318fe57SMatthew G. Knepley switch (cell) { 486261a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 48639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 4864d410b0cfSMatthew G. Knepley if (!interpolate) { 4865d410b0cfSMatthew G. Knepley DM udm; 4866d410b0cfSMatthew G. Knepley 48679566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 486869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 4869d410b0cfSMatthew G. Knepley } 48709318fe57SMatthew G. Knepley break; 4871d71ae5a4SJacob Faibussowitsch default: 48725dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(dm, shape, dim, simplex, faces, lower, upper, bdt, interpolate)); 4873d71ae5a4SJacob Faibussowitsch break; 48749318fe57SMatthew G. Knepley } 4875669647acSMatthew G. Knepley if (isAnnular) { 4876669647acSMatthew G. Knepley DM cdm; 4877669647acSMatthew G. Knepley PetscDS cds; 4878669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 4879669647acSMatthew G. Knepley 4880669647acSMatthew G. Knepley // Fix coordinates for annular region 4881669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 4882669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 4883669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 4884e65c294aSksagiyam PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE)); 4885669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 4886669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 4887669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 4888669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 4889669647acSMatthew G. Knepley } 48909371c9d4SSatish Balay } break; 48919371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 48929318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 48939318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 48949318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 48959318fe57SMatthew G. Knepley PetscInt i, n; 48969318fe57SMatthew G. Knepley 48979318fe57SMatthew G. Knepley n = dim + 1; 48989318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 48999566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 49009318fe57SMatthew G. Knepley n = 3; 49019566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 490263a3b9bcSJacob 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); 49039318fe57SMatthew G. Knepley n = 3; 49049566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 490563a3b9bcSJacob 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); 49069566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 49079371c9d4SSatish Balay } break; 49089371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 49099318fe57SMatthew G. Knepley PetscReal R = 1.0; 49109318fe57SMatthew G. Knepley 49119566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 49129566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 49139371c9d4SSatish Balay } break; 49149371c9d4SSatish Balay case DM_SHAPE_BALL: { 49159318fe57SMatthew G. Knepley PetscReal R = 1.0; 49169318fe57SMatthew G. Knepley 49179566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 49189566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 49199371c9d4SSatish Balay } break; 49209371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 49219318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 49229318fe57SMatthew G. Knepley PetscInt Nw = 6; 492349704ca5SMatthew G. Knepley PetscInt Nr = 0; 49249318fe57SMatthew G. Knepley 49259566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 49269566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 492749704ca5SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_refine", "Number of refinements before projection", "", Nr, &Nr, NULL)); 49289318fe57SMatthew G. Knepley switch (cell) { 4929d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_TRI_PRISM_TENSOR: 4930d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 4931d71ae5a4SJacob Faibussowitsch break; 4932d71ae5a4SJacob Faibussowitsch default: 493349704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt, Nr)); 4934d71ae5a4SJacob Faibussowitsch break; 49359318fe57SMatthew G. Knepley } 49369371c9d4SSatish Balay } break; 4937b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 49389371c9d4SSatish Balay case DM_SHAPE_GYROID: { 4939b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 4940b7f5c055SJed Brown PetscReal thickness = 0.; 4941b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4942b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 49431436d7faSJed Brown PetscBool tps_distribute; 49449566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 49459566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 49469566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 49479566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 49489566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 49499566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 49509566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 49519566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 49529371c9d4SSatish Balay } break; 49539371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 495405bd46c0SStefano Zampini DM dmnew; 495505bd46c0SStefano Zampini PetscReal rl = 0.0; 495605bd46c0SStefano Zampini 495705bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 495805bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 49595de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 496069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 49619371c9d4SSatish Balay } break; 4962cfb853baSMatthew G. Knepley case DM_SHAPE_HYPERCUBIC: { 49638d2ec52aSSatish Balay PetscInt *edges, overlap = 1; 4964cfb853baSMatthew G. Knepley PetscReal *lower, *upper; 4965cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 4966cfb853baSMatthew G. Knepley PetscInt n, d; 4967cfb853baSMatthew G. Knepley 4968cfb853baSMatthew G. Knepley *useCoordSpace = PETSC_FALSE; 4969cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt)); 4970cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 4971cfb853baSMatthew G. Knepley edges[d] = 1; 4972cfb853baSMatthew G. Knepley lower[d] = 0.; 4973cfb853baSMatthew G. Knepley upper[d] = 1.; 4974cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 4975cfb853baSMatthew G. Knepley } 4976cfb853baSMatthew G. Knepley n = dim; 4977cfb853baSMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg)); 4978cfb853baSMatthew G. Knepley n = dim; 4979cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 4980cfb853baSMatthew 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); 4981cfb853baSMatthew G. Knepley n = dim; 4982cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 4983cfb853baSMatthew 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); 4984cfb853baSMatthew G. Knepley n = dim; 4985cfb853baSMatthew G. Knepley PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 4986cfb853baSMatthew 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); 49878d2ec52aSSatish Balay PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", overlap, &overlap, NULL, 0)); 49888d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, overlap, bdt)); 4989cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edges, lower, upper, bdt)); 4990cfb853baSMatthew G. Knepley } break; 4991d71ae5a4SJacob Faibussowitsch default: 4992d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 49939318fe57SMatthew G. Knepley } 49949318fe57SMatthew G. Knepley } 49959566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 499648a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 4997b9da1bb3SMatthew G. Knepley if (orient) PetscCall(DMPlexOrient(dm)); 49984e22dd4cSMatthew G. Knepley // Allow label creation 49994e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_label_", &option, NULL, &flg)); 50004e22dd4cSMatthew G. Knepley if (flg) { 50014e22dd4cSMatthew G. Knepley DMLabel label; 50024e22dd4cSMatthew G. Knepley PetscInt points[1024], n = 1024; 50034e22dd4cSMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 50044e22dd4cSMatthew G. Knepley const char *name = &option[14]; 50054e22dd4cSMatthew G. Knepley 50064e22dd4cSMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 50074e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 50084e22dd4cSMatthew G. Knepley fulloption[0] = '-'; 50094e22dd4cSMatthew G. Knepley fulloption[1] = 0; 50104e22dd4cSMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, option, PETSC_MAX_PATH_LEN)); 50114e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, NULL)); 50124e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) PetscCall(DMLabelSetValue(label, points[p], 1)); 50134e22dd4cSMatthew G. Knepley } 5014dd0eeac9SMatthew G. Knepley // Allow cohesive label creation 5015dd0eeac9SMatthew G. Knepley // Faces are input, completed, and all points are marked with their depth 5016dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_cohesive_label_", &option, NULL, &flg)); 5017dd0eeac9SMatthew G. Knepley if (flg) { 5018dd0eeac9SMatthew G. Knepley DMLabel label; 5019dd0eeac9SMatthew G. Knepley PetscInt points[1024], n, pStart, pEnd, Nl = 1; 50205390be7dSMatthew G. Knepley PetscBool noCreate = PETSC_FALSE; 5021dd0eeac9SMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 5022dd0eeac9SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 5023dd0eeac9SMatthew G. Knepley size_t len; 5024dd0eeac9SMatthew G. Knepley 5025dd0eeac9SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 5026dd0eeac9SMatthew G. Knepley PetscCall(PetscStrncpy(name, &option[23], PETSC_MAX_PATH_LEN)); 5027dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlen(name, &len)); 5028dd0eeac9SMatthew G. Knepley if (name[len - 1] == '0') Nl = 10; 5029dd0eeac9SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 50306497c311SBarry Smith if (l > 0) name[len - 1] = (char)('0' + l); 5031dd0eeac9SMatthew G. Knepley fulloption[0] = 0; 5032dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, "-dm_plex_cohesive_label_", 32)); 5033dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, name, PETSC_MAX_PATH_LEN - 32)); 5034dd0eeac9SMatthew G. Knepley n = 1024; 5035dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, &flg)); 5036dd0eeac9SMatthew G. Knepley if (!flg) break; 50375390be7dSMatthew G. Knepley PetscCall(DMHasLabel(dm, name, &noCreate)); 50385390be7dSMatthew G. Knepley if (noCreate) { 50395390be7dSMatthew G. Knepley DMLabel inlabel; 50405390be7dSMatthew G. Knepley IS pointIS; 50415390be7dSMatthew G. Knepley const PetscInt *lpoints; 50425390be7dSMatthew G. Knepley PetscInt pdep, ln, inval = points[0]; 50435390be7dSMatthew G. Knepley char newname[PETSC_MAX_PATH_LEN]; 50445390be7dSMatthew G. Knepley 50455390be7dSMatthew G. Knepley PetscCheck(n == 1, comm, PETSC_ERR_ARG_WRONG, "Must specify a label value with this option"); 50465390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &inlabel)); 50475390be7dSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(inlabel, inval, &pointIS)); 50485390be7dSMatthew G. Knepley PetscCall(ISGetLocalSize(pointIS, &ln)); 50495390be7dSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &lpoints)); 50505390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, lpoints[0], &pdep)); 50515390be7dSMatthew G. Knepley PetscCall(PetscSNPrintf(newname, PETSC_MAX_PATH_LEN, "%s%" PetscInt_FMT, name, points[0])); 50525390be7dSMatthew G. Knepley PetscCall(DMCreateLabel(dm, newname)); 50535390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, newname, &label)); 50545390be7dSMatthew G. Knepley if (!pdep) PetscCall(ProcessCohesiveLabel_Vertices(dm, label, inlabel, inval, ln, lpoints)); 50555390be7dSMatthew G. Knepley else PetscCall(ProcessCohesiveLabel_Faces(dm, label, ln, lpoints)); 50565390be7dSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &lpoints)); 50575390be7dSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 50585390be7dSMatthew G. Knepley } else { 5059dd0eeac9SMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 5060dd0eeac9SMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 5061dd0eeac9SMatthew G. Knepley if (pStart >= pEnd) n = 0; 50625390be7dSMatthew G. Knepley PetscCall(ProcessCohesiveLabel_Faces(dm, label, n, points)); 5063dd0eeac9SMatthew G. Knepley } 5064dd0eeac9SMatthew G. Knepley PetscCall(DMPlexOrientLabel(dm, label)); 50650542aa8cSMatthew G. Knepley PetscCall(DMPlexLabelCohesiveComplete(dm, label, NULL, 1, PETSC_FALSE, PETSC_FALSE, NULL)); 5066dd0eeac9SMatthew G. Knepley } 5067dd0eeac9SMatthew G. Knepley } 50685390be7dSMatthew G. Knepley PetscCall(DMViewFromOptions(dm, NULL, "-created_dm_view")); 5069708be2fdSJed Brown PetscCall(PetscLogEventEnd(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 50703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50710a6ba040SMatthew G. Knepley } 50720a6ba040SMatthew G. Knepley 5073ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems PetscOptionsObject) 5074d71ae5a4SJacob Faibussowitsch { 50750a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 50767f9d8d6cSVaclav Hapla PetscBool flg, flg2; 50779318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 5078adc21957SMatthew G. Knepley char method[PETSC_MAX_PATH_LEN]; 50790a6ba040SMatthew G. Knepley 50800a6ba040SMatthew G. Knepley PetscFunctionBegin; 50810a6ba040SMatthew G. Knepley /* Handle viewing */ 50829566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 50835962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level for all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 50845962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fvm", "Debug output level for all fvm computations", "DMPlexSNESComputeResidualFVM", 0, &mesh->printFVM, NULL, 0)); 50859566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 50869566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 5087f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 5088a77a5016SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_project", "Debug output level all projection computations", "DMPlexProject", 0, &mesh->printProject, NULL, 0)); 50899566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 50909566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 50915e2c5519SMatthew G. Knepley // Interpolation 50925e2c5519SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_interpolate_prefer_tensor", "When different orderings exist, prefer the tensor order", "DMPlexSetInterpolationPreferTensor", mesh->interpolatePreferTensor, &mesh->interpolatePreferTensor, NULL)); 50939318fe57SMatthew G. Knepley /* Labeling */ 50949566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 50959566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 5096953fc75cSMatthew G. Knepley /* Point Location */ 50979566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 50980848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 50999566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 5100d02c7345SMatthew G. Knepley /* Reordering */ 5101adc21957SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_reorder_section", "Compute point permutation for local section", "DMReorderSectionSetDefault", PETSC_FALSE, &flg2, &flg)); 5102adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetDefault(dm, flg2 ? DM_REORDER_DEFAULT_TRUE : DM_REORDER_DEFAULT_FALSE)); 5103adc21957SMatthew G. Knepley PetscCall(PetscOptionsString("-dm_reorder_section_type", "Reordering method for local section", "DMReorderSectionSetType", method, method, PETSC_MAX_PATH_LEN, &flg)); 5104adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetType(dm, method)); 51052e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 51069566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 510761f058f9SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_save_transform", "Save the transform producing this mesh", "DMAdapt", PETSC_FALSE, &mesh->saveTransform, NULL)); 5108b29cfa1cSToby Isaac /* Projection behavior */ 5109d5b43468SJose E. Roman PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 51109566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 5111f12cf164SMatthew G. Knepley /* Checking structure */ 5112f12cf164SMatthew G. Knepley { 51137f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 5114f12cf164SMatthew G. Knepley 51157f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 51167f9d8d6cSVaclav Hapla if (all) { 51177f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 51187f9d8d6cSVaclav Hapla } else { 51199566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 51207f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 51219566063dSJacob 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)); 51227f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 51239566063dSJacob 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)); 51247f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 51259566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 51267f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 51279566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 5128d7d32a9aSMatthew G. Knepley if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 51299566063dSJacob 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)); 51307f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 51317f9d8d6cSVaclav Hapla } 51329566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 51339566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 5134f12cf164SMatthew G. Knepley } 51359318fe57SMatthew G. Knepley { 51369318fe57SMatthew G. Knepley PetscReal scale = 1.0; 51374f3833eaSMatthew G. Knepley 51389566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 51399318fe57SMatthew G. Knepley if (flg) { 51409318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 51419318fe57SMatthew G. Knepley 51429566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 51439566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 51449566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 51459566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 51469318fe57SMatthew G. Knepley } 51479318fe57SMatthew G. Knepley } 51489566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 51493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 515068d4fef7SMatthew G. Knepley } 515168d4fef7SMatthew G. Knepley 5152ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems PetscOptionsObject, PetscInt *overlap) 5153d71ae5a4SJacob Faibussowitsch { 5154c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 5155c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 5156c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 5157c506a872SMatthew G. Knepley PetscBool flg; 5158c506a872SMatthew G. Knepley 5159c506a872SMatthew G. Knepley PetscFunctionBegin; 5160c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 5161c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 5162c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 5163c506a872SMatthew G. Knepley if (numOvLabels) { 5164c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 5165c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 5166c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 5167c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 5168c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 5169c506a872SMatthew G. Knepley } 5170c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 5171c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 5172c506a872SMatthew 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); 5173c506a872SMatthew G. Knepley 5174c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 5175c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 5176c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 5177c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 5178c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 5179c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 5180c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 5181c506a872SMatthew G. Knepley } 5182c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 5183c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 5184c506a872SMatthew 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); 5185c506a872SMatthew G. Knepley } 51863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5187c506a872SMatthew G. Knepley } 5188c506a872SMatthew G. Knepley 5189ce78bad3SBarry Smith static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems PetscOptionsObject) 5190d71ae5a4SJacob Faibussowitsch { 5191bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 5192bdf63967SMatthew G. Knepley char oname[256]; 51934e22dd4cSMatthew G. Knepley char sublabelname[PETSC_MAX_PATH_LEN] = ""; 5194adc21957SMatthew G. Knepley DMReorderDefaultFlag reorder; 5195d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 51969318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 5197530e699aSMatthew 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; 519868d4fef7SMatthew G. Knepley 519968d4fef7SMatthew G. Knepley PetscFunctionBegin; 5200d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 5201dd4c3f67SMatthew G. Knepley if (dm->cloneOpts) goto non_refine; 52029318fe57SMatthew G. Knepley /* Handle automatic creation */ 52039566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 5204530e699aSMatthew G. Knepley if (dim < 0) PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 52056bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 5206d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 52079566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 5208d89e6e46SMatthew G. Knepley if (flg) { 5209d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 5210d89e6e46SMatthew G. Knepley 52119566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 5212d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 5213d89e6e46SMatthew G. Knepley DM udm; 5214d89e6e46SMatthew G. Knepley 52159566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 521669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 5217d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 5218d89e6e46SMatthew G. Knepley DM idm; 5219d89e6e46SMatthew G. Knepley 52209566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 522169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 5222d89e6e46SMatthew G. Knepley } 5223d89e6e46SMatthew G. Knepley } 52244e22dd4cSMatthew G. Knepley // Handle submesh selection before distribution 52254e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_submesh", "Label to use for submesh selection", "", sublabelname, sublabelname, PETSC_MAX_PATH_LEN, &flg)); 52264e22dd4cSMatthew G. Knepley if (flg) { 52274e22dd4cSMatthew G. Knepley DM subdm; 52284e22dd4cSMatthew G. Knepley DMLabel label; 52294e22dd4cSMatthew G. Knepley IS valueIS, pointIS; 52304e22dd4cSMatthew G. Knepley const PetscInt *values, *points; 52314e22dd4cSMatthew G. Knepley PetscBool markedFaces = PETSC_FALSE; 52324e22dd4cSMatthew G. Knepley PetscInt Nv, value, Np; 52334e22dd4cSMatthew G. Knepley 52344e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, sublabelname, &label)); 52354e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &Nv)); 52364e22dd4cSMatthew 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); 52374e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetValueIS(label, &valueIS)); 52384e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &values)); 52394e22dd4cSMatthew G. Knepley value = values[0]; 52404e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(valueIS, &values)); 52414e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 52424e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumSize(label, value, &Np)); 52434e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, value, &pointIS)); 52444e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &points)); 52454e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 52464e22dd4cSMatthew G. Knepley PetscInt pdepth; 52474e22dd4cSMatthew G. Knepley 52484e22dd4cSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, points[p], &pdepth)); 52494e22dd4cSMatthew G. Knepley if (pdepth) { 52504e22dd4cSMatthew G. Knepley markedFaces = PETSC_TRUE; 52514e22dd4cSMatthew G. Knepley break; 52524e22dd4cSMatthew G. Knepley } 52534e22dd4cSMatthew G. Knepley } 52544e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &points)); 52554e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 52564e22dd4cSMatthew G. Knepley PetscCall(DMPlexCreateSubmesh(dm, label, value, markedFaces, &subdm)); 52574e22dd4cSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &subdm)); 52584e22dd4cSMatthew G. Knepley PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 52594e22dd4cSMatthew G. Knepley } 52609b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 52619566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 52629566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 52639566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 52649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 52659566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 52669566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 52679318fe57SMatthew G. Knepley if (flg) { 52689566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 52699566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 52709318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 52719318fe57SMatthew G. Knepley } 5272b23db253SStefano Zampini if (prerefine) PetscCall(DMLocalizeCoordinates(dm)); 52739b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 52749b44eab4SMatthew G. Knepley DM rdm; 52752192575eSBarry Smith PetscPointFn *coordFunc; 52769b44eab4SMatthew G. Knepley 5277509b31aaSMatthew G. Knepley PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc)); 5278dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 52799566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 528069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 5281dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 528261a622f3SMatthew G. Knepley if (coordFunc && remap) { 52839566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 5284509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, coordFunc)); 52859b44eab4SMatthew G. Knepley } 52869b44eab4SMatthew G. Knepley } 52879566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 52889318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 52899566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 52909318fe57SMatthew G. Knepley if (extLayers) { 52919318fe57SMatthew G. Knepley DM edm; 52929318fe57SMatthew G. Knepley 52939566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 529469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 5295509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, NULL)); 5296dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5297d410b0cfSMatthew G. Knepley extLayers = 0; 52985e17fc22SAidan Hamilton PetscCall(DMGetDimension(dm, &dim)); 52999318fe57SMatthew G. Knepley } 5300bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 53016bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 53029566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 53036bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 53049566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 5305adc21957SMatthew G. Knepley if (reorder == DM_REORDER_DEFAULT_TRUE || flg) { 5306bdf63967SMatthew G. Knepley DM pdm; 5307bdf63967SMatthew G. Knepley IS perm; 5308bdf63967SMatthew G. Knepley 53099566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 53109566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 53119566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 531269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 5313dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5314bdf63967SMatthew G. Knepley } 53159b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 53169566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 5317c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 5318a286e215SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute_save_sf", "Flag to save the migration SF", "DMPlexSetMigrationSF", saveSF, &saveSF, NULL)); 5319dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 53209b44eab4SMatthew G. Knepley if (distribute) { 53219b44eab4SMatthew G. Knepley DM pdm = NULL; 53229b44eab4SMatthew G. Knepley PetscPartitioner part; 5323a286e215SMatthew G. Knepley PetscSF sfMigration; 53249566ead2SJames Wright PetscBool use_partition_balance; 53259b44eab4SMatthew G. Knepley 53269566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 53279566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 53289566ead2SJames Wright PetscCall(DMPlexGetPartitionBalance(dm, &use_partition_balance)); 53299566ead2SJames 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)); 53309566ead2SJames Wright if (flg) PetscCall(DMPlexSetPartitionBalance(dm, use_partition_balance)); 5331a286e215SMatthew G. Knepley PetscCall(DMPlexDistribute(dm, overlap, &sfMigration, &pdm)); 53325d2873a6SJames Wright if (pdm) { 53335d2873a6SJames Wright // Delete the local section to force the existing one to be rebuilt with the distributed DM 53345d2873a6SJames Wright PetscCall(DMSetLocalSection(dm, pdm->localSection)); 53355d2873a6SJames Wright PetscCall(DMPlexReplace_Internal(dm, &pdm)); 53365d2873a6SJames Wright } 5337a286e215SMatthew G. Knepley if (saveSF) PetscCall(DMPlexSetMigrationSF(dm, sfMigration)); 5338a286e215SMatthew G. Knepley PetscCall(PetscSFDestroy(&sfMigration)); 53399b44eab4SMatthew G. Knepley } 53404054ae39SJames Wright 53414054ae39SJames Wright { 53424054ae39SJames Wright PetscBool useBoxLabel = PETSC_FALSE; 53434054ae39SJames Wright PetscCall(PetscOptionsBool("-dm_plex_box_label", "Create 'Face Sets' assuming boundary faces align with cartesian directions", "DMCreate", useBoxLabel, &useBoxLabel, NULL)); 5344d7d2d1d2SJames Wright if (useBoxLabel) { 5345d7d2d1d2SJames Wright PetscInt n = 3; 5346d7d2d1d2SJames Wright DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 5347d7d2d1d2SJames Wright 5348d7d2d1d2SJames Wright PetscCall(PetscOptionsEnumArray("-dm_plex_box_label_bd", "Boundary type for each dimension when using -dm_plex_box_label", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 5349d7d2d1d2SJames 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); 5350d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, bdt)); 5351d7d2d1d2SJames Wright } 53524054ae39SJames Wright } 5353d2b2dc1eSMatthew G. Knepley /* Must check CEED options before creating function space for coordinates */ 5354d2b2dc1eSMatthew G. Knepley { 5355d2b2dc1eSMatthew G. Knepley PetscBool useCeed = PETSC_FALSE, flg; 5356d2b2dc1eSMatthew G. Knepley 5357d2b2dc1eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_use_ceed", "Use LibCEED as the FEM backend", "DMPlexSetUseCeed", useCeed, &useCeed, &flg)); 5358d2b2dc1eSMatthew G. Knepley if (flg) PetscCall(DMPlexSetUseCeed(dm, useCeed)); 5359d2b2dc1eSMatthew G. Knepley } 53609318fe57SMatthew G. Knepley /* Create coordinate space */ 5361530e699aSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, NULL)); 5362530e699aSMatthew G. Knepley if (coordSpace) { 5363e44f6aebSMatthew G. Knepley PetscInt degree = 1, deg; 53645515ebd3SMatthew G. Knepley PetscInt height = 0; 53655515ebd3SMatthew G. Knepley DM cdm; 5366530e699aSMatthew G. Knepley PetscBool localize = PETSC_TRUE, sparseLocalize = PETSC_TRUE; 53679318fe57SMatthew G. Knepley 53689566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 5369e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDegree_Internal(dm, °)); 5370e65c294aSksagiyam if (coordSpace && deg <= 1) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_FALSE, PETSC_TRUE)); 53715515ebd3SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5372530e699aSMatthew G. Knepley if (!coordSpace) { 537361a622f3SMatthew G. Knepley PetscDS cds; 537461a622f3SMatthew G. Knepley PetscObject obj; 537561a622f3SMatthew G. Knepley PetscClassId id; 537661a622f3SMatthew G. Knepley 53779566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 53789566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 53799566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 538061a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 538161a622f3SMatthew G. Knepley PetscContainer dummy; 538261a622f3SMatthew G. Knepley 53839566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 53849566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 53859566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 53869566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 53879566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 538861a622f3SMatthew G. Knepley } 5389509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, NULL)); 539061a622f3SMatthew G. Knepley } 5391c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_localize", "Localize mesh coordinates", "", localize, &localize, NULL)); 5392c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "DMSetSparseLocalize", sparseLocalize, &sparseLocalize, &flg)); 5393c3db174cSMatthew G. Knepley if (flg) PetscCall(DMSetSparseLocalize(dm, sparseLocalize)); 53945515ebd3SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg)); 53955515ebd3SMatthew G. Knepley if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height)); 5396c3db174cSMatthew G. Knepley if (localize) PetscCall(DMLocalizeCoordinates(dm)); 53979318fe57SMatthew G. Knepley } 539868d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 539961a622f3SMatthew G. Knepley remap = PETSC_TRUE; 54009566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 54019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 54029566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 54039566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 540468d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 5405acdc6f61SToby Isaac DM *dms, coarseDM; 540668d4fef7SMatthew G. Knepley 54079566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 54089566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 54099566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 54109566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 541168d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 54129566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 541368d4fef7SMatthew G. Knepley if (refine == 1) { 54149566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 54159566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 541668d4fef7SMatthew G. Knepley } else { 54179566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 54189566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 54199566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 54209566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 542168d4fef7SMatthew G. Knepley } 54229566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 54239566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 542468d4fef7SMatthew G. Knepley /* Free DMs */ 542568d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 5426dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 54279566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 542868d4fef7SMatthew G. Knepley } 54299566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 543068d4fef7SMatthew G. Knepley } else { 543168d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 54329318fe57SMatthew G. Knepley DM rdm; 54332192575eSBarry Smith PetscPointFn *coordFunc; 543468d4fef7SMatthew G. Knepley 5435dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54369566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 543768d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 543869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 5439dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54403674be70SMatthew G. Knepley PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc)); 544161a622f3SMatthew G. Knepley if (coordFunc && remap) { 54429566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 5443509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, coordFunc)); 544451a74b61SMatthew G. Knepley } 544568d4fef7SMatthew G. Knepley } 544668d4fef7SMatthew G. Knepley } 54473cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 54489566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 54499566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 5450b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 5451b653a561SMatthew G. Knepley DM *dms; 5452b653a561SMatthew G. Knepley 54539566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 54549566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 5455b653a561SMatthew G. Knepley /* Free DMs */ 5456b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 5457dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 54589566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 5459b653a561SMatthew G. Knepley } 54609566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 5461b653a561SMatthew G. Knepley } else { 5462b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 54639318fe57SMatthew G. Knepley DM cdm; 54642192575eSBarry Smith PetscPointFn *coordFunc; 54653cf6fe12SMatthew G. Knepley 5466509b31aaSMatthew G. Knepley PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc)); 5467dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54689566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 54693cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 547069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 5471dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54729318fe57SMatthew G. Knepley if (coordFunc) { 54739566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 5474509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, coordFunc)); 54759318fe57SMatthew G. Knepley } 54763cf6fe12SMatthew G. Knepley } 5477b653a561SMatthew G. Knepley } 5478be664eb1SMatthew G. Knepley // Handle coordinate remapping 5479be664eb1SMatthew G. Knepley remap = PETSC_FALSE; 5480be664eb1SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_coord_remap", "Flag to control coordinate remapping", "", remap, &remap, NULL)); 5481be664eb1SMatthew G. Knepley if (remap) { 5482be664eb1SMatthew G. Knepley DMPlexCoordMap map = DM_COORD_MAP_NONE; 54832192575eSBarry Smith PetscPointFn *mapFunc = NULL; 5484be664eb1SMatthew G. Knepley PetscScalar params[16]; 5485f45b553cSPierre Jolivet PetscInt Np = PETSC_STATIC_ARRAY_LENGTH(params), cdim; 5486be664eb1SMatthew G. Knepley MPI_Comm comm; 5487be664eb1SMatthew G. Knepley 5488be664eb1SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 5489be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 5490be664eb1SMatthew G. Knepley PetscCall(PetscOptionsScalarArray("-dm_coord_map_params", "Parameters for the coordinate remapping", "", params, &Np, &flg)); 5491be664eb1SMatthew G. Knepley if (!flg) Np = 0; 5492be664eb1SMatthew G. Knepley // TODO Allow user to pass a map function by name 5493be664eb1SMatthew G. Knepley PetscCall(PetscOptionsEnum("-dm_coord_map", "Coordinate mapping for built-in mesh", "", DMPlexCoordMaps, (PetscEnum)map, (PetscEnum *)&map, &flg)); 5494be664eb1SMatthew G. Knepley if (flg) { 5495be664eb1SMatthew G. Knepley switch (map) { 5496be664eb1SMatthew G. Knepley case DM_COORD_MAP_NONE: 5497be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5498be664eb1SMatthew G. Knepley break; 5499be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHEAR: 5500be664eb1SMatthew G. Knepley mapFunc = coordMap_shear; 5501be664eb1SMatthew G. Knepley if (!Np) { 5502be664eb1SMatthew G. Knepley Np = cdim + 1; 5503be664eb1SMatthew G. Knepley params[0] = 0; 5504be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5505be664eb1SMatthew G. Knepley } 5506be664eb1SMatthew 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); 5507be664eb1SMatthew G. Knepley break; 5508be664eb1SMatthew G. Knepley case DM_COORD_MAP_FLARE: 5509be664eb1SMatthew G. Knepley mapFunc = coordMap_flare; 5510be664eb1SMatthew G. Knepley if (!Np) { 5511be664eb1SMatthew G. Knepley Np = cdim + 1; 5512be664eb1SMatthew G. Knepley params[0] = 0; 5513be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5514be664eb1SMatthew G. Knepley } 5515be664eb1SMatthew 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); 5516be664eb1SMatthew G. Knepley break; 5517be664eb1SMatthew G. Knepley case DM_COORD_MAP_ANNULUS: 5518be664eb1SMatthew G. Knepley mapFunc = coordMap_annulus; 5519be664eb1SMatthew G. Knepley if (!Np) { 5520be664eb1SMatthew G. Knepley Np = 2; 5521be664eb1SMatthew G. Knepley params[0] = 1.; 5522be664eb1SMatthew G. Knepley params[1] = 2.; 5523be664eb1SMatthew G. Knepley } 5524be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The annulus coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5525be664eb1SMatthew G. Knepley break; 5526be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHELL: 5527be664eb1SMatthew G. Knepley mapFunc = coordMap_shell; 5528be664eb1SMatthew G. Knepley if (!Np) { 5529be664eb1SMatthew G. Knepley Np = 2; 5530be664eb1SMatthew G. Knepley params[0] = 1.; 5531be664eb1SMatthew G. Knepley params[1] = 2.; 5532be664eb1SMatthew G. Knepley } 5533be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The spherical shell coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5534be664eb1SMatthew G. Knepley break; 5535530e699aSMatthew G. Knepley case DM_COORD_MAP_SINUSOID: 5536530e699aSMatthew G. Knepley mapFunc = coordMap_sinusoid; 5537530e699aSMatthew G. Knepley if (!Np) { 5538530e699aSMatthew G. Knepley Np = 3; 5539530e699aSMatthew G. Knepley params[0] = 1.; 5540530e699aSMatthew G. Knepley params[1] = 1.; 5541530e699aSMatthew G. Knepley params[2] = 1.; 5542530e699aSMatthew G. Knepley } 5543530e699aSMatthew G. Knepley PetscCheck(Np == 3, comm, PETSC_ERR_ARG_WRONG, "The sinusoidal coordinate map must have 3 parameters, not %" PetscInt_FMT, Np); 5544530e699aSMatthew G. Knepley break; 5545be664eb1SMatthew G. Knepley default: 5546be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5547be664eb1SMatthew G. Knepley } 5548be664eb1SMatthew G. Knepley } 5549be664eb1SMatthew G. Knepley if (Np) { 5550be664eb1SMatthew G. Knepley DM cdm; 5551be664eb1SMatthew G. Knepley PetscDS cds; 5552be664eb1SMatthew G. Knepley 5553be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5554be664eb1SMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 5555be664eb1SMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, Np, params)); 5556be664eb1SMatthew G. Knepley } 5557be664eb1SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, mapFunc)); 5558be664eb1SMatthew G. Knepley } 5559909dfd52SMatthew G. Knepley /* Handle ghost cells */ 55609566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 5561909dfd52SMatthew G. Knepley if (ghostCells) { 5562909dfd52SMatthew G. Knepley DM gdm; 5563909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 5564909dfd52SMatthew G. Knepley 5565909dfd52SMatthew G. Knepley lname[0] = '\0'; 55669566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 55679566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 556869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 5569909dfd52SMatthew G. Knepley } 55706913077dSMatthew G. Knepley /* Handle 1D order */ 5571adc21957SMatthew G. Knepley if (reorder != DM_REORDER_DEFAULT_FALSE && dim == 1) { 55726913077dSMatthew G. Knepley DM cdm, rdm; 55736913077dSMatthew G. Knepley PetscDS cds; 55746913077dSMatthew G. Knepley PetscObject obj; 55756913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 55766913077dSMatthew G. Knepley IS perm; 55776bc1bd01Sksagiyam PetscInt Nf; 55786913077dSMatthew G. Knepley PetscBool distributed; 55796913077dSMatthew G. Knepley 55809566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 55819566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 55829566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 55839566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 55846913077dSMatthew G. Knepley if (Nf) { 55859566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 55869566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 55876913077dSMatthew G. Knepley } 55886bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 55899566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 55909566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 559169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 55929566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 55936913077dSMatthew G. Knepley } 55946913077dSMatthew G. Knepley } 55953cf6fe12SMatthew G. Knepley /* Handle */ 5596dd4c3f67SMatthew G. Knepley non_refine: 5597dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 559822d6dc08SStefano Zampini char *phases[16]; 559922d6dc08SStefano Zampini PetscInt Nphases = 16; 560022d6dc08SStefano Zampini PetscCall(PetscOptionsStringArray("-dm_plex_option_phases", "Option phase prefixes", "DMSetFromOptions", phases, &Nphases, &flg)); 5601d0609cedSBarry Smith PetscOptionsHeadEnd(); 560222d6dc08SStefano Zampini 560322d6dc08SStefano Zampini // Phases 560422d6dc08SStefano Zampini if (flg) { 5605530e699aSMatthew G. Knepley DM cdm; 5606530e699aSMatthew G. Knepley char *oldPrefix, *oldCoordPrefix; 5607530e699aSMatthew G. Knepley const char *tmp; 560822d6dc08SStefano Zampini 5609530e699aSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5610530e699aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &tmp)); 5611530e699aSMatthew G. Knepley PetscCall(PetscStrallocpy(tmp, &oldPrefix)); 5612530e699aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)cdm, &tmp)); 5613530e699aSMatthew G. Knepley PetscCall(PetscStrallocpy(tmp, &oldCoordPrefix)); 561422d6dc08SStefano Zampini for (PetscInt ph = 0; ph < Nphases; ++ph) { 561522d6dc08SStefano Zampini PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, phases[ph])); 5616530e699aSMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)cdm, phases[ph])); 561722d6dc08SStefano Zampini PetscCall(PetscInfo(dm, "Options phase %s for DM %s\n", phases[ph], dm->hdr.name)); 561822d6dc08SStefano Zampini PetscCall(DMSetFromOptions(dm)); 561922d6dc08SStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix)); 5620530e699aSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5621530e699aSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)cdm, oldCoordPrefix)); 562222d6dc08SStefano Zampini PetscCall(PetscFree(phases[ph])); 562322d6dc08SStefano Zampini } 5624530e699aSMatthew G. Knepley PetscCall(PetscFree(oldPrefix)); 5625530e699aSMatthew G. Knepley PetscCall(PetscFree(oldCoordPrefix)); 562622d6dc08SStefano Zampini } 56273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56280a6ba040SMatthew G. Knepley } 56290a6ba040SMatthew G. Knepley 5630d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) 5631d71ae5a4SJacob Faibussowitsch { 5632552f7358SJed Brown PetscFunctionBegin; 56339566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 56349566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 56359566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 56369566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 56379566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 56389566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 56393ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5640552f7358SJed Brown } 5641552f7358SJed Brown 5642d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) 5643d71ae5a4SJacob Faibussowitsch { 5644552f7358SJed Brown PetscFunctionBegin; 56459566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 56469566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 56479566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 56483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5649552f7358SJed Brown } 5650552f7358SJed Brown 5651d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 5652d71ae5a4SJacob Faibussowitsch { 5653793f3fe5SMatthew G. Knepley PetscInt depth, d; 5654793f3fe5SMatthew G. Knepley 5655793f3fe5SMatthew G. Knepley PetscFunctionBegin; 56569566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 5657793f3fe5SMatthew G. Knepley if (depth == 1) { 56589566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 56599566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 56609566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 56619371c9d4SSatish Balay else { 56629371c9d4SSatish Balay *pStart = 0; 56639371c9d4SSatish Balay *pEnd = 0; 56649371c9d4SSatish Balay } 5665793f3fe5SMatthew G. Knepley } else { 56669566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 5667793f3fe5SMatthew G. Knepley } 56683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5669793f3fe5SMatthew G. Knepley } 5670793f3fe5SMatthew G. Knepley 5671d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 5672d71ae5a4SJacob Faibussowitsch { 5673502a2867SDave May PetscSF sf; 56746497c311SBarry Smith PetscMPIInt niranks, njranks; 56756497c311SBarry Smith PetscInt n; 56760a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 56770a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 5678502a2867SDave May 56792f356facSMatthew G. Knepley PetscFunctionBegin; 56809566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 56810a19bb7dSprj- if (!data->neighbors) { 56829566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 56839566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 56849566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 56859566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 56869566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 56879566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 56880a19bb7dSprj- n = njranks + niranks; 56899566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 56900a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 56919566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 56920a19bb7dSprj- } 56930a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 56940a19bb7dSprj- if (ranks) { 56950a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 56960a19bb7dSprj- else *ranks = NULL; 56970a19bb7dSprj- } 56983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5699502a2867SDave May } 5700502a2867SDave May 57011eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 57021eb70e55SToby Isaac 5703d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm) 5704d71ae5a4SJacob Faibussowitsch { 5705552f7358SJed Brown PetscFunctionBegin; 5706552f7358SJed Brown dm->ops->view = DMView_Plex; 57072c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 5708552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 570938221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 5710552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 57111bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 5712adc21957SMatthew G. Knepley dm->ops->createsectionpermutation = DMCreateSectionPermutation_Plex; 571366ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 5714552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 5715552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 5716184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 57170298fd71SBarry Smith dm->ops->createfieldis = NULL; 5718552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 571999acd26cSksagiyam dm->ops->createcellcoordinatedm = DMCreateCellCoordinateDM_Plex; 5720f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 57210a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 5722552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 5723bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 5724bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 5725b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 57265a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 5727552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 57280a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 57290a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 5730b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 5731d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 57320298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 57330298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 57340298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 57350298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 5736552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 5737552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 57382adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 5739793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 5740552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 57410709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 57420709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 5743bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 57448c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 5745ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 57460709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 5747b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 57482a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 574928d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 57506c6a6b79SMatthew G. Knepley dm->ops->getlocalboundingbox = DMGetLocalBoundingBox_Coordinates; 5751907a3e9cSStefano Zampini dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_Plex; 5752907a3e9cSStefano Zampini dm->ops->createddscatters = DMCreateDomainDecompositionScatters_Plex; 57539566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 57546c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 575501468941SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBounds_C", DMPlexInsertBounds_Plex)); 57569566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 57579566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 57589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 57599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 57606bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 57616bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 5762adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", DMReorderSectionGetDefault_Plex)); 5763adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", DMReorderSectionSetDefault_Plex)); 5764adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", DMReorderSectionGetType_Plex)); 5765adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", DMReorderSectionSetType_Plex)); 57669566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 5767c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 5768c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 5769d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", DMPlexGetUseCeed_Plex)); 5770d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", DMPlexSetUseCeed_Plex)); 57713ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5772552f7358SJed Brown } 5773552f7358SJed Brown 5774d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 5775d71ae5a4SJacob Faibussowitsch { 577663a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 57771fca310dSJames Wright const PetscSF *face_sfs; 57781fca310dSJames Wright PetscInt num_face_sfs; 577963a16f15SMatthew G. Knepley 578063a16f15SMatthew G. Knepley PetscFunctionBegin; 578163a16f15SMatthew G. Knepley mesh->refct++; 578263a16f15SMatthew G. Knepley (*newdm)->data = mesh; 57831fca310dSJames Wright PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &face_sfs)); 57841fca310dSJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, num_face_sfs, (PetscSF *)face_sfs)); 57859566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 57869566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 57873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 578863a16f15SMatthew G. Knepley } 578963a16f15SMatthew G. Knepley 57908818961aSMatthew G Knepley /*MC 57910b4b7b1cSBarry Smith DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh (or grid), or CW Complex {cite}`cwcomplex`, 57920b4b7b1cSBarry Smith which can be expressed using a Hasse Diagram {cite}`hassediagram`. 579320f4b53cSBarry Smith In the local representation, `Vec`s contain all unknowns in the interior and shared boundary. This is 57940b4b7b1cSBarry Smith specified by a `PetscSection` object. Ownership in the global representation is determined by 5795a1cb98faSBarry Smith ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object. 57968818961aSMatthew G Knepley 5797e5893cccSMatthew G. Knepley Options Database Keys: 5798250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 5799250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 5800250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 5801250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 5802250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 5803250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 5804c3db174cSMatthew G. Knepley . -dm_localize <bool> - Whether to localize coordinates for periodic meshes 5805c3db174cSMatthew G. Knepley . -dm_sparse_localize <bool> - Whether to only localize cells on the periodic boundary 5806250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 5807ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 5808f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 5809f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 5810d5b43468SJose E. Roman . -dm_plex_max_projection_height - Maximum mesh point height used to project locally 5811f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 5812d02c7345SMatthew G. Knepley . -dm_plex_reorder_section - Use specialized blocking if available 5813aaa8cc7dSPierre Jolivet . -dm_plex_check_all - Perform all checks below 5814f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 5815f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 5816f12cf164SMatthew 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 5817f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 5818f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 5819e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 58205962854dSMatthew G. Knepley . -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 58215962854dSMatthew G. Knepley - -dm_plex_print_fvm <num> - View FVM assembly information, such as flux updates 5822e5893cccSMatthew G. Knepley 58238818961aSMatthew G Knepley Level: intermediate 58248818961aSMatthew G Knepley 58251cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection` 58268818961aSMatthew G Knepley M*/ 58278818961aSMatthew G Knepley 5828d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 5829d71ae5a4SJacob Faibussowitsch { 5830552f7358SJed Brown DM_Plex *mesh; 5831412e9a14SMatthew G. Knepley PetscInt unit; 5832552f7358SJed Brown 5833552f7358SJed Brown PetscFunctionBegin; 5834f39ec787SMatthew G. Knepley PetscCall(PetscCitationsRegister(PlexCitation, &Plexcite)); 5835552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58364dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mesh)); 5837adc21957SMatthew G. Knepley dm->reorderSection = DM_REORDER_DEFAULT_NOTSET; 5838552f7358SJed Brown dm->data = mesh; 5839552f7358SJed Brown 5840552f7358SJed Brown mesh->refct = 1; 58419566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 58429566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 5843552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 5844552f7358SJed Brown mesh->refinementLimit = -1.0; 5845e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 5846adc21957SMatthew G. Knepley mesh->reorderDefault = DM_REORDER_DEFAULT_NOTSET; 58471d1f2f2aSksagiyam mesh->distributionName = NULL; 58487d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 58497d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 58505e2c5519SMatthew G. Knepley mesh->interpolatePreferTensor = PETSC_TRUE; 5851552f7358SJed Brown 58529566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 58532e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 5854d9deefdfSMatthew G. Knepley 58558865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 5856552f7358SJed Brown 5857df0420ecSMatthew G. Knepley mesh->depthState = -1; 5858ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 58596113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 5860c29ce622SStefano Zampini mesh->nonempty_comm = MPI_COMM_SELF; 5861552f7358SJed Brown 58629566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 58633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5864552f7358SJed Brown } 5865552f7358SJed Brown 5866552f7358SJed Brown /*@ 5867a1cb98faSBarry Smith DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 5868552f7358SJed Brown 5869d083f849SBarry Smith Collective 5870552f7358SJed Brown 5871552f7358SJed Brown Input Parameter: 5872a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object 5873552f7358SJed Brown 5874552f7358SJed Brown Output Parameter: 5875a1cb98faSBarry Smith . mesh - The `DMPLEX` object 5876552f7358SJed Brown 5877552f7358SJed Brown Level: beginner 5878552f7358SJed Brown 587942747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMCreate()`, `DMSetType()` 5880552f7358SJed Brown @*/ 5881d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 5882d71ae5a4SJacob Faibussowitsch { 5883552f7358SJed Brown PetscFunctionBegin; 58844f572ea9SToby Isaac PetscAssertPointer(mesh, 2); 58859566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 58869566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 58873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5888552f7358SJed Brown } 5889552f7358SJed Brown 5890b09969d6SVaclav Hapla /*@C 5891b0fe842aSMatthew G. Knepley DMPlexBuildFromCellListParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) where all cells have the same celltype 5892a1cb98faSBarry Smith 589320f4b53cSBarry Smith Collective; No Fortran Support 5894b09969d6SVaclav Hapla 5895b09969d6SVaclav Hapla Input Parameters: 5896a1cb98faSBarry Smith + dm - The `DM` 5897b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 5898a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 5899a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DETERMINE` 5900b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 59015e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 5902b09969d6SVaclav Hapla 5903be8c289dSNicolas Barral Output Parameters: 5904a1cb98faSBarry Smith + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 5905be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 5906b09969d6SVaclav Hapla 5907b09969d6SVaclav Hapla Level: advanced 5908b09969d6SVaclav Hapla 5909a1cb98faSBarry Smith Notes: 5910a1cb98faSBarry Smith Two triangles sharing a face 5911a1cb98faSBarry Smith .vb 5912a1cb98faSBarry Smith 5913a1cb98faSBarry Smith 2 5914a1cb98faSBarry Smith / | \ 5915a1cb98faSBarry Smith / | \ 5916a1cb98faSBarry Smith / | \ 5917a1cb98faSBarry Smith 0 0 | 1 3 5918a1cb98faSBarry Smith \ | / 5919a1cb98faSBarry Smith \ | / 5920a1cb98faSBarry Smith \ | / 5921a1cb98faSBarry Smith 1 5922a1cb98faSBarry Smith .ve 5923a1cb98faSBarry Smith would have input 5924a1cb98faSBarry Smith .vb 5925a1cb98faSBarry Smith numCells = 2, numVertices = 4 5926a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 5927a1cb98faSBarry Smith .ve 5928a1cb98faSBarry Smith which would result in the `DMPLEX` 5929a1cb98faSBarry Smith .vb 5930a1cb98faSBarry Smith 5931a1cb98faSBarry Smith 4 5932a1cb98faSBarry Smith / | \ 5933a1cb98faSBarry Smith / | \ 5934a1cb98faSBarry Smith / | \ 5935a1cb98faSBarry Smith 2 0 | 1 5 5936a1cb98faSBarry Smith \ | / 5937a1cb98faSBarry Smith \ | / 5938a1cb98faSBarry Smith \ | / 5939a1cb98faSBarry Smith 3 5940a1cb98faSBarry Smith .ve 5941a1cb98faSBarry Smith 5942a1cb98faSBarry Smith Vertices are implicitly numbered consecutively 0,...,NVertices. 5943a1cb98faSBarry Smith Each rank owns a chunk of numVertices consecutive vertices. 5944a1cb98faSBarry Smith If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 5945a1cb98faSBarry Smith If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 5946a1cb98faSBarry Smith If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 5947a1cb98faSBarry Smith 5948a1cb98faSBarry Smith The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 5949a1cb98faSBarry Smith 59501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 5951a1cb98faSBarry Smith `PetscSF` 5952b09969d6SVaclav Hapla @*/ 5953ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[]) 5954d71ae5a4SJacob Faibussowitsch { 59552464107aSksagiyam PetscSF sfPoint; 59562464107aSksagiyam PetscLayout layout; 595782fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 5958a47d0d45SMatthew G. Knepley 5959a47d0d45SMatthew G. Knepley PetscFunctionBegin; 596025b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 59619566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 596225b6865aSVaclav Hapla /* Get/check global number of vertices */ 596325b6865aSVaclav Hapla { 596425b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 596525b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 596625b6865aSVaclav Hapla 596725b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 59681690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 59699371c9d4SSatish Balay for (i = 0; i < len; i++) 59709371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 597125b6865aSVaclav Hapla ++NVerticesInCells; 5972462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 597325b6865aSVaclav Hapla 597425b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 59759371c9d4SSatish Balay else 59769371c9d4SSatish 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); 597725b6865aSVaclav Hapla } 59789079aca8SVaclav Hapla /* Count locally unique vertices */ 59799079aca8SVaclav Hapla { 59809079aca8SVaclav Hapla PetscHSetI vhash; 59819079aca8SVaclav Hapla PetscInt off = 0; 59829079aca8SVaclav Hapla 59839566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 5984a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 598548a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 5986a47d0d45SMatthew G. Knepley } 59879566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 59889566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 5989ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 59909566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 59919566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 599263a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 5993a47d0d45SMatthew G. Knepley } 59949566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 5995a47d0d45SMatthew G. Knepley /* Create cones */ 59969566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 59979566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 59989566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 59999566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 6000a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 6001a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 6002a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 6003a47d0d45SMatthew G. Knepley PetscInt lv; 6004a47d0d45SMatthew G. Knepley 60059079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 60069079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 60079566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 600863a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 6009961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 6010a47d0d45SMatthew G. Knepley } 6011a47d0d45SMatthew G. Knepley } 60122464107aSksagiyam /* Build point sf */ 60139566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 60149566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 60159566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 60169566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 60179566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 60189566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 60199566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 60209566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 60212464107aSksagiyam if (dm->sf) { 60222464107aSksagiyam const char *prefix; 60232464107aSksagiyam 60249566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 60259566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 60262464107aSksagiyam } 60279566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 60289566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 6029f4f49eeaSPierre Jolivet if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 6030a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 60319566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 60329566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 60339566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 60343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6035a47d0d45SMatthew G. Knepley } 6036a47d0d45SMatthew G. Knepley 6037b0fe842aSMatthew G. Knepley /*@C 6038b0fe842aSMatthew G. Knepley DMPlexBuildFromCellSectionParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) allowing multiple celltypes 6039b0fe842aSMatthew G. Knepley 6040b0fe842aSMatthew G. Knepley Collective; No Fortran Support 6041b0fe842aSMatthew G. Knepley 6042b0fe842aSMatthew G. Knepley Input Parameters: 6043b0fe842aSMatthew G. Knepley + dm - The `DM` 6044b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 6045b0fe842aSMatthew G. Knepley . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 6046b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DETERMINE` 6047b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 6048b0fe842aSMatthew G. Knepley - cells - An array of the global vertex numbers for each cell 6049b0fe842aSMatthew G. Knepley 6050b0fe842aSMatthew G. Knepley Output Parameters: 6051b0fe842aSMatthew G. Knepley + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 6052b0fe842aSMatthew G. Knepley - verticesAdjSaved - (Optional) vertex adjacency array 6053b0fe842aSMatthew G. Knepley 6054b0fe842aSMatthew G. Knepley Level: advanced 6055b0fe842aSMatthew G. Knepley 6056b0fe842aSMatthew G. Knepley Notes: 6057b0fe842aSMatthew G. Knepley A triangle and quadrilateral sharing a face 6058b0fe842aSMatthew G. Knepley .vb 6059b0fe842aSMatthew G. Knepley 2----------3 6060b0fe842aSMatthew G. Knepley / | | 6061b0fe842aSMatthew G. Knepley / | | 6062b0fe842aSMatthew G. Knepley / | | 6063b0fe842aSMatthew G. Knepley 0 0 | 1 | 6064b0fe842aSMatthew G. Knepley \ | | 6065b0fe842aSMatthew G. Knepley \ | | 6066b0fe842aSMatthew G. Knepley \ | | 6067b0fe842aSMatthew G. Knepley 1----------4 6068b0fe842aSMatthew G. Knepley .ve 6069b0fe842aSMatthew G. Knepley would have input 6070b0fe842aSMatthew G. Knepley .vb 6071b0fe842aSMatthew G. Knepley numCells = 2, numVertices = 5 6072b0fe842aSMatthew G. Knepley cells = [0 1 2 1 4 3 2] 6073b0fe842aSMatthew G. Knepley .ve 6074b0fe842aSMatthew G. Knepley which would result in the `DMPLEX` 6075b0fe842aSMatthew G. Knepley .vb 6076b0fe842aSMatthew G. Knepley 4----------5 6077b0fe842aSMatthew G. Knepley / | | 6078b0fe842aSMatthew G. Knepley / | | 6079b0fe842aSMatthew G. Knepley / | | 6080b0fe842aSMatthew G. Knepley 2 0 | 1 | 6081b0fe842aSMatthew G. Knepley \ | | 6082b0fe842aSMatthew G. Knepley \ | | 6083b0fe842aSMatthew G. Knepley \ | | 6084b0fe842aSMatthew G. Knepley 3----------6 6085b0fe842aSMatthew G. Knepley .ve 6086b0fe842aSMatthew G. Knepley 6087b0fe842aSMatthew G. Knepley Vertices are implicitly numbered consecutively 0,...,NVertices. 6088b0fe842aSMatthew G. Knepley Each rank owns a chunk of numVertices consecutive vertices. 6089b0fe842aSMatthew G. Knepley If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 6090b0fe842aSMatthew 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. 6091b0fe842aSMatthew G. Knepley If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 6092b0fe842aSMatthew G. Knepley 6093b0fe842aSMatthew G. Knepley The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 6094b0fe842aSMatthew G. Knepley 6095b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexCreateFromCellSectionParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 6096b0fe842aSMatthew G. Knepley `PetscSF` 6097b0fe842aSMatthew G. Knepley @*/ 6098ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellSectionParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[]) 6099b0fe842aSMatthew G. Knepley { 6100b0fe842aSMatthew G. Knepley PetscSF sfPoint; 6101b0fe842aSMatthew G. Knepley PetscLayout layout; 6102b0fe842aSMatthew G. Knepley PetscInt numVerticesAdj, *verticesAdj, *cones, cStart, cEnd, len; 6103b0fe842aSMatthew G. Knepley 6104b0fe842aSMatthew G. Knepley PetscFunctionBegin; 6105b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, NVertices, 4); 6106b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 6107b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetChart(cellSection, &cStart, &cEnd)); 6108b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(cellSection, &len)); 6109b0fe842aSMatthew 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); 6110b0fe842aSMatthew G. Knepley /* Get/check global number of vertices */ 6111b0fe842aSMatthew G. Knepley { 6112b0fe842aSMatthew G. Knepley PetscInt NVerticesInCells; 6113b0fe842aSMatthew G. Knepley 6114b0fe842aSMatthew G. Knepley /* NVerticesInCells = max(cells) + 1 */ 6115b0fe842aSMatthew G. Knepley NVerticesInCells = PETSC_MIN_INT; 6116b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) 6117b0fe842aSMatthew G. Knepley if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 6118b0fe842aSMatthew G. Knepley ++NVerticesInCells; 6119b0fe842aSMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 6120b0fe842aSMatthew G. Knepley 6121b0fe842aSMatthew G. Knepley if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 6122b0fe842aSMatthew G. Knepley else 6123b0fe842aSMatthew 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); 6124b0fe842aSMatthew G. Knepley } 6125b0fe842aSMatthew G. Knepley /* Count locally unique vertices */ 6126b0fe842aSMatthew G. Knepley { 6127b0fe842aSMatthew G. Knepley PetscHSetI vhash; 6128b0fe842aSMatthew G. Knepley PetscInt off = 0; 6129b0fe842aSMatthew G. Knepley 6130b0fe842aSMatthew G. Knepley PetscCall(PetscHSetICreate(&vhash)); 6131b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) PetscCall(PetscHSetIAdd(vhash, cells[i])); 6132b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 6133b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 6134b0fe842aSMatthew G. Knepley else verticesAdj = *verticesAdjSaved; 6135b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 6136b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIDestroy(&vhash)); 6137b0fe842aSMatthew 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); 6138b0fe842aSMatthew G. Knepley } 6139b0fe842aSMatthew G. Knepley PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 6140b0fe842aSMatthew G. Knepley /* Create cones */ 6141b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 6142b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 6143b0fe842aSMatthew G. Knepley PetscInt dof; 6144b0fe842aSMatthew G. Knepley 6145b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 6146b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetConeSize(dm, c, dof)); 6147b0fe842aSMatthew G. Knepley } 6148b0fe842aSMatthew G. Knepley PetscCall(DMSetUp(dm)); 6149b0fe842aSMatthew G. Knepley PetscCall(DMPlexGetCones(dm, &cones)); 6150b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 6151b0fe842aSMatthew G. Knepley PetscInt dof, off; 6152b0fe842aSMatthew G. Knepley 6153b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 6154b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cellSection, c, &off)); 6155b0fe842aSMatthew G. Knepley for (PetscInt p = off; p < off + dof; ++p) { 6156b0fe842aSMatthew G. Knepley const PetscInt gv = cells[p]; 6157b0fe842aSMatthew G. Knepley PetscInt lv; 6158b0fe842aSMatthew G. Knepley 6159b0fe842aSMatthew G. Knepley /* Positions within verticesAdj form 0-based local vertex numbering; 6160b0fe842aSMatthew G. Knepley we need to shift it by numCells to get correct DAG points (cells go first) */ 6161b0fe842aSMatthew G. Knepley PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 6162b0fe842aSMatthew G. Knepley PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 6163b0fe842aSMatthew G. Knepley cones[p] = lv + numCells; 6164b0fe842aSMatthew G. Knepley } 6165b0fe842aSMatthew G. Knepley } 6166b0fe842aSMatthew G. Knepley /* Build point sf */ 6167b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 6168b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetSize(layout, NVertices)); 6169b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 6170b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetBlockSize(layout, 1)); 6171b0fe842aSMatthew G. Knepley PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 6172b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutDestroy(&layout)); 6173b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 6174b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 6175b0fe842aSMatthew G. Knepley if (dm->sf) { 6176b0fe842aSMatthew G. Knepley const char *prefix; 6177b0fe842aSMatthew G. Knepley 6178b0fe842aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 6179b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 6180b0fe842aSMatthew G. Knepley } 6181b0fe842aSMatthew G. Knepley PetscCall(DMSetPointSF(dm, sfPoint)); 6182b0fe842aSMatthew G. Knepley PetscCall(PetscSFDestroy(&sfPoint)); 6183b0fe842aSMatthew G. Knepley if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 6184b0fe842aSMatthew G. Knepley /* Fill in the rest of the topology structure */ 6185b0fe842aSMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 6186b0fe842aSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 6187b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 6188b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 6189b0fe842aSMatthew G. Knepley } 6190b0fe842aSMatthew G. Knepley 6191cc4c1da9SBarry Smith /*@ 6192a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 6193a1cb98faSBarry Smith 619420f4b53cSBarry Smith Collective; No Fortran Support 6195b09969d6SVaclav Hapla 6196b09969d6SVaclav Hapla Input Parameters: 6197a1cb98faSBarry Smith + dm - The `DM` 6198b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6199a1cb98faSBarry Smith . sfVert - `PetscSF` describing complete vertex ownership 6200b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6201b09969d6SVaclav Hapla 6202b09969d6SVaclav Hapla Level: advanced 6203b09969d6SVaclav Hapla 62041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 6205b09969d6SVaclav Hapla @*/ 6206d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 6207d71ae5a4SJacob Faibussowitsch { 6208a47d0d45SMatthew G. Knepley PetscSection coordSection; 6209a47d0d45SMatthew G. Knepley Vec coordinates; 6210a47d0d45SMatthew G. Knepley PetscScalar *coords; 62111edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 6212835f2295SStefano Zampini PetscMPIInt spaceDimi; 6213a47d0d45SMatthew G. Knepley 6214a47d0d45SMatthew G. Knepley PetscFunctionBegin; 62159566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 62169566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 62171dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 62189566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 62199566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 62201dca8a05SBarry 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); 62219566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 62229566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 62239566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 62249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 62251edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 62269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 62279566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 6228a47d0d45SMatthew G. Knepley } 62299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 62309566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 62319566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 62329566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 62339566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 62349566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 62359566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 62369566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6237a47d0d45SMatthew G. Knepley { 6238a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 6239a47d0d45SMatthew G. Knepley 6240a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 6241835f2295SStefano Zampini PetscCall(PetscMPIIntCast(spaceDim, &spaceDimi)); 6242835f2295SStefano Zampini PetscCallMPI(MPI_Type_contiguous(spaceDimi, MPIU_SCALAR, &coordtype)); 62439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 624421016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 624521016a8bSBarry Smith { 624621016a8bSBarry Smith PetscScalar *svertexCoords; 624721016a8bSBarry Smith PetscInt i; 62489566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 62493612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 62509566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 62519566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 62529566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 625321016a8bSBarry Smith } 625421016a8bSBarry Smith #else 62559566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 62569566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 625721016a8bSBarry Smith #endif 62589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 6259a47d0d45SMatthew G. Knepley } 62609566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 62619566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 62629566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 62639566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 62643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6265a47d0d45SMatthew G. Knepley } 6266a47d0d45SMatthew G. Knepley 6267c3edce3dSSatish Balay /*@ 6268b0fe842aSMatthew 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 6269a1cb98faSBarry Smith 6270a1cb98faSBarry Smith Collective 6271a47d0d45SMatthew G. Knepley 6272a47d0d45SMatthew G. Knepley Input Parameters: 6273a47d0d45SMatthew G. Knepley + comm - The communicator 6274a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 6275a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 6276a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 6277a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DECIDE` 6278a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 6279a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6280a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 6281a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 6282a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6283a47d0d45SMatthew G. Knepley 6284d8d19677SJose E. Roman Output Parameters: 6285a1cb98faSBarry Smith + dm - The `DM` 6286a1cb98faSBarry Smith . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 628760225df5SJacob Faibussowitsch - verticesAdj - (Optional) vertex adjacency array 6288a47d0d45SMatthew G. Knepley 6289b09969d6SVaclav Hapla Level: intermediate 6290a47d0d45SMatthew G. Knepley 6291a1cb98faSBarry Smith Notes: 6292a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 6293a1cb98faSBarry Smith `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 6294a1cb98faSBarry Smith 6295a1cb98faSBarry Smith See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters. 6296a1cb98faSBarry Smith 6297a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 6298a1cb98faSBarry Smith 62991cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 6300a47d0d45SMatthew G. Knepley @*/ 6301ce78bad3SBarry 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) 6302d71ae5a4SJacob Faibussowitsch { 6303a47d0d45SMatthew G. Knepley PetscSF sfVert; 6304a47d0d45SMatthew G. Knepley 6305a47d0d45SMatthew G. Knepley PetscFunctionBegin; 63069566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 63079566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 6308a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 6309064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 63109566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 63119566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 6312a47d0d45SMatthew G. Knepley if (interpolate) { 63135fd9971aSMatthew G. Knepley DM idm; 6314a47d0d45SMatthew G. Knepley 63159566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 63169566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 6317a47d0d45SMatthew G. Knepley *dm = idm; 6318a47d0d45SMatthew G. Knepley } 63199566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 632018d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 63219566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 63223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6323a47d0d45SMatthew G. Knepley } 6324a47d0d45SMatthew G. Knepley 6325cc4c1da9SBarry Smith /*@ 6326b0fe842aSMatthew G. Knepley DMPlexCreateFromCellSectionParallel - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) and supports multiple celltypes 6327b0fe842aSMatthew G. Knepley 6328b0fe842aSMatthew G. Knepley Collective 6329b0fe842aSMatthew G. Knepley 6330b0fe842aSMatthew G. Knepley Input Parameters: 6331b0fe842aSMatthew G. Knepley + comm - The communicator 6332b0fe842aSMatthew G. Knepley . dim - The topological dimension of the mesh 6333b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 6334b0fe842aSMatthew G. Knepley . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 6335b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DECIDE` 6336b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 6337b0fe842aSMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6338b0fe842aSMatthew G. Knepley . cells - An array of the global vertex numbers for each cell 6339b0fe842aSMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 6340b0fe842aSMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6341b0fe842aSMatthew G. Knepley 6342b0fe842aSMatthew G. Knepley Output Parameters: 6343b0fe842aSMatthew G. Knepley + dm - The `DM` 6344b0fe842aSMatthew G. Knepley . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 6345b0fe842aSMatthew G. Knepley - verticesAdj - (Optional) vertex adjacency array 6346b0fe842aSMatthew G. Knepley 6347b0fe842aSMatthew G. Knepley Level: intermediate 6348b0fe842aSMatthew G. Knepley 6349b0fe842aSMatthew G. Knepley Notes: 6350b0fe842aSMatthew G. Knepley This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 6351b0fe842aSMatthew G. Knepley `DMPlexBuildFromCellSectionParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 6352b0fe842aSMatthew G. Knepley 6353b0fe842aSMatthew G. Knepley See `DMPlexBuildFromCellSectionParallel()` for an example and details about the topology-related parameters. 6354b0fe842aSMatthew G. Knepley 6355b0fe842aSMatthew G. Knepley See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 6356b0fe842aSMatthew G. Knepley 6357b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 6358b0fe842aSMatthew G. Knepley @*/ 6359ce78bad3SBarry 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) 6360b0fe842aSMatthew G. Knepley { 6361b0fe842aSMatthew G. Knepley PetscSF sfVert; 6362b0fe842aSMatthew G. Knepley 6363b0fe842aSMatthew G. Knepley PetscFunctionBegin; 6364b0fe842aSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 6365b0fe842aSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 6366b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 6367b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 6368b0fe842aSMatthew G. Knepley PetscCall(DMSetDimension(*dm, dim)); 6369b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildFromCellSectionParallel(*dm, numCells, numVertices, NVertices, cellSection, cells, &sfVert, verticesAdj)); 6370b0fe842aSMatthew G. Knepley if (interpolate) { 6371b0fe842aSMatthew G. Knepley DM idm; 6372b0fe842aSMatthew G. Knepley 6373b0fe842aSMatthew G. Knepley PetscCall(DMPlexInterpolate(*dm, &idm)); 6374b0fe842aSMatthew G. Knepley PetscCall(DMDestroy(dm)); 6375b0fe842aSMatthew G. Knepley *dm = idm; 6376b0fe842aSMatthew G. Knepley } 6377b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 6378b0fe842aSMatthew G. Knepley if (vertexSF) *vertexSF = sfVert; 6379b0fe842aSMatthew G. Knepley else PetscCall(PetscSFDestroy(&sfVert)); 6380b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 6381b0fe842aSMatthew G. Knepley } 6382b0fe842aSMatthew G. Knepley 6383b0fe842aSMatthew G. Knepley /*@ 6384a1cb98faSBarry Smith DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) 6385a1cb98faSBarry Smith 638620f4b53cSBarry Smith Collective; No Fortran Support 63879298eaa6SMatthew G Knepley 63889298eaa6SMatthew G Knepley Input Parameters: 6389a1cb98faSBarry Smith + dm - The `DM` 6390b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 6391a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE` 63929298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 6393a3b724e8SBarry Smith - cells - An array of `numCells` x `numCorners` numbers, the global vertex numbers for each cell 63949298eaa6SMatthew G Knepley 6395b09969d6SVaclav Hapla Level: advanced 63969298eaa6SMatthew G Knepley 6397b09969d6SVaclav Hapla Notes: 6398b09969d6SVaclav Hapla Two triangles sharing a face 6399a1cb98faSBarry Smith .vb 64009298eaa6SMatthew G Knepley 6401a1cb98faSBarry Smith 2 6402a1cb98faSBarry Smith / | \ 6403a1cb98faSBarry Smith / | \ 6404a1cb98faSBarry Smith / | \ 6405a1cb98faSBarry Smith 0 0 | 1 3 6406a1cb98faSBarry Smith \ | / 6407a1cb98faSBarry Smith \ | / 6408a1cb98faSBarry Smith \ | / 6409a1cb98faSBarry Smith 1 6410a1cb98faSBarry Smith .ve 6411a1cb98faSBarry Smith would have input 6412a1cb98faSBarry Smith .vb 6413a1cb98faSBarry Smith numCells = 2, numVertices = 4 6414a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 6415a1cb98faSBarry Smith .ve 6416a1cb98faSBarry Smith which would result in the `DMPLEX` 6417a1cb98faSBarry Smith .vb 6418a1cb98faSBarry Smith 6419a1cb98faSBarry Smith 4 6420a1cb98faSBarry Smith / | \ 6421a1cb98faSBarry Smith / | \ 6422a1cb98faSBarry Smith / | \ 6423a1cb98faSBarry Smith 2 0 | 1 5 6424a1cb98faSBarry Smith \ | / 6425a1cb98faSBarry Smith \ | / 6426a1cb98faSBarry Smith \ | / 6427a1cb98faSBarry Smith 3 6428a1cb98faSBarry Smith .ve 6429a1cb98faSBarry Smith 6430a1cb98faSBarry Smith If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1. 643125b6865aSVaclav Hapla 64321cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 6433b09969d6SVaclav Hapla @*/ 6434d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 6435d71ae5a4SJacob Faibussowitsch { 6436961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 6437b09969d6SVaclav Hapla 6438b09969d6SVaclav Hapla PetscFunctionBegin; 64399566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 64409566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 644125b6865aSVaclav Hapla /* Get/check global number of vertices */ 644225b6865aSVaclav Hapla { 644325b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 644425b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 644525b6865aSVaclav Hapla 644625b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 64471690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 64489371c9d4SSatish Balay for (i = 0; i < len; i++) 64499371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 645025b6865aSVaclav Hapla ++NVerticesInCells; 645125b6865aSVaclav Hapla 645225b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 64539371c9d4SSatish Balay else 64549371c9d4SSatish 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); 645525b6865aSVaclav Hapla } 64569566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 645748a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 64589566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 64599566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 6460b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 6461ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 6462b09969d6SVaclav Hapla } 64639566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 64649566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 64659566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 64663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6467b09969d6SVaclav Hapla } 6468b09969d6SVaclav Hapla 6469cc4c1da9SBarry Smith /*@ 6470a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 6471a1cb98faSBarry Smith 6472cc4c1da9SBarry Smith Collective 6473b09969d6SVaclav Hapla 6474b09969d6SVaclav Hapla Input Parameters: 6475a1cb98faSBarry Smith + dm - The `DM` 6476b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6477b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6478b09969d6SVaclav Hapla 6479b09969d6SVaclav Hapla Level: advanced 6480b09969d6SVaclav Hapla 64811cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 6482b09969d6SVaclav Hapla @*/ 6483d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 6484d71ae5a4SJacob Faibussowitsch { 6485b09969d6SVaclav Hapla PetscSection coordSection; 6486b09969d6SVaclav Hapla Vec coordinates; 6487b09969d6SVaclav Hapla DM cdm; 6488b09969d6SVaclav Hapla PetscScalar *coords; 64891edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 6490b09969d6SVaclav Hapla 6491b09969d6SVaclav Hapla PetscFunctionBegin; 64929566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 64939566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 64941dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 64959566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 64969566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 64979566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 64989566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 64999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 65001edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 65019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 65029566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 6503b09969d6SVaclav Hapla } 65049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6505b09969d6SVaclav Hapla 65069566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 65079566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 65089566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 65099566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 65109566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 65111edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 6512ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 6513b09969d6SVaclav Hapla } 65149566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 65159566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 65169566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 65179566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 65183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6519b09969d6SVaclav Hapla } 6520b09969d6SVaclav Hapla 6521b09969d6SVaclav Hapla /*@ 6522a1cb98faSBarry Smith DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 65233df08285SMatthew G. Knepley 6524a1cb98faSBarry Smith Collective 6525b09969d6SVaclav Hapla 6526b09969d6SVaclav Hapla Input Parameters: 6527b09969d6SVaclav Hapla + comm - The communicator 6528b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 65293df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 6530a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0 65313df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 6532b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6533ce78bad3SBarry Smith . cells - An array of $ numCells \times numCorners$ numbers, the vertices for each cell, only on process 0 6534b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6535ce78bad3SBarry Smith - vertexCoords - An array of $ numVertices \times spaceDim$ numbers, the coordinates of each vertex, only on process 0 6536b09969d6SVaclav Hapla 6537b09969d6SVaclav Hapla Output Parameter: 6538a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0 653925b6865aSVaclav Hapla 6540b09969d6SVaclav Hapla Level: intermediate 6541b09969d6SVaclav Hapla 6542a1cb98faSBarry Smith Notes: 6543a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`, 6544a1cb98faSBarry Smith `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()` 6545a1cb98faSBarry Smith 6546a1cb98faSBarry Smith See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters. 6547a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters. 6548a1cb98faSBarry Smith See `DMPlexCreateFromCellListParallelPetsc()` for parallel input 6549a1cb98faSBarry Smith 65501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 65519298eaa6SMatthew G Knepley @*/ 6552d71ae5a4SJacob 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) 6553d71ae5a4SJacob Faibussowitsch { 65543df08285SMatthew G. Knepley PetscMPIInt rank; 65559298eaa6SMatthew G Knepley 65569298eaa6SMatthew G Knepley PetscFunctionBegin; 655728b400f6SJacob 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."); 65589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 65599566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 65609566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 65619566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 6562c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 65639566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 65649298eaa6SMatthew G Knepley if (interpolate) { 65655fd9971aSMatthew G. Knepley DM idm; 65669298eaa6SMatthew G Knepley 65679566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 65689566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 65699298eaa6SMatthew G Knepley *dm = idm; 65709298eaa6SMatthew G Knepley } 6571c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 65729566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 65733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 65749298eaa6SMatthew G Knepley } 65759298eaa6SMatthew G Knepley 6576939f6067SMatthew G. Knepley /*@ 657720f4b53cSBarry Smith DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a `DM` 6578939f6067SMatthew G. Knepley 6579939f6067SMatthew G. Knepley Input Parameters: 658020f4b53cSBarry Smith + dm - The empty `DM` object, usually from `DMCreate()` and `DMSetDimension()` 6581939f6067SMatthew G. Knepley . depth - The depth of the DAG 6582ce78bad3SBarry Smith . numPoints - Array of size $ depth + 1 $ containing the number of points at each `depth` 6583939f6067SMatthew G. Knepley . coneSize - The cone size of each point 6584939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 6585939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 6586ce78bad3SBarry Smith - vertexCoords - An array of $ numPoints[0] \times spacedim $ numbers representing the coordinates of each vertex, with `spacedim` the value set via `DMSetCoordinateDim()` 6587939f6067SMatthew G. Knepley 6588939f6067SMatthew G. Knepley Output Parameter: 658920f4b53cSBarry Smith . dm - The `DM` 659020f4b53cSBarry Smith 659120f4b53cSBarry Smith Level: advanced 6592939f6067SMatthew G. Knepley 6593a1cb98faSBarry Smith Note: 6594a1cb98faSBarry Smith Two triangles sharing a face would have input 6595a1cb98faSBarry Smith .vb 6596a1cb98faSBarry Smith depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 6597a1cb98faSBarry Smith cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 6598a1cb98faSBarry Smith vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 6599a1cb98faSBarry Smith .ve 6600939f6067SMatthew G. Knepley which would result in the DMPlex 6601a1cb98faSBarry Smith .vb 6602a1cb98faSBarry Smith 4 6603a1cb98faSBarry Smith / | \ 6604a1cb98faSBarry Smith / | \ 6605a1cb98faSBarry Smith / | \ 6606a1cb98faSBarry Smith 2 0 | 1 5 6607a1cb98faSBarry Smith \ | / 6608a1cb98faSBarry Smith \ | / 6609a1cb98faSBarry Smith \ | / 6610a1cb98faSBarry Smith 3 6611a1cb98faSBarry Smith .ve 6612a1cb98faSBarry Smith Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()` 6613939f6067SMatthew G. Knepley 6614ce78bad3SBarry Smith Developer Note: 6615ce78bad3SBarry Smith This does not create anything so should not have create in the name. 6616ce78bad3SBarry Smith 66171cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 6618939f6067SMatthew G. Knepley @*/ 6619d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 6620d71ae5a4SJacob Faibussowitsch { 66219298eaa6SMatthew G Knepley Vec coordinates; 66229298eaa6SMatthew G Knepley PetscSection coordSection; 66239298eaa6SMatthew G Knepley PetscScalar *coords; 6624811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 66259298eaa6SMatthew G Knepley 66269298eaa6SMatthew G Knepley PetscFunctionBegin; 66279566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 66289566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 662963a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 66309298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 66319566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 66329298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 66339566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 6634ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 663597e052ccSToby Isaac } 66361dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 66379566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 66389298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 66399566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 66409566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 66419298eaa6SMatthew G Knepley } 66429566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 66439566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 66449298eaa6SMatthew G Knepley /* Build coordinates */ 66459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 66469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 66479566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 66489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 66499298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 66509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 66519566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 66529298eaa6SMatthew G Knepley } 66539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 66549566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 66559566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 66569566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 66579566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 665858b7e2c1SStefano Zampini PetscCall(VecSetBlockSize(coordinates, PetscMax(dimEmbed, 1))); 66599566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 66609318fe57SMatthew G. Knepley if (vertexCoords) { 66619566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 66629298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 66639298eaa6SMatthew G Knepley PetscInt off; 66649298eaa6SMatthew G Knepley 66659566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 6666ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 66679298eaa6SMatthew G Knepley } 66689318fe57SMatthew G. Knepley } 66699566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 66709566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 66719566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 66723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 66739298eaa6SMatthew G Knepley } 66748415267dSToby Isaac 6675a4e35b19SJacob Faibussowitsch /* 6676a1cb98faSBarry Smith DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file. 6677a1cb98faSBarry Smith 6678a1cb98faSBarry Smith Collective 66798ca92349SMatthew G. Knepley 66808ca92349SMatthew G. Knepley + comm - The MPI communicator 66818ca92349SMatthew G. Knepley . filename - Name of the .dat file 66828ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 66838ca92349SMatthew G. Knepley 66848ca92349SMatthew G. Knepley Output Parameter: 6685a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 66868ca92349SMatthew G. Knepley 66878ca92349SMatthew G. Knepley Level: beginner 66888ca92349SMatthew G. Knepley 6689a1cb98faSBarry Smith Note: 6690a1cb98faSBarry Smith The format is the simplest possible: 6691a1cb98faSBarry Smith .vb 6692d0812dedSMatthew G. Knepley dim Ne Nv Nc Nl 6693d0812dedSMatthew G. Knepley v_1 v_2 ... v_Nc 6694d0812dedSMatthew G. Knepley ... 6695d0812dedSMatthew G. Knepley x y z marker_1 ... marker_Nl 6696a1cb98faSBarry Smith .ve 6697a1cb98faSBarry Smith 6698a1cb98faSBarry Smith Developer Note: 6699a1cb98faSBarry Smith Should use a `PetscViewer` not a filename 6700a1cb98faSBarry Smith 67016afe31f6SMartin Diehl .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 6702a4e35b19SJacob Faibussowitsch */ 6703ff6a9541SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 6704d71ae5a4SJacob Faibussowitsch { 67058ca92349SMatthew G. Knepley DMLabel marker; 67068ca92349SMatthew G. Knepley PetscViewer viewer; 67078ca92349SMatthew G. Knepley Vec coordinates; 67088ca92349SMatthew G. Knepley PetscSection coordSection; 67098ca92349SMatthew G. Knepley PetscScalar *coords; 67108ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 6711d0812dedSMatthew G. Knepley PetscInt cdim, coordSize, v, c, d; 67128ca92349SMatthew G. Knepley PetscMPIInt rank; 6713d0812dedSMatthew G. Knepley int snum, dim, Nv, Nc, Ncn, Nl; 67148ca92349SMatthew G. Knepley 67158ca92349SMatthew G. Knepley PetscFunctionBegin; 67169566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 67179566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 67189566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 67199566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 67209566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 6721dd400576SPatrick Sanan if (rank == 0) { 6722d0812dedSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING)); 6723d0812dedSMatthew G. Knepley snum = sscanf(line, "%d %d %d %d %d", &dim, &Nc, &Nv, &Ncn, &Nl); 6724d0812dedSMatthew G. Knepley PetscCheck(snum == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 672525ce1634SJed Brown } else { 6726f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 67278ca92349SMatthew G. Knepley } 6728d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm)); 6729835f2295SStefano Zampini cdim = dim; 67309566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 67319566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 67329566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 6733835f2295SStefano Zampini PetscCall(DMSetDimension(*dm, dim)); 67349566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 67358ca92349SMatthew G. Knepley /* Read topology */ 6736dd400576SPatrick Sanan if (rank == 0) { 6737f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 6738f8d5e320SMatthew G. Knepley PetscInt cone[8]; 67398ca92349SMatthew G. Knepley int vbuf[8], v; 67408ca92349SMatthew G. Knepley 67419371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 67429371c9d4SSatish Balay format[c * 3 + 0] = '%'; 67439371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 67449371c9d4SSatish Balay format[c * 3 + 2] = ' '; 67459371c9d4SSatish Balay } 6746f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 67479566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 67489566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 67498ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 67509566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 6751f8d5e320SMatthew G. Knepley switch (Ncn) { 6752d71ae5a4SJacob Faibussowitsch case 2: 6753d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1]); 6754d71ae5a4SJacob Faibussowitsch break; 6755d71ae5a4SJacob Faibussowitsch case 3: 6756d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); 6757d71ae5a4SJacob Faibussowitsch break; 6758d71ae5a4SJacob Faibussowitsch case 4: 6759d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); 6760d71ae5a4SJacob Faibussowitsch break; 6761d71ae5a4SJacob Faibussowitsch case 6: 6762d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); 6763d71ae5a4SJacob Faibussowitsch break; 6764d71ae5a4SJacob Faibussowitsch case 8: 6765d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 6766d71ae5a4SJacob Faibussowitsch break; 6767d71ae5a4SJacob Faibussowitsch default: 6768d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 6769f8d5e320SMatthew G. Knepley } 677008401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6771f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 67728ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 6773f8d5e320SMatthew G. Knepley if (Ncn == 8) { 67748ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 67758ca92349SMatthew G. Knepley cone[1] = cone[3]; 67768ca92349SMatthew G. Knepley cone[3] = tmp; 67778ca92349SMatthew G. Knepley } 67789566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 67798ca92349SMatthew G. Knepley } 67808ca92349SMatthew G. Knepley } 67819566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 67829566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 67838ca92349SMatthew G. Knepley /* Read coordinates */ 67849566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 67859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 67869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 67879566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 67888ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 67899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 67909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 67918ca92349SMatthew G. Knepley } 67929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 67939566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 67949566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 67959566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 67969566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 67979566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 67989566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 67999566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6800dd400576SPatrick Sanan if (rank == 0) { 6801f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 68028ca92349SMatthew G. Knepley double x[3]; 6803f8d5e320SMatthew G. Knepley int l, val[3]; 68048ca92349SMatthew G. Knepley 6805f8d5e320SMatthew G. Knepley if (Nl) { 68069371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 68079371c9d4SSatish Balay format[l * 3 + 0] = '%'; 68089371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 68099371c9d4SSatish Balay format[l * 3 + 2] = ' '; 68109371c9d4SSatish Balay } 6811f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 68129566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 68139566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 6814f8d5e320SMatthew G. Knepley } 68158ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 68169566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 6817f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 681808401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6819f8d5e320SMatthew G. Knepley switch (Nl) { 6820d71ae5a4SJacob Faibussowitsch case 0: 6821d71ae5a4SJacob Faibussowitsch snum = 0; 6822d71ae5a4SJacob Faibussowitsch break; 6823d71ae5a4SJacob Faibussowitsch case 1: 6824d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0]); 6825d71ae5a4SJacob Faibussowitsch break; 6826d71ae5a4SJacob Faibussowitsch case 2: 6827d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1]); 6828d71ae5a4SJacob Faibussowitsch break; 6829d71ae5a4SJacob Faibussowitsch case 3: 6830d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1], &val[2]); 6831d71ae5a4SJacob Faibussowitsch break; 6832d71ae5a4SJacob Faibussowitsch default: 6833d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 6834f8d5e320SMatthew G. Knepley } 683508401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 68368ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 68379566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 68388ca92349SMatthew G. Knepley } 68398ca92349SMatthew G. Knepley } 68409566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 68419566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 68429566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 68439566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 68448ca92349SMatthew G. Knepley if (interpolate) { 68458ca92349SMatthew G. Knepley DM idm; 68468ca92349SMatthew G. Knepley DMLabel bdlabel; 68478ca92349SMatthew G. Knepley 68489566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 68499566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 68508ca92349SMatthew G. Knepley *dm = idm; 68518ca92349SMatthew G. Knepley 6852f8d5e320SMatthew G. Knepley if (!Nl) { 68539566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 68549566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 68559566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 68569566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 68578ca92349SMatthew G. Knepley } 6858f8d5e320SMatthew G. Knepley } 68593ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68608ca92349SMatthew G. Knepley } 68618ca92349SMatthew G. Knepley 6862edfba7faSMatthew G. Knepley /* 6863edfba7faSMatthew G. Knepley DMPlexCreateSTLFromFile - Create a `DMPLEX` mesh from an STL file. 6864edfba7faSMatthew G. Knepley 6865edfba7faSMatthew G. Knepley Collective 6866edfba7faSMatthew G. Knepley 6867edfba7faSMatthew G. Knepley + comm - The MPI communicator 6868edfba7faSMatthew G. Knepley . filename - Name of the .dat file 6869edfba7faSMatthew G. Knepley - interpolate - Create faces and edges in the mesh 6870edfba7faSMatthew G. Knepley 6871edfba7faSMatthew G. Knepley Output Parameter: 6872edfba7faSMatthew G. Knepley . dm - The `DM` object representing the mesh 6873edfba7faSMatthew G. Knepley 6874edfba7faSMatthew G. Knepley Level: beginner 6875edfba7faSMatthew G. Knepley 6876edfba7faSMatthew G. Knepley Notes: 6877edfba7faSMatthew G. Knepley The binary format is: 6878edfba7faSMatthew G. Knepley .vb 6879edfba7faSMatthew G. Knepley UINT8[80] - Header - 80 bytes 6880edfba7faSMatthew G. Knepley UINT32 - Number of triangles - 04 bytes 6881edfba7faSMatthew G. Knepley foreach triangle - 50 bytes 6882edfba7faSMatthew G. Knepley REAL32[3] - Normal vector - 12 bytes 6883edfba7faSMatthew G. Knepley REAL32[3] - Vertex 1 - 12 bytes 6884edfba7faSMatthew G. Knepley REAL32[3] - Vertex 2 - 12 bytes 6885edfba7faSMatthew G. Knepley REAL32[3] - Vertex 3 - 12 bytes 6886edfba7faSMatthew G. Knepley UINT16 - Attribute byte count - 02 bytes 6887edfba7faSMatthew G. Knepley end 6888edfba7faSMatthew G. Knepley .ve 6889edfba7faSMatthew G. Knepley 6890edfba7faSMatthew G. Knepley The format is here <https://en.wikipedia.org/wiki/STL_(file_format)> 6891edfba7faSMatthew G. Knepley 6892edfba7faSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 6893edfba7faSMatthew G. Knepley */ 6894edfba7faSMatthew G. Knepley static PetscErrorCode DMPlexCreateSTLFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 6895edfba7faSMatthew G. Knepley { 6896edfba7faSMatthew G. Knepley PetscViewer viewer; 6897edfba7faSMatthew G. Knepley Vec coordinates; 6898edfba7faSMatthew G. Knepley PetscSection coordSection; 6899edfba7faSMatthew G. Knepley PetscScalar *coords; 6900edfba7faSMatthew G. Knepley PetscInt coordSize; 6901edfba7faSMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 6902edfba7faSMatthew G. Knepley PetscBT bt; 6903edfba7faSMatthew G. Knepley float *trialCoords = NULL; 6904edfba7faSMatthew G. Knepley PetscInt *cells = NULL; 6905edfba7faSMatthew G. Knepley PetscBool isascii; 6906edfba7faSMatthew G. Knepley PetscMPIInt rank; 6907edfba7faSMatthew G. Knepley PetscInt Nc, Nv, nv = 0; 6908edfba7faSMatthew G. Knepley 6909edfba7faSMatthew G. Knepley PetscFunctionBegin; 6910edfba7faSMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 6911edfba7faSMatthew G. Knepley PetscCall(PetscViewerCreate(comm, &viewer)); 6912edfba7faSMatthew G. Knepley PetscCall(PetscViewerSetType(viewer, PETSCVIEWERBINARY)); 6913edfba7faSMatthew G. Knepley PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 6914edfba7faSMatthew G. Knepley PetscCall(PetscViewerFileSetName(viewer, filename)); 6915edfba7faSMatthew G. Knepley if (rank == 0) { 6916edfba7faSMatthew G. Knepley int num; 6917edfba7faSMatthew G. Knepley 6918edfba7faSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_CHAR)); 6919edfba7faSMatthew G. Knepley line[5] = 0; 6920edfba7faSMatthew G. Knepley PetscCall(PetscStrncmp(line, "solid", 5, &isascii)); 6921edfba7faSMatthew G. Knepley PetscCheck(!isascii, comm, PETSC_ERR_SUP, "No support for ASCII yet"); 6922edfba7faSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, line, 75, NULL, PETSC_CHAR)); 6923edfba7faSMatthew G. Knepley line[75] = 0; 6924edfba7faSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, &num, 1, NULL, PETSC_INT32)); 6925edfba7faSMatthew G. Knepley PetscCall(PetscByteSwap(&num, PETSC_INT32, 1)); 6926edfba7faSMatthew G. Knepley Nc = num; 6927edfba7faSMatthew G. Knepley // Read facet coordinates 6928edfba7faSMatthew G. Knepley PetscCall(PetscMalloc1(Nc * 9, &trialCoords)); 6929edfba7faSMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 6930edfba7faSMatthew G. Knepley double normal[3]; 6931edfba7faSMatthew G. Knepley short int dummy; 6932edfba7faSMatthew G. Knepley 6933edfba7faSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, normal, 3, NULL, PETSC_FLOAT)); 6934edfba7faSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, &trialCoords[c * 9 + 0], 9, NULL, PETSC_FLOAT)); 6935edfba7faSMatthew G. Knepley PetscCall(PetscByteSwap(&trialCoords[c * 9 + 0], PETSC_FLOAT, 9)); 6936edfba7faSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, &dummy, 1, NULL, PETSC_SHORT)); 6937edfba7faSMatthew G. Knepley } 6938edfba7faSMatthew G. Knepley PetscCall(PetscMalloc1(Nc * 3, &cells)); 6939edfba7faSMatthew G. Knepley // Find unique vertices 6940edfba7faSMatthew G. Knepley PetscCall(PetscBTCreate(Nc * 3, &bt)); 6941edfba7faSMatthew G. Knepley PetscCall(PetscBTMemzero(Nc * 3, bt)); 6942edfba7faSMatthew G. Knepley PetscCall(PetscBTSet(bt, 0)); 6943edfba7faSMatthew G. Knepley PetscCall(PetscBTSet(bt, 1)); 6944edfba7faSMatthew G. Knepley PetscCall(PetscBTSet(bt, 2)); 6945edfba7faSMatthew G. Knepley Nv = 0; 6946edfba7faSMatthew G. Knepley cells[0] = Nc + Nv++; 6947edfba7faSMatthew G. Knepley cells[1] = Nc + Nv++; 6948edfba7faSMatthew G. Knepley cells[2] = Nc + Nv++; 6949edfba7faSMatthew G. Knepley for (PetscInt v = 3; v < Nc * 3; ++v) { 6950edfba7faSMatthew G. Knepley PetscBool match = PETSC_FALSE; 6951edfba7faSMatthew G. Knepley 6952edfba7faSMatthew G. Knepley for (PetscInt w = 0, x = 0; w < v; ++w) { 6953edfba7faSMatthew G. Knepley if (PetscBTLookup(bt, w)) { 6954edfba7faSMatthew 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]) { 6955edfba7faSMatthew G. Knepley match = PETSC_TRUE; 6956edfba7faSMatthew G. Knepley cells[v] = Nc + x; 6957edfba7faSMatthew G. Knepley break; 6958edfba7faSMatthew G. Knepley } 6959edfba7faSMatthew G. Knepley ++x; 6960edfba7faSMatthew G. Knepley } 6961edfba7faSMatthew G. Knepley } 6962edfba7faSMatthew G. Knepley if (!match) { 6963edfba7faSMatthew G. Knepley PetscCall(PetscBTSet(bt, v)); 6964edfba7faSMatthew G. Knepley cells[v] = Nc + Nv++; 6965edfba7faSMatthew G. Knepley } 6966edfba7faSMatthew G. Knepley } 6967edfba7faSMatthew G. Knepley } else { 6968edfba7faSMatthew G. Knepley Nc = Nv = 0; 6969edfba7faSMatthew G. Knepley } 6970edfba7faSMatthew 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]); 6971edfba7faSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 6972edfba7faSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 6973edfba7faSMatthew G. Knepley PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 6974edfba7faSMatthew G. Knepley PetscCall(DMSetDimension(*dm, 2)); 6975edfba7faSMatthew G. Knepley PetscCall(DMSetCoordinateDim(*dm, 3)); 6976edfba7faSMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, 3)); 6977edfba7faSMatthew G. Knepley PetscCall(DMSetUp(*dm)); 6978edfba7faSMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) PetscCall(DMPlexSetCone(*dm, c, &cells[c * 3])); 6979edfba7faSMatthew G. Knepley PetscCall(PetscFree(cells)); 6980edfba7faSMatthew G. Knepley PetscCall(DMPlexSymmetrize(*dm)); 6981edfba7faSMatthew G. Knepley PetscCall(DMPlexStratify(*dm)); 6982edfba7faSMatthew G. Knepley 6983edfba7faSMatthew G. Knepley PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 6984edfba7faSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(coordSection, 1)); 6985edfba7faSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 6986edfba7faSMatthew G. Knepley PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 6987edfba7faSMatthew G. Knepley for (PetscInt v = Nc; v < Nc + Nv; ++v) { 6988edfba7faSMatthew G. Knepley PetscCall(PetscSectionSetDof(coordSection, v, 3)); 6989edfba7faSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 6990edfba7faSMatthew G. Knepley } 6991edfba7faSMatthew G. Knepley PetscCall(PetscSectionSetUp(coordSection)); 6992edfba7faSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 6993edfba7faSMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 6994edfba7faSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 6995edfba7faSMatthew G. Knepley PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 6996edfba7faSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinates, 3)); 6997edfba7faSMatthew G. Knepley PetscCall(VecSetType(coordinates, VECSTANDARD)); 6998edfba7faSMatthew G. Knepley PetscCall(VecGetArray(coordinates, &coords)); 6999edfba7faSMatthew G. Knepley for (PetscInt tv = 0; tv < Nc * 3; ++tv) { 7000edfba7faSMatthew G. Knepley if (PetscBTLookup(bt, tv)) { 7001edfba7faSMatthew G. Knepley for (PetscInt d = 0; d < 3; ++d) coords[nv * 3 + d] = trialCoords[tv * 3 + d]; 7002edfba7faSMatthew G. Knepley ++nv; 7003edfba7faSMatthew G. Knepley } 7004edfba7faSMatthew G. Knepley } 7005edfba7faSMatthew G. Knepley PetscCheck(nv == Nv, comm, PETSC_ERR_PLIB, "Number of vertices copied %" PetscInt_FMT " != %" PetscInt_FMT " nubmer of mesh vertices", nv, Nv); 7006edfba7faSMatthew G. Knepley PetscCall(PetscFree(trialCoords)); 7007edfba7faSMatthew G. Knepley PetscCall(PetscBTDestroy(&bt)); 7008edfba7faSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &coords)); 7009edfba7faSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 7010edfba7faSMatthew G. Knepley PetscCall(VecDestroy(&coordinates)); 7011edfba7faSMatthew G. Knepley PetscCall(PetscViewerDestroy(&viewer)); 7012edfba7faSMatthew G. Knepley if (interpolate) { 7013edfba7faSMatthew G. Knepley DM idm; 7014edfba7faSMatthew G. Knepley 7015edfba7faSMatthew G. Knepley PetscCall(DMPlexInterpolate(*dm, &idm)); 7016edfba7faSMatthew G. Knepley PetscCall(DMDestroy(dm)); 7017edfba7faSMatthew G. Knepley *dm = idm; 7018edfba7faSMatthew G. Knepley } 7019edfba7faSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 7020edfba7faSMatthew G. Knepley } 7021edfba7faSMatthew G. Knepley 7022*f536a3c1SMatthew G. Knepley /* 7023*f536a3c1SMatthew G. Knepley DMPlexCreateShapefile - Create a `DMPLEX` mesh from the ESRI Shapefile format. 7024*f536a3c1SMatthew G. Knepley 7025*f536a3c1SMatthew G. Knepley Collective 7026*f536a3c1SMatthew G. Knepley 7027*f536a3c1SMatthew G. Knepley + comm - The MPI communicator 7028*f536a3c1SMatthew G. Knepley - viewer - `PetscViewer` for the .shp file 7029*f536a3c1SMatthew G. Knepley 7030*f536a3c1SMatthew G. Knepley Output Parameter: 7031*f536a3c1SMatthew G. Knepley . dm - The `DM` object representing the mesh 7032*f536a3c1SMatthew G. Knepley 7033*f536a3c1SMatthew G. Knepley Level: beginner 7034*f536a3c1SMatthew G. Knepley 7035*f536a3c1SMatthew G. Knepley Note: 7036*f536a3c1SMatthew 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). 7037*f536a3c1SMatthew G. Knepley 7038*f536a3c1SMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 7039*f536a3c1SMatthew G. Knepley */ 7040*f536a3c1SMatthew G. Knepley static PetscErrorCode DMPlexCreateShapefile(MPI_Comm comm, PetscViewer viewer, DM *dm) 7041*f536a3c1SMatthew G. Knepley { 7042*f536a3c1SMatthew G. Knepley Vec coordinates; 7043*f536a3c1SMatthew G. Knepley PetscSection coordSection; 7044*f536a3c1SMatthew G. Knepley PetscScalar *coords; 7045*f536a3c1SMatthew G. Knepley PetscInt cdim = 2, coordSize; 7046*f536a3c1SMatthew G. Knepley int dim = 1, Nv, Nc, vOff; 7047*f536a3c1SMatthew G. Knepley double *points = NULL; 7048*f536a3c1SMatthew G. Knepley double mbr[4], zb[2], mb[2]; 7049*f536a3c1SMatthew G. Knepley PetscMPIInt rank; 7050*f536a3c1SMatthew G. Knepley 7051*f536a3c1SMatthew G. Knepley PetscFunctionBegin; 7052*f536a3c1SMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 7053*f536a3c1SMatthew G. Knepley if (rank == 0) { 7054*f536a3c1SMatthew G. Knepley PetscInt cnt; 7055*f536a3c1SMatthew G. Knepley int magic, dummy[5], len, version, shtype, totlen = 0; 7056*f536a3c1SMatthew G. Knepley 7057*f536a3c1SMatthew G. Knepley // Read header 7058*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &magic, 1, &cnt, PETSC_INT32)); 7059*f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 0-3"); 7060*f536a3c1SMatthew G. Knepley PetscCheck(magic == 0x0000270a, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: invalid magic number %X", magic); 7061*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, dummy, 5, &cnt, PETSC_INT32)); 7062*f536a3c1SMatthew G. Knepley PetscCheck(cnt == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 4-23"); 7063*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &len, 1, &cnt, PETSC_INT32)); 7064*f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 24-27"); 7065*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &version, 1, &cnt, PETSC_INT32)); 7066*f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(&version, PETSC_INT32, 1)); 7067*f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 28-31"); 7068*f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: version %d file length %d\n", version, len)); 7069*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &shtype, 1, &cnt, PETSC_INT32)); 7070*f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(&shtype, PETSC_INT32, 1)); 7071*f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 32-35"); 7072*f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: shape type %d\n", shtype)); 7073*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, mbr, 4, &cnt, PETSC_DOUBLE)); 7074*f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(mbr, PETSC_DOUBLE, 4)); 7075*f536a3c1SMatthew G. Knepley PetscCheck(cnt == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 36-67"); 7076*f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: minimum bounding rectangle (%g, %g) -- (%g, %g)\n", mbr[0], mbr[1], mbr[2], mbr[3])); 7077*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, zb, 2, &cnt, PETSC_DOUBLE)); 7078*f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(zb, PETSC_DOUBLE, 2)); 7079*f536a3c1SMatthew G. Knepley PetscCheck(cnt == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 68-83"); 7080*f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: Z bounds (%g) -- (%g)\n", zb[0], zb[1])); 7081*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, mb, 2, &cnt, PETSC_DOUBLE)); 7082*f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(mb, PETSC_DOUBLE, 2)); 7083*f536a3c1SMatthew G. Knepley PetscCheck(cnt == 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read bytes 84-99"); 7084*f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: M bounds (%g) -- (%g)\n", mb[0], mb[1])); 7085*f536a3c1SMatthew G. Knepley totlen += 100; 7086*f536a3c1SMatthew G. Knepley { 7087*f536a3c1SMatthew G. Knepley int rnum, rlen, rshtype, rnpart, rnp; 7088*f536a3c1SMatthew G. Knepley double rmbr[4]; 7089*f536a3c1SMatthew G. Knepley int *partOffsets; 7090*f536a3c1SMatthew G. Knepley 7091*f536a3c1SMatthew G. Knepley // Read record header 7092*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &rnum, 1, &cnt, PETSC_INT32)); 7093*f536a3c1SMatthew 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"); 7094*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &rlen, 1, &cnt, PETSC_INT32)); 7095*f536a3c1SMatthew 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"); 7096*f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: record %d length %d\n", rnum, rlen)); 7097*f536a3c1SMatthew G. Knepley totlen += 8; 7098*f536a3c1SMatthew G. Knepley // Read record 7099*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &rshtype, 1, &cnt, PETSC_INT32)); 7100*f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(&rshtype, PETSC_INT32, 1)); 7101*f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record bytes 0-3"); 7102*f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: record shape type %d\n", rshtype)); 7103*f536a3c1SMatthew G. Knepley totlen += 4; 7104*f536a3c1SMatthew G. Knepley switch (rshtype) { 7105*f536a3c1SMatthew G. Knepley case 5: // Polygon 7106*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, rmbr, 4, &cnt, PETSC_DOUBLE)); 7107*f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(rmbr, PETSC_DOUBLE, 4)); 7108*f536a3c1SMatthew G. Knepley PetscCheck(cnt == 4, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record bytes 4-35"); 7109*f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: record minimum bounding rectangle (%g, %g) -- (%g, %g)\n", rmbr[0], rmbr[1], rmbr[2], rmbr[3])); 7110*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &rnpart, 1, &cnt, PETSC_INT32)); 7111*f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(&rnpart, PETSC_INT32, 1)); 7112*f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record bytes 36-39"); 7113*f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: record shape number of parts %d\n", rnpart)); 7114*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, &rnp, 1, &cnt, PETSC_INT32)); 7115*f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(&rnp, PETSC_INT32, 1)); 7116*f536a3c1SMatthew G. Knepley PetscCheck(cnt == 1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record bytes 36-39"); 7117*f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: record shape number of points %d\n", rnp)); 7118*f536a3c1SMatthew G. Knepley totlen += 40; 7119*f536a3c1SMatthew G. Knepley PetscCall(PetscMalloc1(rnpart, &partOffsets)); 7120*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, partOffsets, rnpart, &cnt, PETSC_INT32)); 7121*f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(partOffsets, PETSC_INT32, rnpart)); 7122*f536a3c1SMatthew G. Knepley PetscCheck(cnt == rnpart, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record part offsets"); 7123*f536a3c1SMatthew G. Knepley totlen += 4 * rnpart; 7124*f536a3c1SMatthew G. Knepley PetscCall(PetscMalloc1(rnp * 2, &points)); 7125*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerBinaryRead(viewer, points, rnp * 2, &cnt, PETSC_DOUBLE)); 7126*f536a3c1SMatthew G. Knepley PetscCall(PetscByteSwap(points, PETSC_DOUBLE, rnp * 2)); 7127*f536a3c1SMatthew G. Knepley PetscCheck(cnt == rnp * 2, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse Shapefile file: could not read record points"); 7128*f536a3c1SMatthew G. Knepley totlen += 8 * rnp * 2; 7129*f536a3c1SMatthew 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); 7130*f536a3c1SMatthew G. Knepley // Only get the last polygon now 7131*f536a3c1SMatthew G. Knepley vOff = partOffsets[rnpart - 1]; 7132*f536a3c1SMatthew G. Knepley Nv = rnp - vOff; 7133*f536a3c1SMatthew G. Knepley Nc = Nv - 1; 7134*f536a3c1SMatthew G. Knepley PetscCall(PetscInfo(viewer, "Shapefile: record first polygon size %d totlen %d\n", Nv, totlen)); 7135*f536a3c1SMatthew G. Knepley PetscCall(PetscFree(partOffsets)); 7136*f536a3c1SMatthew G. Knepley break; 7137*f536a3c1SMatthew G. Knepley default: 7138*f536a3c1SMatthew G. Knepley PetscCheck(0, PETSC_COMM_SELF, PETSC_ERR_SUP, "Only support polygons right now"); 7139*f536a3c1SMatthew G. Knepley } 7140*f536a3c1SMatthew G. Knepley } 7141*f536a3c1SMatthew G. Knepley } else { 7142*f536a3c1SMatthew G. Knepley Nc = Nv = vOff = 0; 7143*f536a3c1SMatthew G. Knepley } 7144*f536a3c1SMatthew G. Knepley PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm)); 7145*f536a3c1SMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 7146*f536a3c1SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 7147*f536a3c1SMatthew G. Knepley PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 7148*f536a3c1SMatthew G. Knepley PetscCall(DMSetDimension(*dm, dim)); 7149*f536a3c1SMatthew G. Knepley PetscCall(DMSetCoordinateDim(*dm, cdim)); 7150*f536a3c1SMatthew G. Knepley // Topology of a circle 7151*f536a3c1SMatthew G. Knepley if (rank == 0) { 7152*f536a3c1SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, 2)); 7153*f536a3c1SMatthew G. Knepley PetscCall(DMSetUp(*dm)); 7154*f536a3c1SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 7155*f536a3c1SMatthew G. Knepley PetscInt cone[2] = {Nc + c, Nc + c + 1}; 7156*f536a3c1SMatthew G. Knepley 7157*f536a3c1SMatthew G. Knepley PetscCall(DMPlexSetCone(*dm, c, cone)); 7158*f536a3c1SMatthew G. Knepley } 7159*f536a3c1SMatthew G. Knepley } 7160*f536a3c1SMatthew G. Knepley PetscCall(DMPlexSymmetrize(*dm)); 7161*f536a3c1SMatthew G. Knepley PetscCall(DMPlexStratify(*dm)); 7162*f536a3c1SMatthew G. Knepley // Set coordinates 7163*f536a3c1SMatthew G. Knepley PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 7164*f536a3c1SMatthew G. Knepley PetscCall(PetscSectionSetNumFields(coordSection, 1)); 7165*f536a3c1SMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 7166*f536a3c1SMatthew G. Knepley PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 7167*f536a3c1SMatthew G. Knepley for (PetscInt v = Nc; v < Nc + Nv; ++v) { 7168*f536a3c1SMatthew G. Knepley PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 7169*f536a3c1SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 7170*f536a3c1SMatthew G. Knepley } 7171*f536a3c1SMatthew G. Knepley PetscCall(PetscSectionSetUp(coordSection)); 7172*f536a3c1SMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 7173*f536a3c1SMatthew G. Knepley PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 7174*f536a3c1SMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 7175*f536a3c1SMatthew G. Knepley PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 7176*f536a3c1SMatthew G. Knepley PetscCall(VecSetBlockSize(coordinates, cdim)); 7177*f536a3c1SMatthew G. Knepley PetscCall(VecSetType(coordinates, VECSTANDARD)); 7178*f536a3c1SMatthew G. Knepley PetscCall(VecGetArray(coordinates, &coords)); 7179*f536a3c1SMatthew G. Knepley for (PetscInt v = 0; v < Nv; ++v) { 7180*f536a3c1SMatthew G. Knepley coords[v * cdim + 0] = points[(v + vOff) * cdim + 0] - mbr[0]; 7181*f536a3c1SMatthew G. Knepley coords[v * cdim + 1] = points[(v + vOff) * cdim + 1] - mbr[1]; 7182*f536a3c1SMatthew G. Knepley } 7183*f536a3c1SMatthew G. Knepley PetscCall(PetscFree(points)); 7184*f536a3c1SMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &coords)); 7185*f536a3c1SMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 7186*f536a3c1SMatthew G. Knepley PetscCall(VecDestroy(&coordinates)); 7187*f536a3c1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 7188*f536a3c1SMatthew G. Knepley } 7189*f536a3c1SMatthew G. Knepley 7190*f536a3c1SMatthew G. Knepley /* 7191*f536a3c1SMatthew G. Knepley DMPlexCreateShapefileFromFile - Create a `DMPLEX` mesh from the ESRI Shapefile format. 7192*f536a3c1SMatthew G. Knepley 7193*f536a3c1SMatthew G. Knepley Collective 7194*f536a3c1SMatthew G. Knepley 7195*f536a3c1SMatthew G. Knepley + comm - The MPI communicator 7196*f536a3c1SMatthew G. Knepley . filename - Name of the .shp file 7197*f536a3c1SMatthew G. Knepley 7198*f536a3c1SMatthew G. Knepley Output Parameter: 7199*f536a3c1SMatthew G. Knepley . dm - The `DM` object representing the mesh 7200*f536a3c1SMatthew G. Knepley 7201*f536a3c1SMatthew G. Knepley Level: beginner 7202*f536a3c1SMatthew G. Knepley 7203*f536a3c1SMatthew G. Knepley Note: 7204*f536a3c1SMatthew 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). 7205*f536a3c1SMatthew G. Knepley 7206*f536a3c1SMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 7207*f536a3c1SMatthew G. Knepley */ 7208*f536a3c1SMatthew G. Knepley static PetscErrorCode DMPlexCreateShapefileFromFile(MPI_Comm comm, const char filename[], DM *dm) 7209*f536a3c1SMatthew G. Knepley { 7210*f536a3c1SMatthew G. Knepley PetscViewer viewer; 7211*f536a3c1SMatthew G. Knepley 7212*f536a3c1SMatthew G. Knepley PetscFunctionBegin; 7213*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerCreate(comm, &viewer)); 7214*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerSetType(viewer, PETSCVIEWERBINARY)); 7215*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 7216*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerFileSetName(viewer, filename)); 7217*f536a3c1SMatthew G. Knepley PetscCall(DMPlexCreateShapefile(comm, viewer, dm)); 7218*f536a3c1SMatthew G. Knepley PetscCall(PetscViewerDestroy(&viewer)); 7219*f536a3c1SMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 7220*f536a3c1SMatthew G. Knepley } 7221*f536a3c1SMatthew G. Knepley 7222cc4c1da9SBarry Smith /*@ 7223a1cb98faSBarry Smith DMPlexCreateFromFile - This takes a filename and produces a `DM` 7224a1cb98faSBarry Smith 7225a1cb98faSBarry Smith Collective 7226ca522641SMatthew G. Knepley 7227ca522641SMatthew G. Knepley Input Parameters: 7228ca522641SMatthew G. Knepley + comm - The communicator 7229ca522641SMatthew G. Knepley . filename - A file name 7230a1cb98faSBarry Smith . plexname - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats 7231ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 7232ca522641SMatthew G. Knepley 7233ca522641SMatthew G. Knepley Output Parameter: 7234a1cb98faSBarry Smith . dm - The `DM` 7235ca522641SMatthew G. Knepley 7236a1cb98faSBarry Smith Options Database Key: 7237a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5 723802ef0d99SVaclav Hapla 7239b44f4de4SBarry Smith Use `-dm_plex_create_ prefix` to pass options to the internal `PetscViewer`, e.g. `-dm_plex_create_viewer_hdf5_collective` 7240bca97951SVaclav Hapla 7241ca522641SMatthew G. Knepley Level: beginner 7242ca522641SMatthew G. Knepley 7243a1cb98faSBarry Smith Notes: 7244a1cb98faSBarry Smith Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX` 7245a1cb98faSBarry Smith meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()` 7246a1cb98faSBarry Smith before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object. 7247a1cb98faSBarry Smith The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally 7248a1cb98faSBarry Smith calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats. 7249a1cb98faSBarry Smith 72501cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 7251ca522641SMatthew G. Knepley @*/ 7252d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 7253d71ae5a4SJacob Faibussowitsch { 7254ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 7255ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 7256ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 7257ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 7258ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 7259ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 7260ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 7261ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 7262ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 72636f2c871aSStefano Zampini const char extXDMFHDF5[] = ".xdmf.h5"; 7264ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 72655552b385SBrandon const char extEGADSlite[] = ".egadslite"; 7266ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 7267ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 72685552b385SBrandon const char extIGES2[] = ".iges"; 7269ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 72705552b385SBrandon const char extSTEP2[] = ".step"; 72715552b385SBrandon const char extBREP[] = ".brep"; 7272ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 7273edfba7faSMatthew G. Knepley const char extSTL[] = ".stl"; 7274*f536a3c1SMatthew G. Knepley const char extSHP[] = ".shp"; 7275ca522641SMatthew G. Knepley size_t len; 7276*f536a3c1SMatthew G. Knepley PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isPLY, isEGADSlite, isEGADS, isIGES, isIGES2, isSTEP, isSTEP2, isBREP, isCV, isSTL, isSHP, isXDMFHDF5; 7277ca522641SMatthew G. Knepley PetscMPIInt rank; 7278ca522641SMatthew G. Knepley 7279ca522641SMatthew G. Knepley PetscFunctionBegin; 72804f572ea9SToby Isaac PetscAssertPointer(filename, 2); 72814f572ea9SToby Isaac if (plexname) PetscAssertPointer(plexname, 3); 72824f572ea9SToby Isaac PetscAssertPointer(dm, 5); 72839566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 72849566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 72859566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 72869566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 728728b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 7288ef3a5affSJacob Faibussowitsch 72899371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 72909371c9d4SSatish Balay do { \ 7291274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 7292274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 7293274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 7294274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 7295ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 7296ef3a5affSJacob Faibussowitsch } else { \ 7297274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 7298ef3a5affSJacob Faibussowitsch } \ 7299ef3a5affSJacob Faibussowitsch } while (0) 7300ef3a5affSJacob Faibussowitsch 7301ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 7302ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 7303ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 7304ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 7305ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 7306ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 7307ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 7308ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 7309ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 7310ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 73115552b385SBrandon CheckExtension(extEGADSlite, isEGADSlite); 7312ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 7313ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 73145552b385SBrandon CheckExtension(extIGES2, isIGES2); 7315ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 73165552b385SBrandon CheckExtension(extSTEP2, isSTEP2); 73175552b385SBrandon CheckExtension(extBREP, isBREP); 7318ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 7319edfba7faSMatthew G. Knepley CheckExtension(extSTL, isSTL); 7320*f536a3c1SMatthew G. Knepley CheckExtension(extSHP, isSHP); 73216f2c871aSStefano Zampini CheckExtension(extXDMFHDF5, isXDMFHDF5); 7322ef3a5affSJacob Faibussowitsch 7323ef3a5affSJacob Faibussowitsch #undef CheckExtension 7324ef3a5affSJacob Faibussowitsch 7325de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 73269566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 7327ca522641SMatthew G. Knepley } else if (isCGNS) { 73289566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 732990c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 73309566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 73312f0bd6dcSMichael Lange } else if (isFluent) { 73329566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 7333cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 7334cc2f8f65SMatthew G. Knepley PetscViewer viewer; 7335cc2f8f65SMatthew G. Knepley 733643b242b4SVaclav 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 */ 73376f2c871aSStefano Zampini PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &isXDMFHDF5, NULL)); 73389566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 73399566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 73409566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 73419566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 73429566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 73439566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 7344cd7e8a5eSksagiyam 73459566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 7346f4f49eeaSPierre Jolivet PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 73479566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 73486f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 73499566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 73506f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPopFormat(viewer)); 73519566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 73525fd9971aSMatthew G. Knepley 73535fd9971aSMatthew G. Knepley if (interpolate) { 73545fd9971aSMatthew G. Knepley DM idm; 73555fd9971aSMatthew G. Knepley 73569566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 73579566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 73585fd9971aSMatthew G. Knepley *dm = idm; 73595fd9971aSMatthew G. Knepley } 7360f2801cd6SMatthew G. Knepley } else if (isPLY) { 73619566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 73625552b385SBrandon } else if (isEGADSlite || isEGADS || isIGES || isIGES2 || isSTEP || isSTEP2 || isBREP) { 73635552b385SBrandon PetscCall(DMPlexCreateGeomFromFile(comm, filename, dm, isEGADSlite)); 73645552b385SBrandon 73657bee2925SMatthew Knepley if (!interpolate) { 73667bee2925SMatthew Knepley DM udm; 73677bee2925SMatthew Knepley 73689566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 73699566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 73707bee2925SMatthew Knepley *dm = udm; 73717bee2925SMatthew Knepley } 73728ca92349SMatthew G. Knepley } else if (isCV) { 73739566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 7374edfba7faSMatthew G. Knepley } else if (isSTL) { 7375edfba7faSMatthew G. Knepley PetscCall(DMPlexCreateSTLFromFile(comm, filename, interpolate, dm)); 7376*f536a3c1SMatthew G. Knepley } else if (isSHP) { 7377*f536a3c1SMatthew G. Knepley PetscCall(DMPlexCreateShapefileFromFile(comm, filename, dm)); 737898921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 73799566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 7380f4f49eeaSPierre Jolivet if (len) PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 73819566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 73823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7383ca522641SMatthew G. Knepley } 738412b8a6daSStefano Zampini 7385cc4c1da9SBarry Smith /*@ 73869f6c5813SMatthew 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. 73879f6c5813SMatthew G. Knepley 73880528010dSStefano Zampini Input Parameters: 73890528010dSStefano Zampini + tr - The `DMPlexTransform` 73900528010dSStefano Zampini - prefix - An options prefix, or NULL 73919f6c5813SMatthew G. Knepley 73929f6c5813SMatthew G. Knepley Output Parameter: 73939f6c5813SMatthew G. Knepley . dm - The `DM` 73949f6c5813SMatthew G. Knepley 73959f6c5813SMatthew G. Knepley Level: beginner 73969f6c5813SMatthew G. Knepley 739720f4b53cSBarry Smith Notes: 739820f4b53cSBarry 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. 739920f4b53cSBarry Smith 74009f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 74019f6c5813SMatthew G. Knepley @*/ 74020528010dSStefano Zampini PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, const char prefix[], DM *dm) 74039f6c5813SMatthew G. Knepley { 74040528010dSStefano Zampini DM bdm, bcdm, cdm; 74050528010dSStefano Zampini Vec coordinates, coordinatesNew; 74060528010dSStefano Zampini PetscSection cs; 7407817b2c36SMatthew G. Knepley PetscInt cdim, Nl; 74089f6c5813SMatthew G. Knepley 74099f6c5813SMatthew G. Knepley PetscFunctionBegin; 74109f6c5813SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm)); 74119f6c5813SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 74120528010dSStefano Zampini ((DM_Plex *)(*dm)->data)->interpolated = DMPLEX_INTERPOLATED_FULL; 74130528010dSStefano Zampini // Handle coordinates 74140528010dSStefano Zampini PetscCall(DMPlexTransformGetDM(tr, &bdm)); 7415817b2c36SMatthew G. Knepley PetscCall(DMPlexTransformSetDimensions(tr, bdm, *dm)); 7416817b2c36SMatthew G. Knepley PetscCall(DMGetCoordinateDim(*dm, &cdim)); 74170528010dSStefano Zampini PetscCall(DMGetCoordinateDM(bdm, &bcdm)); 74180528010dSStefano Zampini PetscCall(DMGetCoordinateDM(*dm, &cdm)); 74190528010dSStefano Zampini PetscCall(DMCopyDisc(bcdm, cdm)); 74200528010dSStefano Zampini PetscCall(DMGetLocalSection(cdm, &cs)); 74210528010dSStefano Zampini PetscCall(PetscSectionSetNumFields(cs, 1)); 74220528010dSStefano Zampini PetscCall(PetscSectionSetFieldComponents(cs, 0, cdim)); 74230528010dSStefano Zampini PetscCall(DMGetCoordinatesLocal(bdm, &coordinates)); 74240528010dSStefano Zampini PetscCall(VecDuplicate(coordinates, &coordinatesNew)); 74250528010dSStefano Zampini PetscCall(VecCopy(coordinates, coordinatesNew)); 74260528010dSStefano Zampini PetscCall(DMSetCoordinatesLocal(*dm, coordinatesNew)); 74270528010dSStefano Zampini PetscCall(VecDestroy(&coordinatesNew)); 74289f6c5813SMatthew G. Knepley 74299f6c5813SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)tr)); 74309f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr)); 74319f6c5813SMatthew G. Knepley ((DM_Plex *)(*dm)->data)->tr = tr; 74320528010dSStefano Zampini PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE)); 74330528010dSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix)); 74340528010dSStefano Zampini PetscCall(DMSetFromOptions(*dm)); 74359f6c5813SMatthew G. Knepley 74369f6c5813SMatthew G. Knepley PetscCall(DMGetNumLabels(bdm, &Nl)); 74379f6c5813SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 74389f6c5813SMatthew G. Knepley DMLabel label, labelNew; 74399f6c5813SMatthew G. Knepley const char *lname; 74409f6c5813SMatthew G. Knepley PetscBool isDepth, isCellType; 74419f6c5813SMatthew G. Knepley 74429f6c5813SMatthew G. Knepley PetscCall(DMGetLabelName(bdm, l, &lname)); 74439f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 74449f6c5813SMatthew G. Knepley if (isDepth) continue; 74459f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "celltype", &isCellType)); 74469f6c5813SMatthew G. Knepley if (isCellType) continue; 74479f6c5813SMatthew G. Knepley PetscCall(DMCreateLabel(*dm, lname)); 74489f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(bdm, lname, &label)); 74499f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(*dm, lname, &labelNew)); 74509f6c5813SMatthew G. Knepley PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL)); 74519f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetLabel(labelNew, label)); 74529f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetTransform(labelNew, tr)); 74539f6c5813SMatthew G. Knepley PetscCall(DMLabelSetUp(labelNew)); 74549f6c5813SMatthew G. Knepley } 74553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 74569f6c5813SMatthew G. Knepley } 7457