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` 294*4c712d99Sksagiyam . localized - Flag to create a localized (DG) coordinate space 295e44f6aebSMatthew G. Knepley . project - Flag to project current coordinates into the space 2969318fe57SMatthew G. Knepley - coordFunc - An optional function to map new points from refinement to the surface 2979318fe57SMatthew G. Knepley 2989318fe57SMatthew G. Knepley Level: advanced 2999318fe57SMatthew G. Knepley 3002192575eSBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscPointFn`, `PetscFECreateLagrange()`, `DMGetCoordinateDM()` 3019318fe57SMatthew G. Knepley @*/ 302*4c712d99Sksagiyam PetscErrorCode DMPlexCreateCoordinateSpace(DM dm, PetscInt degree, PetscBool localized, PetscBool project, PetscPointFn *coordFunc) 303d71ae5a4SJacob Faibussowitsch { 304e44f6aebSMatthew G. Knepley PetscFE fe = NULL; 3059318fe57SMatthew G. Knepley DM cdm; 306ac9d17c7SMatthew G. Knepley PetscInt dim, cdim, dE, qorder, height; 3079318fe57SMatthew G. Knepley 308e44f6aebSMatthew G. Knepley PetscFunctionBegin; 3099566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 310ac9d17c7SMatthew G. Knepley cdim = dim; 3119566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dE)); 3129318fe57SMatthew G. Knepley qorder = degree; 313e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 314509b31aaSMatthew G. Knepley if (!coordFunc) PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc)); 315d0609cedSBarry Smith PetscObjectOptionsBegin((PetscObject)cdm); 316dc431b0cSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-default_quadrature_order", "Quadrature order is one less than quadrature points per edge", "DMPlexCreateCoordinateSpace", qorder, &qorder, NULL, 0)); 317ac9d17c7SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_coordinate_dim", "Set the coordinate dimension", "DMPlexCreateCoordinateSpace", cdim, &cdim, NULL, dim)); 318d0609cedSBarry Smith PetscOptionsEnd(); 3191df12153SMatthew G. Knepley PetscCall(DMPlexGetVTKCellHeight(dm, &height)); 320ac9d17c7SMatthew G. Knepley if (cdim > dim) { 321ac9d17c7SMatthew G. Knepley DM cdm; 322ac9d17c7SMatthew G. Knepley PetscSection cs, csNew; 323ac9d17c7SMatthew G. Knepley Vec coordinates, coordinatesNew; 324ac9d17c7SMatthew G. Knepley VecType vectype; 325ac9d17c7SMatthew G. Knepley IS idx; 326ac9d17c7SMatthew G. Knepley PetscInt *indices; 327ac9d17c7SMatthew G. Knepley PetscInt bs, n; 328ac9d17c7SMatthew G. Knepley 329ac9d17c7SMatthew G. Knepley // Recreate coordinate section 330ac9d17c7SMatthew G. Knepley { 331ac9d17c7SMatthew G. Knepley const char *fieldName = NULL, *compName = NULL; 332ac9d17c7SMatthew G. Knepley PetscInt Nc, pStart, pEnd; 333ac9d17c7SMatthew G. Knepley 334ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 335ac9d17c7SMatthew G. Knepley PetscCall(DMGetLocalSection(cdm, &cs)); 336ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)cs), &csNew)); 337ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetNumFields(csNew, 1)); 338ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetFieldName(cs, 0, &fieldName)); 339ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldName(csNew, 0, fieldName)); 340ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetFieldComponents(cs, 0, &Nc)); 341ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(csNew, 0, cdim)); 342ac9d17c7SMatthew G. Knepley for (PetscInt c = 0; c < Nc; ++c) { 343ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetComponentName(cs, 0, c, &compName)); 344ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetComponentName(csNew, 0, c, compName)); 345ac9d17c7SMatthew G. Knepley } 346ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionGetChart(cs, &pStart, &pEnd)); 347ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetChart(csNew, pStart, pEnd)); 348ac9d17c7SMatthew G. Knepley for (PetscInt p = pStart; p < pEnd; ++p) { 349530e699aSMatthew G. Knepley PetscInt dof; 350530e699aSMatthew G. Knepley 351530e699aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cs, p, &dof)); 352530e699aSMatthew G. Knepley if (dof) { 353ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetDof(csNew, p, cdim)); 354ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(csNew, p, 0, cdim)); 355ac9d17c7SMatthew G. Knepley } 356530e699aSMatthew G. Knepley } 357ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionSetUp(csNew)); 358ac9d17c7SMatthew G. Knepley } 359ac9d17c7SMatthew G. Knepley PetscCall(DMSetLocalSection(cdm, csNew)); 360ac9d17c7SMatthew G. Knepley PetscCall(PetscSectionDestroy(&csNew)); 361530e699aSMatthew G. Knepley // Reset coordinate dimension for coordinate DM 362530e699aSMatthew G. Knepley PetscCall(DMSetCoordinateDim(cdm, cdim)); 363530e699aSMatthew G. Knepley PetscCall(DMSetCoordinateField(cdm, NULL)); 364ac9d17c7SMatthew G. Knepley // Inject coordinates into higher dimension 365ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 366ac9d17c7SMatthew G. Knepley PetscCall(VecGetBlockSize(coordinates, &bs)); 367ac9d17c7SMatthew G. Knepley PetscCheck(bs == dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension"); 368ac9d17c7SMatthew G. Knepley PetscCall(VecCreate(PetscObjectComm((PetscObject)coordinates), &coordinatesNew)); 369ac9d17c7SMatthew G. Knepley PetscCall(VecGetType(coordinates, &vectype)); 370ac9d17c7SMatthew G. Knepley PetscCall(VecSetType(coordinatesNew, vectype)); 371ac9d17c7SMatthew G. Knepley PetscCall(VecGetLocalSize(coordinates, &n)); 372ac9d17c7SMatthew G. Knepley PetscCheck(!(n % bs), PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "We can only inject simple coordinates into a higher dimension"); 373ac9d17c7SMatthew G. Knepley n /= bs; 374ac9d17c7SMatthew G. Knepley PetscCall(VecSetSizes(coordinatesNew, n * cdim, PETSC_DETERMINE)); 375ac9d17c7SMatthew G. Knepley PetscCall(VecSetUp(coordinatesNew)); 376ac9d17c7SMatthew G. Knepley PetscCall(PetscMalloc1(n * bs, &indices)); 377ac9d17c7SMatthew G. Knepley for (PetscInt i = 0; i < n; ++i) 378ac9d17c7SMatthew G. Knepley for (PetscInt b = 0; b < bs; ++b) indices[i * bs + b] = i * cdim + b; 379ac9d17c7SMatthew G. Knepley PetscCall(ISCreateGeneral(PETSC_COMM_SELF, n * bs, indices, PETSC_OWN_POINTER, &idx)); 380ac9d17c7SMatthew G. Knepley PetscCall(VecISCopy(coordinatesNew, idx, SCATTER_FORWARD, coordinates)); 381ac9d17c7SMatthew G. Knepley PetscCall(ISDestroy(&idx)); 382ac9d17c7SMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinatesNew)); 383ac9d17c7SMatthew G. Knepley PetscCall(VecDestroy(&coordinatesNew)); 384ac9d17c7SMatthew G. Knepley PetscCall(DMSetCoordinateDim(dm, cdim)); 385ac9d17c7SMatthew G. Knepley { 386ac9d17c7SMatthew G. Knepley PetscInt gn; 387ac9d17c7SMatthew G. Knepley 388ac9d17c7SMatthew G. Knepley PetscCall(DMGetCoordinates(dm, &coordinatesNew)); 389ac9d17c7SMatthew G. Knepley PetscCall(VecGetLocalSize(coordinatesNew, &gn)); 390ac9d17c7SMatthew 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); 391ac9d17c7SMatthew G. Knepley } 392ac9d17c7SMatthew G. Knepley dE = cdim; 393530e699aSMatthew G. Knepley project = PETSC_FALSE; 394ac9d17c7SMatthew G. Knepley } 395e44f6aebSMatthew G. Knepley if (degree >= 0) { 396e44f6aebSMatthew G. Knepley DMPolytopeType ct = DM_POLYTOPE_UNKNOWN; 397e44f6aebSMatthew G. Knepley PetscInt cStart, cEnd, gct; 398dc431b0cSMatthew G. Knepley 3991df12153SMatthew G. Knepley PetscCall(DMPlexGetHeightStratum(dm, height, &cStart, &cEnd)); 400dc431b0cSMatthew G. Knepley if (cEnd > cStart) PetscCall(DMPlexGetCellType(dm, cStart, &ct)); 401e44f6aebSMatthew G. Knepley gct = (PetscInt)ct; 402462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &gct, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm))); 403e44f6aebSMatthew G. Knepley ct = (DMPolytopeType)gct; 404e44f6aebSMatthew G. Knepley // Work around current bug in PetscDualSpaceSetUp_Lagrange() 405e44f6aebSMatthew G. Knepley // Can be seen in plex_tutorials-ex10_1 406*4c712d99Sksagiyam if (ct != DM_POLYTOPE_SEG_PRISM_TENSOR && ct != DM_POLYTOPE_TRI_PRISM_TENSOR && ct != DM_POLYTOPE_QUAD_PRISM_TENSOR) { 407*4c712d99Sksagiyam PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, dE, ct, degree, qorder, &fe)); 408*4c712d99Sksagiyam if (localized) { 409*4c712d99Sksagiyam PetscFE dgfe = NULL; 410*4c712d99Sksagiyam 411*4c712d99Sksagiyam PetscCall(PetscFECreateBrokenElement(fe, &dgfe)); 412*4c712d99Sksagiyam PetscCall(PetscFEDestroy(&fe)); 413*4c712d99Sksagiyam fe = dgfe; 4144f9ab2b4SJed Brown } 415*4c712d99Sksagiyam } 416*4c712d99Sksagiyam } 417*4c712d99Sksagiyam PetscCall(DMSetCoordinateDisc(dm, fe, localized, project)); 4189566063dSJacob Faibussowitsch PetscCall(PetscFEDestroy(&fe)); 4193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4209318fe57SMatthew G. Knepley } 4219318fe57SMatthew G. Knepley 4221df5d5c5SMatthew G. Knepley /*@ 4231df5d5c5SMatthew G. Knepley DMPlexCreateDoublet - Creates a mesh of two cells of the specified type, optionally with later refinement. 4241df5d5c5SMatthew G. Knepley 425d083f849SBarry Smith Collective 4261df5d5c5SMatthew G. Knepley 4271df5d5c5SMatthew G. Knepley Input Parameters: 428a1cb98faSBarry Smith + comm - The communicator for the `DM` object 4291df5d5c5SMatthew G. Knepley . dim - The spatial dimension 4301df5d5c5SMatthew G. Knepley . simplex - Flag for simplicial cells, otherwise they are tensor product cells 4311df5d5c5SMatthew G. Knepley . interpolate - Flag to create intermediate mesh pieces (edges, faces) 4321df5d5c5SMatthew G. Knepley - refinementLimit - A nonzero number indicates the largest admissible volume for a refined cell 4331df5d5c5SMatthew G. Knepley 4341df5d5c5SMatthew G. Knepley Output Parameter: 43560225df5SJacob Faibussowitsch . newdm - The `DM` object 4361df5d5c5SMatthew G. Knepley 4371df5d5c5SMatthew G. Knepley Level: beginner 4381df5d5c5SMatthew G. Knepley 4391cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetType()`, `DMCreate()` 4401df5d5c5SMatthew G. Knepley @*/ 441d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateDoublet(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscBool interpolate, PetscReal refinementLimit, DM *newdm) 442d71ae5a4SJacob Faibussowitsch { 4431df5d5c5SMatthew G. Knepley DM dm; 4441df5d5c5SMatthew G. Knepley PetscMPIInt rank; 4451df5d5c5SMatthew G. Knepley 4461df5d5c5SMatthew G. Knepley PetscFunctionBegin; 4479566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, &dm)); 4489566063dSJacob Faibussowitsch PetscCall(DMSetType(dm, DMPLEX)); 4499566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 45046139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 4519566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 452ce78fa2fSMatthew G. Knepley switch (dim) { 453ce78fa2fSMatthew G. Knepley case 2: 4549566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "triangular")); 4559566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "quadrilateral")); 456ce78fa2fSMatthew G. Knepley break; 457ce78fa2fSMatthew G. Knepley case 3: 4589566063dSJacob Faibussowitsch if (simplex) PetscCall(PetscObjectSetName((PetscObject)dm, "tetrahedral")); 4599566063dSJacob Faibussowitsch else PetscCall(PetscObjectSetName((PetscObject)dm, "hexahedral")); 460ce78fa2fSMatthew G. Knepley break; 461d71ae5a4SJacob Faibussowitsch default: 462d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 463ce78fa2fSMatthew G. Knepley } 4641df5d5c5SMatthew G. Knepley if (rank) { 4651df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {0, 0}; 4669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, NULL, NULL, NULL, NULL)); 4671df5d5c5SMatthew G. Knepley } else { 4681df5d5c5SMatthew G. Knepley switch (dim) { 4691df5d5c5SMatthew G. Knepley case 2: 4701df5d5c5SMatthew G. Knepley if (simplex) { 4711df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {4, 2}; 4721df5d5c5SMatthew G. Knepley PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 4731df5d5c5SMatthew G. Knepley PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 4741df5d5c5SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 4751df5d5c5SMatthew G. Knepley PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 4761df5d5c5SMatthew G. Knepley 4779566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4781df5d5c5SMatthew G. Knepley } else { 4791df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {6, 2}; 4801df5d5c5SMatthew G. Knepley PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 4811df5d5c5SMatthew G. Knepley PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 4821df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 4831df5d5c5SMatthew 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}; 4841df5d5c5SMatthew G. Knepley 4859566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4861df5d5c5SMatthew G. Knepley } 4871df5d5c5SMatthew G. Knepley break; 4881df5d5c5SMatthew G. Knepley case 3: 4891df5d5c5SMatthew G. Knepley if (simplex) { 4901df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {5, 2}; 4911df5d5c5SMatthew G. Knepley PetscInt coneSize[7] = {4, 4, 0, 0, 0, 0, 0}; 4921df5d5c5SMatthew G. Knepley PetscInt cones[8] = {4, 3, 5, 2, 5, 3, 4, 6}; 4931df5d5c5SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 4941df5d5c5SMatthew 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}; 4951df5d5c5SMatthew G. Knepley 4969566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 4971df5d5c5SMatthew G. Knepley } else { 4981df5d5c5SMatthew G. Knepley PetscInt numPoints[2] = {12, 2}; 4991df5d5c5SMatthew G. Knepley PetscInt coneSize[14] = {8, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 5001df5d5c5SMatthew G. Knepley PetscInt cones[16] = {2, 3, 4, 5, 6, 7, 8, 9, 5, 4, 10, 11, 7, 12, 13, 8}; 5011df5d5c5SMatthew G. Knepley PetscInt coneOrientations[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 5029371c9d4SSatish 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}; 5031df5d5c5SMatthew G. Knepley 5049566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 5051df5d5c5SMatthew G. Knepley } 5061df5d5c5SMatthew G. Knepley break; 507d71ae5a4SJacob Faibussowitsch default: 508d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %" PetscInt_FMT, dim); 5091df5d5c5SMatthew G. Knepley } 5101df5d5c5SMatthew G. Knepley } 51146139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 5121df5d5c5SMatthew G. Knepley *newdm = dm; 5131df5d5c5SMatthew G. Knepley if (refinementLimit > 0.0) { 5141df5d5c5SMatthew G. Knepley DM rdm; 5151df5d5c5SMatthew G. Knepley const char *name; 5161df5d5c5SMatthew G. Knepley 5179566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(*newdm, PETSC_FALSE)); 5189566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(*newdm, refinementLimit)); 5199566063dSJacob Faibussowitsch PetscCall(DMRefine(*newdm, comm, &rdm)); 5209566063dSJacob Faibussowitsch PetscCall(PetscObjectGetName((PetscObject)*newdm, &name)); 5219566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, name)); 5229566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 5231df5d5c5SMatthew G. Knepley *newdm = rdm; 5241df5d5c5SMatthew G. Knepley } 5251df5d5c5SMatthew G. Knepley if (interpolate) { 5265fd9971aSMatthew G. Knepley DM idm; 5271df5d5c5SMatthew G. Knepley 5289566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*newdm, &idm)); 5299566063dSJacob Faibussowitsch PetscCall(DMDestroy(newdm)); 5301df5d5c5SMatthew G. Knepley *newdm = idm; 5311df5d5c5SMatthew G. Knepley } 5323ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5331df5d5c5SMatthew G. Knepley } 5341df5d5c5SMatthew G. Knepley 535d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 536d71ae5a4SJacob Faibussowitsch { 5379318fe57SMatthew G. Knepley const PetscInt numVertices = 2; 5389318fe57SMatthew G. Knepley PetscInt markerRight = 1; 5399318fe57SMatthew G. Knepley PetscInt markerLeft = 1; 5409318fe57SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 5419318fe57SMatthew G. Knepley Vec coordinates; 5429318fe57SMatthew G. Knepley PetscSection coordSection; 5439318fe57SMatthew G. Knepley PetscScalar *coords; 5449318fe57SMatthew G. Knepley PetscInt coordSize; 5459318fe57SMatthew G. Knepley PetscMPIInt rank; 5469318fe57SMatthew G. Knepley PetscInt cdim = 1, v; 547552f7358SJed Brown 5489318fe57SMatthew G. Knepley PetscFunctionBegin; 5499566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 5509318fe57SMatthew G. Knepley if (markerSeparate) { 5519318fe57SMatthew G. Knepley markerRight = 2; 5529318fe57SMatthew G. Knepley markerLeft = 1; 5539318fe57SMatthew G. Knepley } 5549566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 555c5853193SPierre Jolivet if (rank == 0) { 5569566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numVertices)); 5579566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 5589566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 0, markerLeft)); 5599566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", 1, markerRight)); 5609318fe57SMatthew G. Knepley } 5619566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 5629566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 5639318fe57SMatthew G. Knepley /* Build coordinates */ 5649566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, cdim)); 5659566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 5669566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 5679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, 0, numVertices)); 5689566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 5699318fe57SMatthew G. Knepley for (v = 0; v < numVertices; ++v) { 5709566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 5719566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 5729318fe57SMatthew G. Knepley } 5739566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 5749566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 5759566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 5769566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 5779566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 5789566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 5799566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 5809566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 5819318fe57SMatthew G. Knepley coords[0] = lower[0]; 5829318fe57SMatthew G. Knepley coords[1] = upper[0]; 5839566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 5849566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 5859566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 5863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5879318fe57SMatthew G. Knepley } 58826492d91SMatthew G. Knepley 589d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[]) 590d71ae5a4SJacob Faibussowitsch { 5911df21d24SMatthew G. Knepley const PetscInt numVertices = (edges[0] + 1) * (edges[1] + 1); 5921df21d24SMatthew G. Knepley const PetscInt numEdges = edges[0] * (edges[1] + 1) + (edges[0] + 1) * edges[1]; 593552f7358SJed Brown PetscInt markerTop = 1; 594552f7358SJed Brown PetscInt markerBottom = 1; 595552f7358SJed Brown PetscInt markerRight = 1; 596552f7358SJed Brown PetscInt markerLeft = 1; 597552f7358SJed Brown PetscBool markerSeparate = PETSC_FALSE; 598552f7358SJed Brown Vec coordinates; 599552f7358SJed Brown PetscSection coordSection; 600552f7358SJed Brown PetscScalar *coords; 601552f7358SJed Brown PetscInt coordSize; 602552f7358SJed Brown PetscMPIInt rank; 603552f7358SJed Brown PetscInt v, vx, vy; 604552f7358SJed Brown 605552f7358SJed Brown PetscFunctionBegin; 6069566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 607552f7358SJed Brown if (markerSeparate) { 6081df21d24SMatthew G. Knepley markerTop = 3; 6091df21d24SMatthew G. Knepley markerBottom = 1; 6101df21d24SMatthew G. Knepley markerRight = 2; 6111df21d24SMatthew G. Knepley markerLeft = 4; 612552f7358SJed Brown } 6139566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 614dd400576SPatrick Sanan if (rank == 0) { 615552f7358SJed Brown PetscInt e, ex, ey; 616552f7358SJed Brown 6179566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numEdges + numVertices)); 61848a46eb9SPierre Jolivet for (e = 0; e < numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 6199566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 620552f7358SJed Brown for (vx = 0; vx <= edges[0]; vx++) { 621552f7358SJed Brown for (ey = 0; ey < edges[1]; ey++) { 622552f7358SJed Brown PetscInt edge = vx * edges[1] + ey + edges[0] * (edges[1] + 1); 623552f7358SJed Brown PetscInt vertex = ey * (edges[0] + 1) + vx + numEdges; 624da80777bSKarl Rupp PetscInt cone[2]; 625552f7358SJed Brown 6269371c9d4SSatish Balay cone[0] = vertex; 6279371c9d4SSatish Balay cone[1] = vertex + edges[0] + 1; 6289566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 629552f7358SJed Brown if (vx == edges[0]) { 6309566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 6319566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 632552f7358SJed Brown if (ey == edges[1] - 1) { 6339566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 6349566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerRight)); 635552f7358SJed Brown } 636552f7358SJed Brown } else if (vx == 0) { 6379566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 6389566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 639552f7358SJed Brown if (ey == edges[1] - 1) { 6409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 6419566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerLeft)); 642552f7358SJed Brown } 643552f7358SJed Brown } 644552f7358SJed Brown } 645552f7358SJed Brown } 646552f7358SJed Brown for (vy = 0; vy <= edges[1]; vy++) { 647552f7358SJed Brown for (ex = 0; ex < edges[0]; ex++) { 648552f7358SJed Brown PetscInt edge = vy * edges[0] + ex; 649552f7358SJed Brown PetscInt vertex = vy * (edges[0] + 1) + ex + numEdges; 650da80777bSKarl Rupp PetscInt cone[2]; 651552f7358SJed Brown 6529371c9d4SSatish Balay cone[0] = vertex; 6539371c9d4SSatish Balay cone[1] = vertex + 1; 6549566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 655552f7358SJed Brown if (vy == edges[1]) { 6569566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 6579566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 658552f7358SJed Brown if (ex == edges[0] - 1) { 6599566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 6609566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerTop)); 661552f7358SJed Brown } 662552f7358SJed Brown } else if (vy == 0) { 6639566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 6649566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 665552f7358SJed Brown if (ex == edges[0] - 1) { 6669566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 6679566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", cone[1], markerBottom)); 668552f7358SJed Brown } 669552f7358SJed Brown } 670552f7358SJed Brown } 671552f7358SJed Brown } 672552f7358SJed Brown } 6739566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 6749566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 675552f7358SJed Brown /* Build coordinates */ 6769566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 2)); 6779566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 6789566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 6799566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numEdges, numEdges + numVertices)); 6809566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 681552f7358SJed Brown for (v = numEdges; v < numEdges + numVertices; ++v) { 6829566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 2)); 6839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 684552f7358SJed Brown } 6859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6869566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 6879566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 6889566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 6899566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 6909566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 2)); 6919566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 6929566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 693552f7358SJed Brown for (vy = 0; vy <= edges[1]; ++vy) { 694552f7358SJed Brown for (vx = 0; vx <= edges[0]; ++vx) { 695552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 0] = lower[0] + ((upper[0] - lower[0]) / edges[0]) * vx; 696552f7358SJed Brown coords[(vy * (edges[0] + 1) + vx) * 2 + 1] = lower[1] + ((upper[1] - lower[1]) / edges[1]) * vy; 697552f7358SJed Brown } 698552f7358SJed Brown } 6999566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 7009566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 7019566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 7023ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 703552f7358SJed Brown } 704552f7358SJed Brown 705d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt faces[]) 706d71ae5a4SJacob Faibussowitsch { 7079e8abbc3SMichael Lange PetscInt vertices[3], numVertices; 7087b59f5a9SMichael Lange PetscInt numFaces = 2 * faces[0] * faces[1] + 2 * faces[1] * faces[2] + 2 * faces[0] * faces[2]; 709c2df9bbfSMatthew G. Knepley PetscInt markerTop = 1; 710c2df9bbfSMatthew G. Knepley PetscInt markerBottom = 1; 711c2df9bbfSMatthew G. Knepley PetscInt markerFront = 1; 712c2df9bbfSMatthew G. Knepley PetscInt markerBack = 1; 713c2df9bbfSMatthew G. Knepley PetscInt markerRight = 1; 714c2df9bbfSMatthew G. Knepley PetscInt markerLeft = 1; 715c2df9bbfSMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE; 716552f7358SJed Brown Vec coordinates; 717552f7358SJed Brown PetscSection coordSection; 718552f7358SJed Brown PetscScalar *coords; 719552f7358SJed Brown PetscInt coordSize; 720552f7358SJed Brown PetscMPIInt rank; 721552f7358SJed Brown PetscInt v, vx, vy, vz; 7227b59f5a9SMichael Lange PetscInt voffset, iface = 0, cone[4]; 723552f7358SJed Brown 724552f7358SJed Brown PetscFunctionBegin; 7251dca8a05SBarry 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"); 7269566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 727c2df9bbfSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 728c2df9bbfSMatthew G. Knepley if (markerSeparate) { 729c2df9bbfSMatthew G. Knepley markerBottom = 1; 730c2df9bbfSMatthew G. Knepley markerTop = 2; 731c2df9bbfSMatthew G. Knepley markerFront = 3; 732c2df9bbfSMatthew G. Knepley markerBack = 4; 733c2df9bbfSMatthew G. Knepley markerRight = 5; 734c2df9bbfSMatthew G. Knepley markerLeft = 6; 735c2df9bbfSMatthew G. Knepley } 7369371c9d4SSatish Balay vertices[0] = faces[0] + 1; 7379371c9d4SSatish Balay vertices[1] = faces[1] + 1; 7389371c9d4SSatish Balay vertices[2] = faces[2] + 1; 7399e8abbc3SMichael Lange numVertices = vertices[0] * vertices[1] * vertices[2]; 740dd400576SPatrick Sanan if (rank == 0) { 741552f7358SJed Brown PetscInt f; 742552f7358SJed Brown 7439566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numFaces + numVertices)); 74448a46eb9SPierre Jolivet for (f = 0; f < numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 7459566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 7467b59f5a9SMichael Lange 7477b59f5a9SMichael Lange /* Side 0 (Top) */ 7487b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7497b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7507b59f5a9SMichael Lange voffset = numFaces + vertices[0] * vertices[1] * (vertices[2] - 1) + vy * vertices[0] + vx; 7519371c9d4SSatish Balay cone[0] = voffset; 7529371c9d4SSatish Balay cone[1] = voffset + 1; 7539371c9d4SSatish Balay cone[2] = voffset + vertices[0] + 1; 7549371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 7559566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 756c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerTop)); 757c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerTop)); 758c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerTop)); 759c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerTop)); 760c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerTop)); 7617b59f5a9SMichael Lange iface++; 762552f7358SJed Brown } 763552f7358SJed Brown } 7647b59f5a9SMichael Lange 7657b59f5a9SMichael Lange /* Side 1 (Bottom) */ 7667b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 7677b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7687b59f5a9SMichael Lange voffset = numFaces + vy * (faces[0] + 1) + vx; 7699371c9d4SSatish Balay cone[0] = voffset + 1; 7709371c9d4SSatish Balay cone[1] = voffset; 7719371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 7729371c9d4SSatish Balay cone[3] = voffset + vertices[0] + 1; 7739566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 774c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBottom)); 775c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBottom)); 776c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBottom)); 777c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerBottom)); 778c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 1, markerBottom)); 7797b59f5a9SMichael Lange iface++; 780552f7358SJed Brown } 781552f7358SJed Brown } 7827b59f5a9SMichael Lange 7837b59f5a9SMichael Lange /* Side 2 (Front) */ 7847b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 7857b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 7867b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vx; 7879371c9d4SSatish Balay cone[0] = voffset; 7889371c9d4SSatish Balay cone[1] = voffset + 1; 7899371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + 1; 7909371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1]; 7919566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 792c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerFront)); 793c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerFront)); 794c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerFront)); 795c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerFront)); 796c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerFront)); 7977b59f5a9SMichael Lange iface++; 798552f7358SJed Brown } 7997b59f5a9SMichael Lange } 8007b59f5a9SMichael Lange 8017b59f5a9SMichael Lange /* Side 3 (Back) */ 8027b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8037b59f5a9SMichael Lange for (vx = 0; vx < faces[0]; vx++) { 8047b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vertices[0] * (vertices[1] - 1) + vx; 8059371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 8069371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1] + 1; 8079371c9d4SSatish Balay cone[2] = voffset + 1; 8089371c9d4SSatish Balay cone[3] = voffset; 8099566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 810c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerBack)); 811c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerBack)); 812c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 1, markerBack)); 813c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerBack)); 814c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 1, markerBack)); 8157b59f5a9SMichael Lange iface++; 8167b59f5a9SMichael Lange } 8177b59f5a9SMichael Lange } 8187b59f5a9SMichael Lange 8197b59f5a9SMichael Lange /* Side 4 (Left) */ 8207b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8217b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 8227b59f5a9SMichael Lange voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0]; 8239371c9d4SSatish Balay cone[0] = voffset; 8249371c9d4SSatish Balay cone[1] = voffset + vertices[0] * vertices[1]; 8259371c9d4SSatish Balay cone[2] = voffset + vertices[0] * vertices[1] + vertices[0]; 8269371c9d4SSatish Balay cone[3] = voffset + vertices[0]; 8279566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 828c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerLeft)); 829c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerLeft)); 830c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerLeft)); 831c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[1] + 0, markerLeft)); 832c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerLeft)); 8337b59f5a9SMichael Lange iface++; 8347b59f5a9SMichael Lange } 8357b59f5a9SMichael Lange } 8367b59f5a9SMichael Lange 8377b59f5a9SMichael Lange /* Side 5 (Right) */ 8387b59f5a9SMichael Lange for (vz = 0; vz < faces[2]; vz++) { 8397b59f5a9SMichael Lange for (vy = 0; vy < faces[1]; vy++) { 840aab5bcd8SJed Brown voffset = numFaces + vz * vertices[0] * vertices[1] + vy * vertices[0] + faces[0]; 8419371c9d4SSatish Balay cone[0] = voffset + vertices[0] * vertices[1]; 8429371c9d4SSatish Balay cone[1] = voffset; 8439371c9d4SSatish Balay cone[2] = voffset + vertices[0]; 8449371c9d4SSatish Balay cone[3] = voffset + vertices[0] * vertices[1] + vertices[0]; 8459566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, iface, cone)); 846c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", iface, markerRight)); 847c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + 0, markerRight)); 848c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] + 0, markerRight)); 849c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + 0, markerRight)); 850c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", voffset + vertices[0] * vertices[1] + vertices[0], markerRight)); 8517b59f5a9SMichael Lange iface++; 8527b59f5a9SMichael Lange } 853552f7358SJed Brown } 854552f7358SJed Brown } 8559566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 8569566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 857552f7358SJed Brown /* Build coordinates */ 8589566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, 3)); 8599566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 8609566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 8619566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numFaces, numFaces + numVertices)); 8629566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 3)); 863552f7358SJed Brown for (v = numFaces; v < numFaces + numVertices; ++v) { 8649566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, 3)); 8659566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 3)); 866552f7358SJed Brown } 8679566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 8689566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 8699566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 8709566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 8719566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 8729566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, 3)); 8739566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 8749566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 875552f7358SJed Brown for (vz = 0; vz <= faces[2]; ++vz) { 876552f7358SJed Brown for (vy = 0; vy <= faces[1]; ++vy) { 877552f7358SJed Brown for (vx = 0; vx <= faces[0]; ++vx) { 878552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 0] = lower[0] + ((upper[0] - lower[0]) / faces[0]) * vx; 879552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 1] = lower[1] + ((upper[1] - lower[1]) / faces[1]) * vy; 880552f7358SJed Brown coords[((vz * (faces[1] + 1) + vy) * (faces[0] + 1) + vx) * 3 + 2] = lower[2] + ((upper[2] - lower[2]) / faces[2]) * vz; 881552f7358SJed Brown } 882552f7358SJed Brown } 883552f7358SJed Brown } 8849566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 8859566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 8869566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 8873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 888552f7358SJed Brown } 889552f7358SJed Brown 890d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxSurfaceMesh_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate) 891d71ae5a4SJacob Faibussowitsch { 8929318fe57SMatthew G. Knepley PetscFunctionBegin; 8939318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 89446139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 8959566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim - 1)); 8969566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim)); 8979318fe57SMatthew G. Knepley switch (dim) { 898d71ae5a4SJacob Faibussowitsch case 1: 899d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_1D_Internal(dm, lower, upper, faces)); 900d71ae5a4SJacob Faibussowitsch break; 901d71ae5a4SJacob Faibussowitsch case 2: 902d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_2D_Internal(dm, lower, upper, faces)); 903d71ae5a4SJacob Faibussowitsch break; 904d71ae5a4SJacob Faibussowitsch case 3: 905d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Tensor_3D_Internal(dm, lower, upper, faces)); 906d71ae5a4SJacob Faibussowitsch break; 907d71ae5a4SJacob Faibussowitsch default: 908d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Dimension not supported: %" PetscInt_FMT, dim); 9099318fe57SMatthew G. Knepley } 91046139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 9119566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 9123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9139318fe57SMatthew G. Knepley } 9149318fe57SMatthew G. Knepley 9159318fe57SMatthew G. Knepley /*@C 9169318fe57SMatthew G. Knepley DMPlexCreateBoxSurfaceMesh - Creates a mesh on the surface of the tensor product of unit intervals (box) using tensor cells (hexahedra). 9179318fe57SMatthew G. Knepley 9189318fe57SMatthew G. Knepley Collective 9199318fe57SMatthew G. Knepley 9209318fe57SMatthew G. Knepley Input Parameters: 921a1cb98faSBarry Smith + comm - The communicator for the `DM` object 92220f4b53cSBarry Smith . dim - The spatial dimension of the box, so the resulting mesh is has dimension `dim`-1 92320f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 92420f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 92520f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 9269318fe57SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 9279318fe57SMatthew G. Knepley 9289318fe57SMatthew G. Knepley Output Parameter: 929a1cb98faSBarry Smith . dm - The `DM` object 9309318fe57SMatthew G. Knepley 9319318fe57SMatthew G. Knepley Level: beginner 9329318fe57SMatthew G. Knepley 9331cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateBoxMesh()`, `DMPlexCreateFromFile()`, `DMSetType()`, `DMCreate()` 9349318fe57SMatthew G. Knepley @*/ 935d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBoxSurfaceMesh(MPI_Comm comm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], PetscBool interpolate, DM *dm) 936d71ae5a4SJacob Faibussowitsch { 9379318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 9389318fe57SMatthew G. Knepley PetscReal low[3] = {0, 0, 0}; 9399318fe57SMatthew G. Knepley PetscReal upp[3] = {1, 1, 1}; 9409318fe57SMatthew G. Knepley 9419318fe57SMatthew G. Knepley PetscFunctionBegin; 9429566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 9439566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 9449566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(*dm, dim, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, interpolate)); 9453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 9469318fe57SMatthew G. Knepley } 9479318fe57SMatthew G. Knepley 948d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateLineMesh_Internal(DM dm, PetscInt segments, PetscReal lower, PetscReal upper, DMBoundaryType bd) 949d71ae5a4SJacob Faibussowitsch { 950fdbf62faSLisandro Dalcin PetscInt i, fStart, fEnd, numCells = 0, numVerts = 0; 951fdbf62faSLisandro Dalcin PetscInt numPoints[2], *coneSize, *cones, *coneOrientations; 952fdbf62faSLisandro Dalcin PetscScalar *vertexCoords; 953fdbf62faSLisandro Dalcin PetscReal L, maxCell; 954fdbf62faSLisandro Dalcin PetscBool markerSeparate = PETSC_FALSE; 955fdbf62faSLisandro Dalcin PetscInt markerLeft = 1, faceMarkerLeft = 1; 956fdbf62faSLisandro Dalcin PetscInt markerRight = 1, faceMarkerRight = 2; 957fdbf62faSLisandro Dalcin PetscBool wrap = (bd == DM_BOUNDARY_PERIODIC || bd == DM_BOUNDARY_TWIST) ? PETSC_TRUE : PETSC_FALSE; 958fdbf62faSLisandro Dalcin PetscMPIInt rank; 959fdbf62faSLisandro Dalcin 960fdbf62faSLisandro Dalcin PetscFunctionBegin; 9614f572ea9SToby Isaac PetscAssertPointer(dm, 1); 962fdbf62faSLisandro Dalcin 9639566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, 1)); 9649566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 9659566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 966fdbf62faSLisandro Dalcin 9679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 968dd400576SPatrick Sanan if (rank == 0) numCells = segments; 969dd400576SPatrick Sanan if (rank == 0) numVerts = segments + (wrap ? 0 : 1); 970fdbf62faSLisandro Dalcin 9719371c9d4SSatish Balay numPoints[0] = numVerts; 9729371c9d4SSatish Balay numPoints[1] = numCells; 9739566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(numCells + numVerts, &coneSize, numCells * 2, &cones, numCells + numVerts, &coneOrientations, numVerts, &vertexCoords)); 9749566063dSJacob Faibussowitsch PetscCall(PetscArrayzero(coneOrientations, numCells + numVerts)); 975ad540459SPierre Jolivet for (i = 0; i < numCells; ++i) coneSize[i] = 2; 976ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) coneSize[numCells + i] = 0; 9779371c9d4SSatish Balay for (i = 0; i < numCells; ++i) { 9789371c9d4SSatish Balay cones[2 * i] = numCells + i % numVerts; 9799371c9d4SSatish Balay cones[2 * i + 1] = numCells + (i + 1) % numVerts; 9809371c9d4SSatish Balay } 981ad540459SPierre Jolivet for (i = 0; i < numVerts; ++i) vertexCoords[i] = lower + (upper - lower) * ((PetscReal)i / (PetscReal)numCells); 9829566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 9839566063dSJacob Faibussowitsch PetscCall(PetscFree4(coneSize, cones, coneOrientations, vertexCoords)); 984fdbf62faSLisandro Dalcin 9859566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 9869371c9d4SSatish Balay if (markerSeparate) { 9879371c9d4SSatish Balay markerLeft = faceMarkerLeft; 9889371c9d4SSatish Balay markerRight = faceMarkerRight; 9899371c9d4SSatish Balay } 990dd400576SPatrick Sanan if (!wrap && rank == 0) { 9919566063dSJacob Faibussowitsch PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 9929566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fStart, markerLeft)); 9939566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", fEnd - 1, markerRight)); 9949566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fStart, faceMarkerLeft)); 9959566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", fEnd - 1, faceMarkerRight)); 996fdbf62faSLisandro Dalcin } 997fdbf62faSLisandro Dalcin if (wrap) { 998fdbf62faSLisandro Dalcin L = upper - lower; 999fdbf62faSLisandro Dalcin maxCell = (PetscReal)1.1 * (L / (PetscReal)PetscMax(1, segments)); 10004fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, &maxCell, &lower, &L)); 1001fdbf62faSLisandro Dalcin } 10029566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 10033ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1004fdbf62faSLisandro Dalcin } 1005fdbf62faSLisandro Dalcin 10064054ae39SJames Wright // Creates "Face Sets" label based on the standard box labeling conventions 1007d7d2d1d2SJames Wright static PetscErrorCode DMPlexSetBoxLabel_Internal(DM dm, const DMBoundaryType periodicity[]) 10084054ae39SJames Wright { 10096ff49feeSJames Wright DM cdm; 10106ff49feeSJames Wright PetscSection csection; 10116ff49feeSJames Wright Vec coordinates; 10124054ae39SJames Wright DMLabel label; 10136ff49feeSJames Wright IS faces_is; 10142b4f33d9SJames Wright PetscInt dim, num_face = 0; 10154054ae39SJames Wright const PetscInt *faces; 10164054ae39SJames Wright PetscInt faceMarkerBottom, faceMarkerTop, faceMarkerFront, faceMarkerBack, faceMarkerRight, faceMarkerLeft; 10174054ae39SJames Wright 10184054ae39SJames Wright PetscFunctionBeginUser; 10194054ae39SJames Wright PetscCall(DMGetDimension(dm, &dim)); 1020d7c1f440SPierre 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); 10214054ae39SJames Wright // Get Face Sets label 10224054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 10234054ae39SJames Wright if (label) { 10244054ae39SJames Wright PetscCall(DMLabelReset(label)); 10254054ae39SJames Wright } else { 10264054ae39SJames Wright PetscCall(DMCreateLabel(dm, "Face Sets")); 10274054ae39SJames Wright PetscCall(DMGetLabel(dm, "Face Sets", &label)); 10284054ae39SJames Wright } 10294054ae39SJames Wright PetscCall(DMPlexMarkBoundaryFaces(dm, 1, label)); 10306ff49feeSJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", 1, &faces_is)); 10314054ae39SJames Wright 10324054ae39SJames Wright switch (dim) { 10334054ae39SJames Wright case 2: 10344054ae39SJames Wright faceMarkerTop = 3; 10354054ae39SJames Wright faceMarkerBottom = 1; 10364054ae39SJames Wright faceMarkerRight = 2; 10374054ae39SJames Wright faceMarkerLeft = 4; 10384054ae39SJames Wright break; 10394054ae39SJames Wright case 3: 10404054ae39SJames Wright faceMarkerBottom = 1; 10414054ae39SJames Wright faceMarkerTop = 2; 10424054ae39SJames Wright faceMarkerFront = 3; 10434054ae39SJames Wright faceMarkerBack = 4; 10444054ae39SJames Wright faceMarkerRight = 5; 10454054ae39SJames Wright faceMarkerLeft = 6; 10464054ae39SJames Wright break; 10474054ae39SJames Wright default: 10484054ae39SJames Wright SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 10494054ae39SJames Wright } 10504054ae39SJames Wright 10512b4f33d9SJames Wright if (faces_is) PetscCall(ISGetLocalSize(faces_is, &num_face)); 10522b4f33d9SJames Wright if (faces_is) PetscCall(ISGetIndices(faces_is, &faces)); 10536ff49feeSJames Wright PetscCall(DMGetCoordinatesLocal(dm, &coordinates)); 10546ff49feeSJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 10556ff49feeSJames Wright PetscCall(DMGetLocalSection(cdm, &csection)); 10564054ae39SJames Wright for (PetscInt f = 0; f < num_face; ++f) { 10576ff49feeSJames Wright PetscScalar *coords = NULL; 10586ff49feeSJames Wright PetscInt face = faces[f], flip = 1, label_value = -1, coords_size; 10594054ae39SJames Wright 10604054ae39SJames Wright { // Determine if orientation of face is flipped 10614054ae39SJames Wright PetscInt num_cells_support, num_faces, start = -1; 10624054ae39SJames Wright const PetscInt *orients, *cell_faces, *cells; 10634054ae39SJames Wright 10644054ae39SJames Wright PetscCall(DMPlexGetSupport(dm, face, &cells)); 10654054ae39SJames Wright PetscCall(DMPlexGetSupportSize(dm, face, &num_cells_support)); 10664054ae39SJames 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); 10674054ae39SJames Wright PetscCall(DMPlexGetCone(dm, cells[0], &cell_faces)); 10684054ae39SJames Wright PetscCall(DMPlexGetConeSize(dm, cells[0], &num_faces)); 10694054ae39SJames Wright for (PetscInt i = 0; i < num_faces; i++) { 10704054ae39SJames Wright if (cell_faces[i] == face) start = i; 10714054ae39SJames Wright } 10724054ae39SJames Wright PetscCheck(start >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_CORRUPT, "Could not find face %" PetscInt_FMT " in cone of its support", face); 10734054ae39SJames Wright PetscCall(DMPlexGetConeOrientation(dm, cells[0], &orients)); 10744054ae39SJames Wright if (orients[start] < 0) flip = -1; 10754054ae39SJames Wright } 10764054ae39SJames Wright 10776ff49feeSJames Wright // Cannot use DMPlexComputeCellGeometryFVM() for high-order geometry, so must calculate normal vectors manually 10786ff49feeSJames Wright // Use the vertices (depth 0) of coordinate DM to calculate normal vector 10796ff49feeSJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 10804054ae39SJames Wright switch (dim) { 10814054ae39SJames Wright case 2: { 10826ff49feeSJames Wright PetscScalar vec[2]; 10836ff49feeSJames Wright 10846ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) vec[d] = flip * (PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d])); 10856ff49feeSJames Wright PetscScalar normal[] = {vec[1], -vec[0]}; 10866ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 10876ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 10884054ae39SJames Wright } else { 10896ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerTop : faceMarkerBottom; 10904054ae39SJames Wright } 10914054ae39SJames Wright } break; 10924054ae39SJames Wright case 3: { 10936ff49feeSJames Wright PetscScalar vec1[3], vec2[3], normal[3]; 10946ff49feeSJames Wright 10956ff49feeSJames Wright for (PetscInt d = 0; d < dim; ++d) { 10966ff49feeSJames Wright vec1[d] = PetscRealPart(coords[1 * dim + d]) - PetscRealPart(coords[0 * dim + d]); 10976ff49feeSJames Wright vec2[d] = PetscRealPart(coords[2 * dim + d]) - PetscRealPart(coords[1 * dim + d]); 10986ff49feeSJames Wright } 10996ff49feeSJames Wright 11006ff49feeSJames Wright // Calculate normal vector via cross-product 11016ff49feeSJames Wright normal[0] = flip * ((vec1[1] * vec2[2]) - (vec1[2] * vec2[1])); 11026ff49feeSJames Wright normal[1] = flip * ((vec1[2] * vec2[0]) - (vec1[0] * vec2[2])); 11036ff49feeSJames Wright normal[2] = flip * ((vec1[0] * vec2[1]) - (vec1[1] * vec2[0])); 11046ff49feeSJames Wright 11056ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[1])) { 11066ff49feeSJames Wright if (PetscAbsScalar(normal[0]) > PetscAbsScalar(normal[2])) { 11076ff49feeSJames Wright label_value = PetscRealPart(normal[0]) > 0 ? faceMarkerRight : faceMarkerLeft; 11084054ae39SJames Wright } else { 11096ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 11104054ae39SJames Wright } 11114054ae39SJames Wright } else { 11126ff49feeSJames Wright if (PetscAbsScalar(normal[1]) > PetscAbsScalar(normal[2])) { 11136ff49feeSJames Wright label_value = PetscRealPart(normal[1]) > 0 ? faceMarkerBack : faceMarkerFront; 11144054ae39SJames Wright } else { 11156ff49feeSJames Wright label_value = PetscRealPart(normal[2]) > 0 ? faceMarkerTop : faceMarkerBottom; 11164054ae39SJames Wright } 11174054ae39SJames Wright } 11184054ae39SJames Wright } break; 11194054ae39SJames Wright } 11204054ae39SJames Wright 11214054ae39SJames Wright PetscInt previous_label_value; // always 1 due to DMPlexMarkBoundaryFaces call above 11224054ae39SJames Wright PetscCall(DMGetLabelValue(dm, "Face Sets", face, &previous_label_value)); 11234054ae39SJames Wright PetscCall(DMClearLabelValue(dm, "Face Sets", face, previous_label_value)); 11244054ae39SJames Wright PetscCall(DMSetLabelValue(dm, "Face Sets", face, label_value)); 11256ff49feeSJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 11264054ae39SJames Wright } 11272b4f33d9SJames Wright if (faces_is) PetscCall(ISRestoreIndices(faces_is, &faces)); 11286ff49feeSJames Wright PetscCall(ISDestroy(&faces_is)); 1129d7d2d1d2SJames Wright 1130d7d2d1d2SJames Wright // Create Isoperiodic SF from newly-created face labels 1131d7d2d1d2SJames Wright PetscSF periodicsfs[3]; 1132d7d2d1d2SJames Wright PetscInt periodic_sf_index = 0; 1133d7d2d1d2SJames Wright PetscScalar transform[3][4][4] = {{{0.}}}; 1134d7d2d1d2SJames Wright for (PetscInt d = 0; d < dim; d++) { 1135d7d2d1d2SJames Wright IS donor_is, periodic_is; 1136d7d2d1d2SJames Wright const PetscInt *donor_faces = NULL, *periodic_faces = NULL; 1137d7d2d1d2SJames Wright PetscInt num_donor = 0, num_periodic = 0; 1138d7d2d1d2SJames Wright PetscSF centroidsf; 1139d7d2d1d2SJames Wright PetscReal donor_to_periodic_distance; 1140d7d2d1d2SJames Wright const PetscInt face_pairings[2][3][2] = { 1141d7d2d1d2SJames Wright // 2D face pairings, {donor, periodic} 1142d7d2d1d2SJames Wright {{4, 2}, {1, 3}}, 1143d7d2d1d2SJames Wright // 3D face pairings 1144d7d2d1d2SJames Wright {{5, 6}, {3, 4}, {1, 2}} 1145d7d2d1d2SJames Wright }; 1146d7d2d1d2SJames Wright 1147d7d2d1d2SJames Wright if (periodicity[d] != DM_BOUNDARY_PERIODIC) continue; 1148d7d2d1d2SJames Wright { 1149d7d2d1d2SJames Wright // Compute centroidsf, which is the mapping from donor faces to periodic faces 1150d7d2d1d2SJames Wright // Matches the centroid of the faces together, ignoring the periodic direction component (which should not match between donor and periodic face) 1151d7d2d1d2SJames Wright PetscInt coords_size, centroid_comps = dim - 1; 1152d7d2d1d2SJames Wright PetscScalar *coords = NULL; 1153d7d2d1d2SJames Wright PetscReal *donor_centroids, *periodic_centroids; 1154d7d2d1d2SJames 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 1155d7d2d1d2SJames Wright 1156d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][0], &donor_is)); 1157d7d2d1d2SJames Wright PetscCall(DMGetStratumIS(dm, "Face Sets", face_pairings[dim - 2][d][1], &periodic_is)); 1158d7d2d1d2SJames Wright if (donor_is) { 1159d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(donor_is, &num_donor)); 1160d7d2d1d2SJames Wright PetscCall(ISGetIndices(donor_is, &donor_faces)); 1161d7d2d1d2SJames Wright } 1162d7d2d1d2SJames Wright if (periodic_is) { 1163d7d2d1d2SJames Wright PetscCall(ISGetLocalSize(periodic_is, &num_periodic)); 1164d7d2d1d2SJames Wright PetscCall(ISGetIndices(periodic_is, &periodic_faces)); 1165d7d2d1d2SJames Wright } 1166d7d2d1d2SJames Wright PetscCall(PetscCalloc2(num_donor * centroid_comps, &donor_centroids, num_periodic * centroid_comps, &periodic_centroids)); 1167d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_donor; f++) { 1168d7d2d1d2SJames Wright PetscInt face = donor_faces[f], num_coords; 1169d7d2d1d2SJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 1170d7d2d1d2SJames Wright num_coords = coords_size / dim; 1171d7d2d1d2SJames Wright for (PetscInt c = 0; c < num_coords; c++) { 1172d7d2d1d2SJames Wright PetscInt comp_index = 0; 1173d7d2d1d2SJames Wright loc_periodic[0] = PetscRealPart(coords[c * dim + d]); 1174d7d2d1d2SJames Wright for (PetscInt i = 0; i < dim; i++) { 1175d7d2d1d2SJames Wright if (i == d) continue; // Periodic direction not used for centroid calculation 1176d7d2d1d2SJames Wright donor_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords; 1177d7d2d1d2SJames Wright comp_index++; 1178d7d2d1d2SJames Wright } 1179d7d2d1d2SJames Wright } 1180d7d2d1d2SJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 1181d7d2d1d2SJames Wright } 1182d7d2d1d2SJames Wright 1183d7d2d1d2SJames Wright for (PetscInt f = 0; f < num_periodic; f++) { 1184d7d2d1d2SJames Wright PetscInt face = periodic_faces[f], num_coords; 1185d7d2d1d2SJames Wright PetscCall(DMPlexVecGetClosureAtDepth_Internal(cdm, csection, coordinates, face, 0, &coords_size, &coords)); 1186d7d2d1d2SJames Wright num_coords = coords_size / dim; 1187d7d2d1d2SJames Wright for (PetscInt c = 0; c < num_coords; c++) { 1188d7d2d1d2SJames Wright PetscInt comp_index = 0; 1189d7d2d1d2SJames Wright loc_periodic[1] = PetscRealPart(coords[c * dim + d]); 1190d7d2d1d2SJames Wright for (PetscInt i = 0; i < dim; i++) { 1191d7d2d1d2SJames Wright if (i == d) continue; // Periodic direction not used for centroid calculation 1192d7d2d1d2SJames Wright periodic_centroids[f * centroid_comps + comp_index] += PetscRealPart(coords[c * dim + i]) / num_coords; 1193d7d2d1d2SJames Wright comp_index++; 1194d7d2d1d2SJames Wright } 1195d7d2d1d2SJames Wright } 1196d7d2d1d2SJames Wright PetscCall(DMPlexVecRestoreClosure(cdm, csection, coordinates, face, &coords_size, &coords)); 1197d7d2d1d2SJames Wright } 1198d7d2d1d2SJames Wright PetscCallMPI(MPIU_Allreduce(loc_periodic, loc_periodic_global, 2, MPIU_REAL, MPIU_MAX, PetscObjectComm((PetscObject)dm))); 1199d7d2d1d2SJames Wright donor_to_periodic_distance = loc_periodic_global[1] - loc_periodic_global[0]; 1200d7d2d1d2SJames Wright 1201d7d2d1d2SJames Wright PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), ¢roidsf)); 1202d7d2d1d2SJames Wright PetscCall(PetscSFSetGraphFromCoordinates(centroidsf, num_donor, num_periodic, centroid_comps, 1e-10, donor_centroids, periodic_centroids)); 1203d7d2d1d2SJames Wright PetscCall(PetscSFViewFromOptions(centroidsf, NULL, "-dm_plex_box_label_centroid_sf_view")); 1204d7d2d1d2SJames Wright PetscCall(PetscFree2(donor_centroids, periodic_centroids)); 1205d7d2d1d2SJames Wright } 1206d7d2d1d2SJames Wright 1207d7d2d1d2SJames Wright { // Create Isoperiodic SF using centroidsSF 1208d7d2d1d2SJames Wright PetscInt pStart, pEnd; 1209d7d2d1d2SJames Wright PetscInt *leaf_faces; 1210d7d2d1d2SJames Wright const PetscSFNode *firemote; 1211d7d2d1d2SJames Wright PetscSFNode *isoperiodic_leaves; 1212d7d2d1d2SJames Wright 1213d7d2d1d2SJames Wright PetscCall(PetscMalloc1(num_periodic, &leaf_faces)); 1214d7d2d1d2SJames Wright PetscCall(PetscSFBcastBegin(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE)); 1215d7d2d1d2SJames Wright PetscCall(PetscSFBcastEnd(centroidsf, MPIU_INT, donor_faces, leaf_faces, MPI_REPLACE)); 1216d7d2d1d2SJames Wright 1217d7d2d1d2SJames Wright PetscCall(PetscMalloc1(num_periodic, &isoperiodic_leaves)); 1218d7d2d1d2SJames Wright PetscCall(PetscSFGetGraph(centroidsf, NULL, NULL, NULL, &firemote)); 1219d7d2d1d2SJames Wright for (PetscInt l = 0; l < num_periodic; ++l) { 1220d7d2d1d2SJames Wright isoperiodic_leaves[l].index = leaf_faces[l]; 1221d7d2d1d2SJames Wright isoperiodic_leaves[l].rank = firemote[l].rank; 1222d7d2d1d2SJames Wright } 1223d7d2d1d2SJames Wright 1224d7d2d1d2SJames Wright PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 1225d7d2d1d2SJames Wright PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), &periodicsfs[periodic_sf_index])); 1226d7d2d1d2SJames Wright PetscCall(PetscSFSetGraph(periodicsfs[periodic_sf_index], pEnd - pStart, num_periodic, (PetscInt *)periodic_faces, PETSC_COPY_VALUES, isoperiodic_leaves, PETSC_OWN_POINTER)); 1227d7d2d1d2SJames Wright PetscCall(PetscSFViewFromOptions(periodicsfs[periodic_sf_index], NULL, "-dm_plex_box_label_periodic_sf_view")); 1228d7d2d1d2SJames Wright PetscCall(PetscFree(leaf_faces)); 1229d7d2d1d2SJames Wright } 1230d7d2d1d2SJames Wright 1231d7d2d1d2SJames Wright transform[periodic_sf_index][0][0] = 1; 1232d7d2d1d2SJames Wright transform[periodic_sf_index][1][1] = 1; 1233d7d2d1d2SJames Wright transform[periodic_sf_index][2][2] = 1; 1234d7d2d1d2SJames Wright transform[periodic_sf_index][3][3] = 1; 1235d7d2d1d2SJames Wright transform[periodic_sf_index][d][3] = donor_to_periodic_distance; 1236d7d2d1d2SJames Wright 1237d7d2d1d2SJames Wright periodic_sf_index++; 1238d7d2d1d2SJames Wright PetscCall(PetscSFDestroy(¢roidsf)); 1239d7d2d1d2SJames Wright if (donor_is) { 1240d7d2d1d2SJames Wright PetscCall(ISRestoreIndices(donor_is, &donor_faces)); 1241d7d2d1d2SJames Wright PetscCall(ISDestroy(&donor_is)); 1242d7d2d1d2SJames Wright } 1243d7d2d1d2SJames Wright if (periodic_is) { 1244d7d2d1d2SJames Wright PetscCall(ISRestoreIndices(periodic_is, &periodic_faces)); 1245d7d2d1d2SJames Wright PetscCall(ISDestroy(&periodic_is)); 1246d7d2d1d2SJames Wright } 1247d7d2d1d2SJames Wright PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][0])); 1248d7d2d1d2SJames Wright PetscCall(DMClearLabelStratum(dm, "Face Sets", face_pairings[dim - 2][d][1])); 1249d7d2d1d2SJames Wright } 1250d7d2d1d2SJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(dm, periodic_sf_index, periodicsfs)); 1251d7d2d1d2SJames Wright PetscCall(DMPlexSetIsoperiodicFaceTransform(dm, periodic_sf_index, (const PetscScalar *)transform)); 1252d7d2d1d2SJames Wright for (PetscInt p = 0; p < periodic_sf_index; p++) PetscCall(PetscSFDestroy(&periodicsfs[p])); 1253d7d2d1d2SJames Wright 1254d7d2d1d2SJames Wright { // Update coordinate DM with new Face Sets label 1255d7d2d1d2SJames Wright DM cdm; 1256d7d2d1d2SJames Wright DMLabel oldFaceSets, newFaceSets; 1257d7d2d1d2SJames Wright PetscCall(DMGetCoordinateDM(dm, &cdm)); 1258d7d2d1d2SJames Wright PetscCall(DMGetLabel(cdm, "Face Sets", &oldFaceSets)); 1259d7d2d1d2SJames Wright if (oldFaceSets) PetscCall(DMRemoveLabelBySelf(cdm, &oldFaceSets, PETSC_FALSE)); 1260d7d2d1d2SJames Wright PetscCall(DMLabelDuplicate(label, &newFaceSets)); 1261d7d2d1d2SJames Wright PetscCall(DMAddLabel(cdm, newFaceSets)); 1262d7d2d1d2SJames Wright PetscCall(DMLabelDestroy(&newFaceSets)); 1263d7d2d1d2SJames Wright } 12644054ae39SJames Wright PetscFunctionReturn(PETSC_SUCCESS); 12654054ae39SJames Wright } 12664054ae39SJames Wright 1267d698cf03SStefano Zampini static PetscErrorCode DMPlexCreateSquareMesh_Simplex_CrissCross(DM dm, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType bd[]) 1268d698cf03SStefano Zampini { 1269d698cf03SStefano Zampini PetscInt markerTop = 1, faceMarkerTop = 3; 1270d698cf03SStefano Zampini PetscInt markerBottom = 1, faceMarkerBottom = 1; 1271d698cf03SStefano Zampini PetscInt markerRight = 1, faceMarkerRight = 2; 1272d698cf03SStefano Zampini PetscInt markerLeft = 1, faceMarkerLeft = 4; 1273d698cf03SStefano Zampini PetscBool markerSeparate = PETSC_FALSE; 1274d698cf03SStefano Zampini DMBoundaryType bdX = bd[0], bdY = bd[1]; 1275d698cf03SStefano Zampini PetscMPIInt rank; 1276d698cf03SStefano Zampini 1277d698cf03SStefano Zampini PetscFunctionBegin; 1278d698cf03SStefano Zampini PetscCheck(bdX == DM_BOUNDARY_NONE || bdX == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdX]); 1279d698cf03SStefano Zampini PetscCheck(bdY == DM_BOUNDARY_NONE || bdY == DM_BOUNDARY_PERIODIC, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented for boundary type %s", DMBoundaryTypes[bdY]); 1280d698cf03SStefano Zampini PetscCall(DMSetDimension(dm, 2)); 1281d698cf03SStefano Zampini PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 1282d698cf03SStefano Zampini PetscCall(DMCreateLabel(dm, "marker")); 1283d698cf03SStefano Zampini PetscCall(DMCreateLabel(dm, "Face Sets")); 1284d698cf03SStefano Zampini PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 1285d698cf03SStefano Zampini if (markerSeparate) { 1286d698cf03SStefano Zampini markerBottom = faceMarkerBottom; 1287d698cf03SStefano Zampini markerTop = faceMarkerTop; 1288d698cf03SStefano Zampini markerRight = faceMarkerRight; 1289d698cf03SStefano Zampini markerLeft = faceMarkerLeft; 1290d698cf03SStefano Zampini } 1291d698cf03SStefano Zampini { 1292d698cf03SStefano Zampini const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 1293d698cf03SStefano Zampini const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 1294d698cf03SStefano Zampini const PetscInt numZEdges = rank == 0 ? 4 * edges[0] * edges[1] : 0; /* Z-edges are the 4 internal edges per cell */ 1295d698cf03SStefano Zampini const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC ? edges[0] : edges[0] + 1) : 0; 1296d698cf03SStefano Zampini const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC ? edges[1] : edges[1] + 1) : 0; 1297d698cf03SStefano Zampini const PetscInt numZVertices = rank == 0 ? edges[0] * edges[1] : 0; 1298d698cf03SStefano Zampini const PetscInt numCells = 4 * numXEdges * numYEdges; 1299d698cf03SStefano Zampini const PetscInt numTotXEdges = numXEdges * numYVertices; 1300d698cf03SStefano Zampini const PetscInt numTotYEdges = numYEdges * numXVertices; 1301d698cf03SStefano Zampini const PetscInt numVertices = numXVertices * numYVertices + numZVertices; 1302d698cf03SStefano Zampini const PetscInt numEdges = numTotXEdges + numTotYEdges + numZEdges; 1303d698cf03SStefano Zampini const PetscInt firstVertex = numCells; 1304d698cf03SStefano Zampini const PetscInt firstXEdge = numCells + numVertices; 1305d698cf03SStefano Zampini const PetscInt firstYEdge = firstXEdge + numTotXEdges; 1306d698cf03SStefano Zampini const PetscInt firstZEdge = firstYEdge + numTotYEdges; 1307d698cf03SStefano Zampini Vec coordinates; 1308d698cf03SStefano Zampini PetscSection coordSection; 1309d698cf03SStefano Zampini PetscScalar *coords; 1310d698cf03SStefano Zampini PetscInt coordSize; 1311d698cf03SStefano Zampini PetscInt v, vx, vy; 1312d698cf03SStefano Zampini PetscInt c, e, ex, ey; 1313d698cf03SStefano Zampini 1314d698cf03SStefano Zampini PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVertices)); 1315d698cf03SStefano Zampini for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 3)); 1316d698cf03SStefano Zampini for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 1317d698cf03SStefano Zampini PetscCall(DMSetUp(dm)); 1318d698cf03SStefano Zampini 1319d698cf03SStefano Zampini /* Build cells and Z-edges */ 1320d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ++ey) { 1321d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ++ex) { 1322d698cf03SStefano Zampini const PetscInt exp1 = (ex + 1) % numXVertices; 1323d698cf03SStefano Zampini const PetscInt eyp1 = (ey + 1) % numYVertices; 1324d698cf03SStefano Zampini const PetscInt ez = firstZEdge + 4 * (ey * numXEdges + ex); 1325d698cf03SStefano Zampini const PetscInt vc = firstVertex + numXVertices * numYVertices + ey * numXEdges + ex; 1326d698cf03SStefano Zampini const PetscInt v0 = firstVertex + ey * numXVertices + ex; 1327d698cf03SStefano Zampini const PetscInt v1 = firstVertex + ey * numXVertices + exp1; 1328d698cf03SStefano Zampini const PetscInt v2 = firstVertex + eyp1 * numXVertices + exp1; 1329d698cf03SStefano Zampini const PetscInt v3 = firstVertex + eyp1 * numXVertices + ex; 1330d698cf03SStefano Zampini const PetscInt e0 = firstXEdge + ey * numXEdges + ex; 1331d698cf03SStefano Zampini const PetscInt e1 = firstYEdge + exp1 * numYEdges + ey; 1332d698cf03SStefano Zampini const PetscInt e2 = firstXEdge + eyp1 * numXEdges + ex; 1333d698cf03SStefano Zampini const PetscInt e3 = firstYEdge + ex * numYEdges + ey; 1334d698cf03SStefano Zampini 1335d698cf03SStefano Zampini const PetscInt cones[] = {ez, e0, ez + 1, ez + 1, e1, ez + 2, ez + 2, e2, ez + 3, ez + 3, e3, ez}; 1336d698cf03SStefano Zampini const PetscInt ornts[] = {-1, 0, 0, -1, 0, 0, -1, -1, 0, -1, -1, 0}; 1337d698cf03SStefano Zampini const PetscInt verts[] = {v0, vc, v1, vc, v2, vc, v3, vc}; 1338d698cf03SStefano Zampini 1339d698cf03SStefano Zampini for (c = 0; c < 4; c++) { 1340d698cf03SStefano Zampini PetscInt cell = 4 * (ey * numXEdges + ex) + c; 1341d698cf03SStefano Zampini PetscInt edge = ez + c; 1342d698cf03SStefano Zampini 1343d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, cell, cones + 3 * c)); 1344d698cf03SStefano Zampini PetscCall(DMPlexSetConeOrientation(dm, cell, ornts + 3 * c)); 1345d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, verts + 2 * c)); 1346d698cf03SStefano Zampini } 1347d698cf03SStefano Zampini } 1348d698cf03SStefano Zampini } 1349d698cf03SStefano Zampini 1350d698cf03SStefano Zampini /* Build Y edges*/ 1351d698cf03SStefano Zampini for (vx = 0; vx < numXVertices; vx++) { 1352d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ey++) { 1353d698cf03SStefano Zampini const PetscInt edge = firstYEdge + vx * numYEdges + ey; 1354d698cf03SStefano Zampini const PetscInt v0 = firstVertex + ey * numXVertices + vx; 1355d698cf03SStefano Zampini const PetscInt v1 = firstVertex + ((ey + 1) % numYVertices) * numXVertices + vx; 1356d698cf03SStefano Zampini const PetscInt cone[] = {v0, v1}; 1357d698cf03SStefano Zampini 1358d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, cone)); 1359d698cf03SStefano Zampini if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 1360d698cf03SStefano Zampini if (vx == numXVertices - 1) { 1361d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 1362d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1363d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1364d698cf03SStefano Zampini if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1365d698cf03SStefano Zampini } else if (vx == 0) { 1366d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 1367d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1368d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1369d698cf03SStefano Zampini if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 1370d698cf03SStefano Zampini } 1371d698cf03SStefano Zampini } 1372d698cf03SStefano Zampini } 1373d698cf03SStefano Zampini } 1374d698cf03SStefano Zampini 1375d698cf03SStefano Zampini /* Build X edges*/ 1376d698cf03SStefano Zampini for (vy = 0; vy < numYVertices; vy++) { 1377d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ex++) { 1378d698cf03SStefano Zampini const PetscInt edge = firstXEdge + vy * numXEdges + ex; 1379d698cf03SStefano Zampini const PetscInt v0 = firstVertex + vy * numXVertices + ex; 1380d698cf03SStefano Zampini const PetscInt v1 = firstVertex + vy * numXVertices + (ex + 1) % numXVertices; 1381d698cf03SStefano Zampini const PetscInt cone[] = {v0, v1}; 1382d698cf03SStefano Zampini 1383d698cf03SStefano Zampini PetscCall(DMPlexSetCone(dm, edge, cone)); 1384d698cf03SStefano Zampini if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 1385d698cf03SStefano Zampini if (vy == numYVertices - 1) { 1386d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 1387d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1388d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1389d698cf03SStefano Zampini if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1390d698cf03SStefano Zampini } else if (vy == 0) { 1391d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 1392d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1393d698cf03SStefano Zampini PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1394d698cf03SStefano Zampini if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 1395d698cf03SStefano Zampini } 1396d698cf03SStefano Zampini } 1397d698cf03SStefano Zampini } 1398d698cf03SStefano Zampini } 1399d698cf03SStefano Zampini 1400d698cf03SStefano Zampini /* Compute support, stratify, and celltype label */ 1401d698cf03SStefano Zampini PetscCall(DMPlexSymmetrize(dm)); 1402d698cf03SStefano Zampini PetscCall(DMPlexStratify(dm)); 1403d698cf03SStefano Zampini PetscCall(DMPlexComputeCellTypes(dm)); 1404d698cf03SStefano Zampini 1405d698cf03SStefano Zampini /* Build coordinates */ 1406d698cf03SStefano Zampini PetscCall(DMGetCoordinateSection(dm, &coordSection)); 1407d698cf03SStefano Zampini PetscCall(PetscSectionSetNumFields(coordSection, 1)); 1408d698cf03SStefano Zampini PetscCall(PetscSectionSetFieldComponents(coordSection, 0, 2)); 1409d698cf03SStefano Zampini PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 1410d698cf03SStefano Zampini for (v = firstVertex; v < firstVertex + numVertices; ++v) { 1411d698cf03SStefano Zampini PetscCall(PetscSectionSetDof(coordSection, v, 2)); 1412d698cf03SStefano Zampini PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, 2)); 1413d698cf03SStefano Zampini } 1414d698cf03SStefano Zampini PetscCall(PetscSectionSetUp(coordSection)); 1415d698cf03SStefano Zampini PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 1416d698cf03SStefano Zampini PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 1417d698cf03SStefano Zampini PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 1418d698cf03SStefano Zampini PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 1419d698cf03SStefano Zampini PetscCall(VecSetBlockSize(coordinates, 2)); 1420d698cf03SStefano Zampini PetscCall(VecSetType(coordinates, VECSTANDARD)); 1421d698cf03SStefano Zampini PetscCall(VecGetArray(coordinates, &coords)); 1422d698cf03SStefano Zampini for (vy = 0; vy < numYVertices; ++vy) { 1423d698cf03SStefano Zampini for (vx = 0; vx < numXVertices; ++vx) { 1424d698cf03SStefano Zampini coords[2 * (vy * numXVertices + vx) + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 1425d698cf03SStefano Zampini coords[2 * (vy * numXVertices + vx) + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1426d698cf03SStefano Zampini } 1427d698cf03SStefano Zampini } 1428d698cf03SStefano Zampini for (ey = 0; ey < numYEdges; ++ey) { 1429d698cf03SStefano Zampini for (ex = 0; ex < numXEdges; ++ex) { 1430d698cf03SStefano Zampini const PetscInt c = ey * numXEdges + ex + numYVertices * numXVertices; 1431d698cf03SStefano Zampini 1432d698cf03SStefano Zampini coords[2 * c + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * (ex + 0.5); 1433d698cf03SStefano Zampini coords[2 * c + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * (ey + 0.5); 1434d698cf03SStefano Zampini } 1435d698cf03SStefano Zampini } 1436d698cf03SStefano Zampini PetscCall(VecRestoreArray(coordinates, &coords)); 1437d698cf03SStefano Zampini PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 1438d698cf03SStefano Zampini PetscCall(VecDestroy(&coordinates)); 1439d698cf03SStefano Zampini 1440d698cf03SStefano Zampini /* handle periodic BC */ 1441d698cf03SStefano Zampini if (bdX == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_PERIODIC) { 1442d698cf03SStefano Zampini PetscReal L[2] = {-1., -1.}; 1443d698cf03SStefano Zampini PetscReal maxCell[2] = {-1., -1.}; 1444d698cf03SStefano Zampini 1445d698cf03SStefano Zampini for (PetscInt d = 0; d < 2; ++d) { 1446d698cf03SStefano Zampini if (bd[d] != DM_BOUNDARY_NONE) { 1447d698cf03SStefano Zampini L[d] = upper[d] - lower[d]; 1448d698cf03SStefano Zampini maxCell[d] = 1.1 * (L[d] / PetscMax(1, edges[d])); 1449d698cf03SStefano Zampini } 1450d698cf03SStefano Zampini } 1451d698cf03SStefano Zampini PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1452d698cf03SStefano Zampini } 1453d698cf03SStefano Zampini } 1454d698cf03SStefano Zampini PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 1455d698cf03SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1456d698cf03SStefano Zampini } 1457d698cf03SStefano Zampini 1458d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Simplex_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool interpolate) 1459d71ae5a4SJacob Faibussowitsch { 14609318fe57SMatthew G. Knepley DM boundary, vol; 1461c22d3578SMatthew G. Knepley DMLabel bdlabel; 1462d698cf03SStefano Zampini PetscBool crisscross = PETSC_FALSE; 1463d6218766SMatthew G. Knepley 1464d6218766SMatthew G. Knepley PetscFunctionBegin; 14654f572ea9SToby Isaac PetscAssertPointer(dm, 1); 1466d698cf03SStefano Zampini if (dim == 2) PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_box_crisscross", &crisscross, NULL)); 1467d698cf03SStefano Zampini if (crisscross) { 1468d698cf03SStefano Zampini PetscCall(DMPlexCreateSquareMesh_Simplex_CrissCross(dm, faces, lower, upper, periodicity)); 1469d698cf03SStefano Zampini } else { 1470c22d3578SMatthew 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"); 14719566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &boundary)); 14729566063dSJacob Faibussowitsch PetscCall(DMSetType(boundary, DMPLEX)); 1473d698cf03SStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)boundary, ((PetscObject)dm)->prefix)); 14749566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(boundary, dim, faces, lower, upper, PETSC_FALSE)); 14759566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(boundary, NULL, interpolate, &vol)); 1476c22d3578SMatthew G. Knepley PetscCall(DMGetLabel(vol, "marker", &bdlabel)); 1477c22d3578SMatthew G. Knepley if (bdlabel) PetscCall(DMPlexLabelComplete(vol, bdlabel)); 14785de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, PETSC_FALSE, vol)); 147969d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 1480d698cf03SStefano Zampini PetscCall(DMDestroy(&boundary)); 1481d698cf03SStefano Zampini } 14824054ae39SJames Wright if (interpolate) { 14834054ae39SJames Wright PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 1484d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, periodicity)); 14854054ae39SJames Wright } 14863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1487d6218766SMatthew G. Knepley } 1488d6218766SMatthew G. Knepley 1489d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCubeMesh_Internal(DM dm, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], DMBoundaryType bdX, DMBoundaryType bdY, DMBoundaryType bdZ) 1490d71ae5a4SJacob Faibussowitsch { 1491ed0e4b50SMatthew G. Knepley DMLabel cutLabel = NULL; 1492f4eb4c5dSMatthew G. Knepley PetscInt markerTop = 1, faceMarkerTop = 1; 1493f4eb4c5dSMatthew G. Knepley PetscInt markerBottom = 1, faceMarkerBottom = 1; 1494f4eb4c5dSMatthew G. Knepley PetscInt markerFront = 1, faceMarkerFront = 1; 1495f4eb4c5dSMatthew G. Knepley PetscInt markerBack = 1, faceMarkerBack = 1; 1496f4eb4c5dSMatthew G. Knepley PetscInt markerRight = 1, faceMarkerRight = 1; 1497f4eb4c5dSMatthew G. Knepley PetscInt markerLeft = 1, faceMarkerLeft = 1; 14983dfda0b1SToby Isaac PetscInt dim; 1499d8211ee3SMatthew G. Knepley PetscBool markerSeparate = PETSC_FALSE, cutMarker = PETSC_FALSE; 15003dfda0b1SToby Isaac PetscMPIInt rank; 15013dfda0b1SToby Isaac 15023dfda0b1SToby Isaac PetscFunctionBegin; 15039566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 15049566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 15059566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 15069566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 15079566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 15089371c9d4SSatish 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) { 15099371c9d4SSatish Balay if (cutMarker) { 15109371c9d4SSatish Balay PetscCall(DMCreateLabel(dm, "periodic_cut")); 15119371c9d4SSatish Balay PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 15129371c9d4SSatish Balay } 1513d8211ee3SMatthew G. Knepley } 15143dfda0b1SToby Isaac switch (dim) { 15153dfda0b1SToby Isaac case 2: 1516f4eb4c5dSMatthew G. Knepley faceMarkerTop = 3; 1517f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1518f4eb4c5dSMatthew G. Knepley faceMarkerRight = 2; 1519f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 4; 15203dfda0b1SToby Isaac break; 15213dfda0b1SToby Isaac case 3: 1522f4eb4c5dSMatthew G. Knepley faceMarkerBottom = 1; 1523f4eb4c5dSMatthew G. Knepley faceMarkerTop = 2; 1524f4eb4c5dSMatthew G. Knepley faceMarkerFront = 3; 1525f4eb4c5dSMatthew G. Knepley faceMarkerBack = 4; 1526f4eb4c5dSMatthew G. Knepley faceMarkerRight = 5; 1527f4eb4c5dSMatthew G. Knepley faceMarkerLeft = 6; 15283dfda0b1SToby Isaac break; 1529d71ae5a4SJacob Faibussowitsch default: 1530d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Dimension %" PetscInt_FMT " not supported", dim); 15313dfda0b1SToby Isaac } 15329566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_separate_marker", &markerSeparate, NULL)); 1533f4eb4c5dSMatthew G. Knepley if (markerSeparate) { 1534f4eb4c5dSMatthew G. Knepley markerBottom = faceMarkerBottom; 1535f4eb4c5dSMatthew G. Knepley markerTop = faceMarkerTop; 1536f4eb4c5dSMatthew G. Knepley markerFront = faceMarkerFront; 1537f4eb4c5dSMatthew G. Knepley markerBack = faceMarkerBack; 1538f4eb4c5dSMatthew G. Knepley markerRight = faceMarkerRight; 1539f4eb4c5dSMatthew G. Knepley markerLeft = faceMarkerLeft; 15403dfda0b1SToby Isaac } 15413dfda0b1SToby Isaac { 1542dd400576SPatrick Sanan const PetscInt numXEdges = rank == 0 ? edges[0] : 0; 1543dd400576SPatrick Sanan const PetscInt numYEdges = rank == 0 ? edges[1] : 0; 1544dd400576SPatrick Sanan const PetscInt numZEdges = rank == 0 ? edges[2] : 0; 1545dd400576SPatrick Sanan const PetscInt numXVertices = rank == 0 ? (bdX == DM_BOUNDARY_PERIODIC || bdX == DM_BOUNDARY_TWIST ? edges[0] : edges[0] + 1) : 0; 1546dd400576SPatrick Sanan const PetscInt numYVertices = rank == 0 ? (bdY == DM_BOUNDARY_PERIODIC || bdY == DM_BOUNDARY_TWIST ? edges[1] : edges[1] + 1) : 0; 1547dd400576SPatrick Sanan const PetscInt numZVertices = rank == 0 ? (bdZ == DM_BOUNDARY_PERIODIC || bdZ == DM_BOUNDARY_TWIST ? edges[2] : edges[2] + 1) : 0; 15483dfda0b1SToby Isaac const PetscInt numCells = numXEdges * numYEdges * numZEdges; 15493dfda0b1SToby Isaac const PetscInt numXFaces = numYEdges * numZEdges; 15503dfda0b1SToby Isaac const PetscInt numYFaces = numXEdges * numZEdges; 15513dfda0b1SToby Isaac const PetscInt numZFaces = numXEdges * numYEdges; 15523dfda0b1SToby Isaac const PetscInt numTotXFaces = numXVertices * numXFaces; 15533dfda0b1SToby Isaac const PetscInt numTotYFaces = numYVertices * numYFaces; 15543dfda0b1SToby Isaac const PetscInt numTotZFaces = numZVertices * numZFaces; 15553dfda0b1SToby Isaac const PetscInt numFaces = numTotXFaces + numTotYFaces + numTotZFaces; 15563dfda0b1SToby Isaac const PetscInt numTotXEdges = numXEdges * numYVertices * numZVertices; 15573dfda0b1SToby Isaac const PetscInt numTotYEdges = numYEdges * numXVertices * numZVertices; 15583dfda0b1SToby Isaac const PetscInt numTotZEdges = numZEdges * numXVertices * numYVertices; 15593dfda0b1SToby Isaac const PetscInt numVertices = numXVertices * numYVertices * numZVertices; 15603dfda0b1SToby Isaac const PetscInt numEdges = numTotXEdges + numTotYEdges + numTotZEdges; 15613dfda0b1SToby Isaac const PetscInt firstVertex = (dim == 2) ? numFaces : numCells; 15623dfda0b1SToby Isaac const PetscInt firstXFace = (dim == 2) ? 0 : numCells + numVertices; 15633dfda0b1SToby Isaac const PetscInt firstYFace = firstXFace + numTotXFaces; 15643dfda0b1SToby Isaac const PetscInt firstZFace = firstYFace + numTotYFaces; 15653dfda0b1SToby Isaac const PetscInt firstXEdge = numCells + numFaces + numVertices; 15663dfda0b1SToby Isaac const PetscInt firstYEdge = firstXEdge + numTotXEdges; 15673dfda0b1SToby Isaac const PetscInt firstZEdge = firstYEdge + numTotYEdges; 15683dfda0b1SToby Isaac Vec coordinates; 15693dfda0b1SToby Isaac PetscSection coordSection; 15703dfda0b1SToby Isaac PetscScalar *coords; 15713dfda0b1SToby Isaac PetscInt coordSize; 15723dfda0b1SToby Isaac PetscInt v, vx, vy, vz; 15733dfda0b1SToby Isaac PetscInt c, f, fx, fy, fz, e, ex, ey, ez; 15743dfda0b1SToby Isaac 15759566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numFaces + numEdges + numVertices)); 157648a46eb9SPierre Jolivet for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 157748a46eb9SPierre Jolivet for (f = firstXFace; f < firstXFace + numFaces; ++f) PetscCall(DMPlexSetConeSize(dm, f, 4)); 157848a46eb9SPierre Jolivet for (e = firstXEdge; e < firstXEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 15799566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 15803dfda0b1SToby Isaac /* Build cells */ 15813dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 15823dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 15833dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 15843dfda0b1SToby Isaac PetscInt cell = (fz * numYEdges + fy) * numXEdges + fx; 15853dfda0b1SToby Isaac PetscInt faceB = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 15863dfda0b1SToby Isaac PetscInt faceT = firstZFace + (fy * numXEdges + fx) * numZVertices + ((fz + 1) % numZVertices); 15873dfda0b1SToby Isaac PetscInt faceF = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 15883dfda0b1SToby Isaac PetscInt faceK = firstYFace + (fz * numXEdges + fx) * numYVertices + ((fy + 1) % numYVertices); 15893dfda0b1SToby Isaac PetscInt faceL = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 15903dfda0b1SToby Isaac PetscInt faceR = firstXFace + (fz * numYEdges + fy) * numXVertices + ((fx + 1) % numXVertices); 15913dfda0b1SToby Isaac /* B, T, F, K, R, L */ 1592b5a892a1SMatthew G. Knepley PetscInt ornt[6] = {-2, 0, 0, -3, 0, -2}; /* ??? */ 159342206facSLisandro Dalcin PetscInt cone[6]; 15943dfda0b1SToby Isaac 15953dfda0b1SToby Isaac /* no boundary twisting in 3D */ 15969371c9d4SSatish Balay cone[0] = faceB; 15979371c9d4SSatish Balay cone[1] = faceT; 15989371c9d4SSatish Balay cone[2] = faceF; 15999371c9d4SSatish Balay cone[3] = faceK; 16009371c9d4SSatish Balay cone[4] = faceR; 16019371c9d4SSatish Balay cone[5] = faceL; 16029566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, cell, cone)); 16039566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, cell, ornt)); 16049566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 16059566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 16069566063dSJacob Faibussowitsch if (bdZ != DM_BOUNDARY_NONE && fz == numZEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, cell, 2)); 16073dfda0b1SToby Isaac } 16083dfda0b1SToby Isaac } 16093dfda0b1SToby Isaac } 16103dfda0b1SToby Isaac /* Build x faces */ 16113dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 16123dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 16133dfda0b1SToby Isaac for (fx = 0; fx < numXVertices; ++fx) { 16143dfda0b1SToby Isaac PetscInt face = firstXFace + (fz * numYEdges + fy) * numXVertices + fx; 16153dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 16163dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (((fy + 1) % numYVertices) * numXVertices + fx) * numZEdges + fz; 16173dfda0b1SToby Isaac PetscInt edgeB = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 16183dfda0b1SToby Isaac PetscInt edgeT = firstYEdge + (((fz + 1) % numZVertices) * numXVertices + fx) * numYEdges + fy; 1619b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16203dfda0b1SToby Isaac PetscInt cone[4]; 16213dfda0b1SToby Isaac 16223dfda0b1SToby Isaac if (dim == 3) { 16233dfda0b1SToby Isaac /* markers */ 16243dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 16253dfda0b1SToby Isaac if (fx == numXVertices - 1) { 16269566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerRight)); 16279566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerRight)); 16289371c9d4SSatish Balay } else if (fx == 0) { 16299566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerLeft)); 16309566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerLeft)); 16313dfda0b1SToby Isaac } 16323dfda0b1SToby Isaac } 16333dfda0b1SToby Isaac } 16349371c9d4SSatish Balay cone[0] = edgeB; 16359371c9d4SSatish Balay cone[1] = edgeR; 16369371c9d4SSatish Balay cone[2] = edgeT; 16379371c9d4SSatish Balay cone[3] = edgeL; 16389566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 16399566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 16403dfda0b1SToby Isaac } 16413dfda0b1SToby Isaac } 16423dfda0b1SToby Isaac } 16433dfda0b1SToby Isaac /* Build y faces */ 16443dfda0b1SToby Isaac for (fz = 0; fz < numZEdges; ++fz) { 164542206facSLisandro Dalcin for (fx = 0; fx < numXEdges; ++fx) { 16463dfda0b1SToby Isaac for (fy = 0; fy < numYVertices; ++fy) { 16473dfda0b1SToby Isaac PetscInt face = firstYFace + (fz * numXEdges + fx) * numYVertices + fy; 16483dfda0b1SToby Isaac PetscInt edgeL = firstZEdge + (fy * numXVertices + fx) * numZEdges + fz; 16493dfda0b1SToby Isaac PetscInt edgeR = firstZEdge + (fy * numXVertices + ((fx + 1) % numXVertices)) * numZEdges + fz; 16503dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 16513dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (((fz + 1) % numZVertices) * numYVertices + fy) * numXEdges + fx; 1652b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16533dfda0b1SToby Isaac PetscInt cone[4]; 16543dfda0b1SToby Isaac 16553dfda0b1SToby Isaac if (dim == 3) { 16563dfda0b1SToby Isaac /* markers */ 16573dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 16583dfda0b1SToby Isaac if (fy == numYVertices - 1) { 16599566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBack)); 16609566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBack)); 16619371c9d4SSatish Balay } else if (fy == 0) { 16629566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerFront)); 16639566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerFront)); 16643dfda0b1SToby Isaac } 16653dfda0b1SToby Isaac } 16663dfda0b1SToby Isaac } 16679371c9d4SSatish Balay cone[0] = edgeB; 16689371c9d4SSatish Balay cone[1] = edgeR; 16699371c9d4SSatish Balay cone[2] = edgeT; 16709371c9d4SSatish Balay cone[3] = edgeL; 16719566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 16729566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 16733dfda0b1SToby Isaac } 16743dfda0b1SToby Isaac } 16753dfda0b1SToby Isaac } 16763dfda0b1SToby Isaac /* Build z faces */ 16773dfda0b1SToby Isaac for (fy = 0; fy < numYEdges; ++fy) { 16783dfda0b1SToby Isaac for (fx = 0; fx < numXEdges; ++fx) { 16793dfda0b1SToby Isaac for (fz = 0; fz < numZVertices; fz++) { 16803dfda0b1SToby Isaac PetscInt face = firstZFace + (fy * numXEdges + fx) * numZVertices + fz; 16813dfda0b1SToby Isaac PetscInt edgeL = firstYEdge + (fz * numXVertices + fx) * numYEdges + fy; 16823dfda0b1SToby Isaac PetscInt edgeR = firstYEdge + (fz * numXVertices + ((fx + 1) % numXVertices)) * numYEdges + fy; 16833dfda0b1SToby Isaac PetscInt edgeB = firstXEdge + (fz * numYVertices + fy) * numXEdges + fx; 16843dfda0b1SToby Isaac PetscInt edgeT = firstXEdge + (fz * numYVertices + ((fy + 1) % numYVertices)) * numXEdges + fx; 1685b5a892a1SMatthew G. Knepley PetscInt ornt[4] = {0, 0, -1, -1}; 16863dfda0b1SToby Isaac PetscInt cone[4]; 16873dfda0b1SToby Isaac 16883dfda0b1SToby Isaac if (dim == 2) { 16899371c9d4SSatish Balay if (bdX == DM_BOUNDARY_TWIST && fx == numXEdges - 1) { 16909371c9d4SSatish Balay edgeR += numYEdges - 1 - 2 * fy; 16919371c9d4SSatish Balay ornt[1] = -1; 16929371c9d4SSatish Balay } 16939371c9d4SSatish Balay if (bdY == DM_BOUNDARY_TWIST && fy == numYEdges - 1) { 16949371c9d4SSatish Balay edgeT += numXEdges - 1 - 2 * fx; 16959371c9d4SSatish Balay ornt[2] = 0; 16969371c9d4SSatish Balay } 16979566063dSJacob Faibussowitsch if (bdX != DM_BOUNDARY_NONE && fx == numXEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 16989566063dSJacob Faibussowitsch if (bdY != DM_BOUNDARY_NONE && fy == numYEdges - 1 && cutLabel) PetscCall(DMLabelSetValue(cutLabel, face, 2)); 1699d1c88043SMatthew G. Knepley } else { 17003dfda0b1SToby Isaac /* markers */ 17013dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 17023dfda0b1SToby Isaac if (fz == numZVertices - 1) { 17039566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerTop)); 17049566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerTop)); 17059371c9d4SSatish Balay } else if (fz == 0) { 17069566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", face, faceMarkerBottom)); 17079566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", face, markerBottom)); 17083dfda0b1SToby Isaac } 17093dfda0b1SToby Isaac } 17103dfda0b1SToby Isaac } 17119371c9d4SSatish Balay cone[0] = edgeB; 17129371c9d4SSatish Balay cone[1] = edgeR; 17139371c9d4SSatish Balay cone[2] = edgeT; 17149371c9d4SSatish Balay cone[3] = edgeL; 17159566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, face, cone)); 17169566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, face, ornt)); 17173dfda0b1SToby Isaac } 17183dfda0b1SToby Isaac } 17193dfda0b1SToby Isaac } 17203dfda0b1SToby Isaac /* Build Z edges*/ 17213dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 17223dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 17233dfda0b1SToby Isaac for (ez = 0; ez < numZEdges; ez++) { 17243dfda0b1SToby Isaac const PetscInt edge = firstZEdge + (vy * numXVertices + vx) * numZEdges + ez; 17253dfda0b1SToby Isaac const PetscInt vertexB = firstVertex + (ez * numYVertices + vy) * numXVertices + vx; 17263dfda0b1SToby Isaac const PetscInt vertexT = firstVertex + (((ez + 1) % numZVertices) * numYVertices + vy) * numXVertices + vx; 17273dfda0b1SToby Isaac PetscInt cone[2]; 17283dfda0b1SToby Isaac 17299371c9d4SSatish Balay cone[0] = vertexB; 17309371c9d4SSatish Balay cone[1] = vertexT; 1731c2df9bbfSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, edge, cone)); 17323dfda0b1SToby Isaac if (dim == 3) { 17333dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 17343dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17359566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1736c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1737c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1738c2df9bbfSMatthew G. Knepley } else if (vx == 0) { 17399566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1740c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1741c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 17423dfda0b1SToby Isaac } 17433dfda0b1SToby Isaac } 17443dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 17453dfda0b1SToby Isaac if (vy == numYVertices - 1) { 17469566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1747c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1748c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1749c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 17509566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1751c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1752c2df9bbfSMatthew G. Knepley if (ez == numZEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 17533dfda0b1SToby Isaac } 17543dfda0b1SToby Isaac } 17553dfda0b1SToby Isaac } 17563dfda0b1SToby Isaac } 17573dfda0b1SToby Isaac } 17583dfda0b1SToby Isaac } 17593dfda0b1SToby Isaac /* Build Y edges*/ 17603dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 17613dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; vx++) { 17623dfda0b1SToby Isaac for (ey = 0; ey < numYEdges; ey++) { 17633dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdY == DM_BOUNDARY_TWIST && ey == numYEdges - 1) ? (numXVertices - vx - 1) : (vz * numYVertices + ((ey + 1) % numYVertices)) * numXVertices + vx; 17643dfda0b1SToby Isaac const PetscInt edge = firstYEdge + (vz * numXVertices + vx) * numYEdges + ey; 17653dfda0b1SToby Isaac const PetscInt vertexF = firstVertex + (vz * numYVertices + ey) * numXVertices + vx; 17663dfda0b1SToby Isaac const PetscInt vertexK = firstVertex + nextv; 17673dfda0b1SToby Isaac PetscInt cone[2]; 17683dfda0b1SToby Isaac 17699371c9d4SSatish Balay cone[0] = vertexF; 17709371c9d4SSatish Balay cone[1] = vertexK; 17719566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 17723dfda0b1SToby Isaac if (dim == 2) { 17733dfda0b1SToby Isaac if ((bdX != DM_BOUNDARY_PERIODIC) && (bdX != DM_BOUNDARY_TWIST)) { 17743dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17759566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerRight)); 17769566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 17779566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1778c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1779d8211ee3SMatthew G. Knepley } else if (vx == 0) { 17809566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerLeft)); 17819566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 17829566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1783c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 17843dfda0b1SToby Isaac } 1785d8211ee3SMatthew G. Knepley } else { 17864c67ea77SStefano Zampini if (vx == 0 && cutLabel) { 17879566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 17889566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1789c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 17903dfda0b1SToby Isaac } 1791d8211ee3SMatthew G. Knepley } 1792d8211ee3SMatthew G. Knepley } else { 17933dfda0b1SToby Isaac if (bdX != DM_BOUNDARY_PERIODIC) { 17943dfda0b1SToby Isaac if (vx == numXVertices - 1) { 17959566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerRight)); 1796c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerRight)); 1797c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerRight)); 1798d8211ee3SMatthew G. Knepley } else if (vx == 0) { 17999566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerLeft)); 1800c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerLeft)); 1801c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerLeft)); 18023dfda0b1SToby Isaac } 18033dfda0b1SToby Isaac } 18043dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 18053dfda0b1SToby Isaac if (vz == numZVertices - 1) { 18069566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1807c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1808c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1809d8211ee3SMatthew G. Knepley } else if (vz == 0) { 18109566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1811c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1812c2df9bbfSMatthew G. Knepley if (ey == numYEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 18133dfda0b1SToby Isaac } 18143dfda0b1SToby Isaac } 18153dfda0b1SToby Isaac } 18163dfda0b1SToby Isaac } 18173dfda0b1SToby Isaac } 18183dfda0b1SToby Isaac } 18193dfda0b1SToby Isaac /* Build X edges*/ 18203dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; vz++) { 18213dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; vy++) { 18223dfda0b1SToby Isaac for (ex = 0; ex < numXEdges; ex++) { 18233dfda0b1SToby Isaac const PetscInt nextv = (dim == 2 && bdX == DM_BOUNDARY_TWIST && ex == numXEdges - 1) ? (numYVertices - vy - 1) * numXVertices : (vz * numYVertices + vy) * numXVertices + (ex + 1) % numXVertices; 18243dfda0b1SToby Isaac const PetscInt edge = firstXEdge + (vz * numYVertices + vy) * numXEdges + ex; 18253dfda0b1SToby Isaac const PetscInt vertexL = firstVertex + (vz * numYVertices + vy) * numXVertices + ex; 18263dfda0b1SToby Isaac const PetscInt vertexR = firstVertex + nextv; 18273dfda0b1SToby Isaac PetscInt cone[2]; 18283dfda0b1SToby Isaac 18299371c9d4SSatish Balay cone[0] = vertexL; 18309371c9d4SSatish Balay cone[1] = vertexR; 18319566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, edge, cone)); 18323dfda0b1SToby Isaac if (dim == 2) { 18333dfda0b1SToby Isaac if ((bdY != DM_BOUNDARY_PERIODIC) && (bdY != DM_BOUNDARY_TWIST)) { 18343dfda0b1SToby Isaac if (vy == numYVertices - 1) { 18359566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerTop)); 18369566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 18379566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1838c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1839d8211ee3SMatthew G. Knepley } else if (vy == 0) { 18409566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "Face Sets", edge, faceMarkerBottom)); 18419566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 18429566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1843c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 18443dfda0b1SToby Isaac } 1845d8211ee3SMatthew G. Knepley } else { 18464c67ea77SStefano Zampini if (vy == 0 && cutLabel) { 18479566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, edge, 1)); 18489566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(cutLabel, cone[0], 1)); 1849c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMLabelSetValue(cutLabel, cone[1], 1)); 18503dfda0b1SToby Isaac } 1851d8211ee3SMatthew G. Knepley } 1852d8211ee3SMatthew G. Knepley } else { 18533dfda0b1SToby Isaac if (bdY != DM_BOUNDARY_PERIODIC) { 18543dfda0b1SToby Isaac if (vy == numYVertices - 1) { 18559566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBack)); 1856c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBack)); 1857c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBack)); 1858c2df9bbfSMatthew G. Knepley } else if (vy == 0) { 18599566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerFront)); 1860c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerFront)); 1861c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerFront)); 18623dfda0b1SToby Isaac } 18633dfda0b1SToby Isaac } 18643dfda0b1SToby Isaac if (bdZ != DM_BOUNDARY_PERIODIC) { 18653dfda0b1SToby Isaac if (vz == numZVertices - 1) { 18669566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerTop)); 1867c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerTop)); 1868c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerTop)); 1869c2df9bbfSMatthew G. Knepley } else if (vz == 0) { 18709566063dSJacob Faibussowitsch PetscCall(DMSetLabelValue(dm, "marker", edge, markerBottom)); 1871c2df9bbfSMatthew G. Knepley PetscCall(DMSetLabelValue(dm, "marker", cone[0], markerBottom)); 1872c2df9bbfSMatthew G. Knepley if (ex == numXEdges - 1) PetscCall(DMSetLabelValue(dm, "marker", cone[1], markerBottom)); 18733dfda0b1SToby Isaac } 18743dfda0b1SToby Isaac } 18753dfda0b1SToby Isaac } 18763dfda0b1SToby Isaac } 18773dfda0b1SToby Isaac } 18783dfda0b1SToby Isaac } 18799566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 18809566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 18813dfda0b1SToby Isaac /* Build coordinates */ 18829566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 18839566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 18849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 18859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVertices)); 18863dfda0b1SToby Isaac for (v = firstVertex; v < firstVertex + numVertices; ++v) { 18879566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 18889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 18893dfda0b1SToby Isaac } 18909566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 18919566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 18929566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 18939566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 18949566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 18959566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 18969566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 18979566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 18983dfda0b1SToby Isaac for (vz = 0; vz < numZVertices; ++vz) { 18993dfda0b1SToby Isaac for (vy = 0; vy < numYVertices; ++vy) { 19003dfda0b1SToby Isaac for (vx = 0; vx < numXVertices; ++vx) { 19013dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 0] = lower[0] + ((upper[0] - lower[0]) / numXEdges) * vx; 19023dfda0b1SToby Isaac coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 1] = lower[1] + ((upper[1] - lower[1]) / numYEdges) * vy; 1903ad540459SPierre Jolivet if (dim == 3) coords[((vz * numYVertices + vy) * numXVertices + vx) * dim + 2] = lower[2] + ((upper[2] - lower[2]) / numZEdges) * vz; 19043dfda0b1SToby Isaac } 19053dfda0b1SToby Isaac } 19063dfda0b1SToby Isaac } 19079566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 19089566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 19099566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 19103dfda0b1SToby Isaac } 19113ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19123dfda0b1SToby Isaac } 19133dfda0b1SToby Isaac 1914d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoxMesh_Tensor_Internal(DM dm, PetscInt dim, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 1915d71ae5a4SJacob Faibussowitsch { 19169318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 19179318fe57SMatthew G. Knepley PetscInt fac[3] = {0, 0, 0}, d; 1918552f7358SJed Brown 1919552f7358SJed Brown PetscFunctionBegin; 19204f572ea9SToby Isaac PetscAssertPointer(dm, 1); 19219318fe57SMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, dim, 2); 19229566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 19239371c9d4SSatish Balay for (d = 0; d < dim; ++d) { 19249371c9d4SSatish Balay fac[d] = faces[d]; 19259371c9d4SSatish Balay bdt[d] = periodicity[d]; 19269371c9d4SSatish Balay } 19279566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCubeMesh_Internal(dm, lower, upper, fac, bdt[0], bdt[1], bdt[2])); 19289371c9d4SSatish 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))) { 19296858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 19306858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 1931552f7358SJed Brown 19329318fe57SMatthew G. Knepley for (d = 0; d < dim; ++d) { 19336858538eSMatthew G. Knepley if (periodicity[d] != DM_BOUNDARY_NONE) { 19349318fe57SMatthew G. Knepley L[d] = upper[d] - lower[d]; 19359318fe57SMatthew G. Knepley maxCell[d] = 1.1 * (L[d] / PetscMax(1, faces[d])); 1936768d5fceSMatthew G. Knepley } 19376858538eSMatthew G. Knepley } 19384fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 1939768d5fceSMatthew G. Knepley } 19409566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 19413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 19429318fe57SMatthew G. Knepley } 19439318fe57SMatthew G. Knepley 19445dca41c3SJed 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) 1945d71ae5a4SJacob Faibussowitsch { 19469318fe57SMatthew G. Knepley PetscFunctionBegin; 194746139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 19485dca41c3SJed Brown if (shape == DM_SHAPE_ZBOX) PetscCall(DMPlexCreateBoxMesh_Tensor_SFC_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 19496725e60dSJed Brown else if (dim == 1) PetscCall(DMPlexCreateLineMesh_Internal(dm, faces[0], lower[0], upper[0], periodicity[0])); 19509566063dSJacob Faibussowitsch else if (simplex) PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(dm, dim, faces, lower, upper, periodicity, interpolate)); 19519566063dSJacob Faibussowitsch else PetscCall(DMPlexCreateBoxMesh_Tensor_Internal(dm, dim, faces, lower, upper, periodicity)); 19529318fe57SMatthew G. Knepley if (!interpolate && dim > 1 && !simplex) { 1953768d5fceSMatthew G. Knepley DM udm; 1954768d5fceSMatthew G. Knepley 19559566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 19569566063dSJacob Faibussowitsch PetscCall(DMPlexCopyCoordinates(dm, udm)); 195769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 1958768d5fceSMatthew G. Knepley } 195946139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 19603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 1961c8c68bd8SToby Isaac } 1962c8c68bd8SToby Isaac 19635d83a8b1SBarry Smith /*@ 1964768d5fceSMatthew G. Knepley DMPlexCreateBoxMesh - Creates a mesh on the tensor product of unit intervals (box) using simplices or tensor cells (hexahedra). 1965768d5fceSMatthew G. Knepley 1966d083f849SBarry Smith Collective 1967768d5fceSMatthew G. Knepley 1968768d5fceSMatthew G. Knepley Input Parameters: 1969a1cb98faSBarry Smith + comm - The communicator for the `DM` object 1970768d5fceSMatthew G. Knepley . dim - The spatial dimension 1971a1cb98faSBarry Smith . simplex - `PETSC_TRUE` for simplices, `PETSC_FALSE` for tensor cells 197220f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 197320f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 197420f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 197520f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 197642108689Sksagiyam . interpolate - Flag to create intermediate mesh pieces (edges, faces) 197742108689Sksagiyam . localizationHeight - Flag to localize edges and faces in addition to cells; only significant for periodic meshes 197842108689Sksagiyam - sparseLocalize - Flag to localize coordinates only for cells near the periodic boundary; only significant for periodic meshes 1979768d5fceSMatthew G. Knepley 1980768d5fceSMatthew G. Knepley Output Parameter: 1981a1cb98faSBarry Smith . dm - The `DM` object 1982768d5fceSMatthew G. Knepley 1983768d5fceSMatthew G. Knepley Level: beginner 1984768d5fceSMatthew G. Knepley 1985a1cb98faSBarry Smith Note: 1986a1cb98faSBarry Smith To customize this mesh using options, use 1987a1cb98faSBarry Smith .vb 1988a1cb98faSBarry Smith DMCreate(comm, &dm); 1989a1cb98faSBarry Smith DMSetType(dm, DMPLEX); 1990a1cb98faSBarry Smith DMSetFromOptions(dm); 1991a1cb98faSBarry Smith .ve 1992a1cb98faSBarry Smith and use the options in `DMSetFromOptions()`. 1993a1cb98faSBarry Smith 1994a4e35b19SJacob Faibussowitsch Here is the numbering returned for 2 faces in each direction for tensor cells\: 1995a1cb98faSBarry Smith .vb 1996a1cb98faSBarry Smith 10---17---11---18----12 1997a1cb98faSBarry Smith | | | 1998a1cb98faSBarry Smith | | | 1999a1cb98faSBarry Smith 20 2 22 3 24 2000a1cb98faSBarry Smith | | | 2001a1cb98faSBarry Smith | | | 2002a1cb98faSBarry Smith 7---15----8---16----9 2003a1cb98faSBarry Smith | | | 2004a1cb98faSBarry Smith | | | 2005a1cb98faSBarry Smith 19 0 21 1 23 2006a1cb98faSBarry Smith | | | 2007a1cb98faSBarry Smith | | | 2008a1cb98faSBarry Smith 4---13----5---14----6 2009a1cb98faSBarry Smith .ve 2010a1cb98faSBarry Smith and for simplicial cells 2011a1cb98faSBarry Smith .vb 2012a1cb98faSBarry Smith 14----8---15----9----16 2013a1cb98faSBarry Smith |\ 5 |\ 7 | 2014a1cb98faSBarry Smith | \ | \ | 2015a1cb98faSBarry Smith 13 2 14 3 15 2016a1cb98faSBarry Smith | 4 \ | 6 \ | 2017a1cb98faSBarry Smith | \ | \ | 2018a1cb98faSBarry Smith 11----6---12----7----13 2019a1cb98faSBarry Smith |\ |\ | 2020a1cb98faSBarry Smith | \ 1 | \ 3 | 2021a1cb98faSBarry Smith 10 0 11 1 12 2022a1cb98faSBarry Smith | 0 \ | 2 \ | 2023a1cb98faSBarry Smith | \ | \ | 2024a1cb98faSBarry Smith 8----4----9----5----10 2025a1cb98faSBarry Smith .ve 2026a1cb98faSBarry Smith 20271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 2028768d5fceSMatthew G. Knepley @*/ 202942108689Sksagiyam 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) 2030d71ae5a4SJacob Faibussowitsch { 20319318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 2032fdbf62faSLisandro Dalcin PetscReal low[3] = {0, 0, 0}; 2033fdbf62faSLisandro Dalcin PetscReal upp[3] = {1, 1, 1}; 2034fdbf62faSLisandro Dalcin DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 2035552f7358SJed Brown 2036768d5fceSMatthew G. Knepley PetscFunctionBegin; 20379566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 20389566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 20395dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(*dm, DM_SHAPE_BOX, dim, simplex, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt, interpolate)); 204042108689Sksagiyam if (periodicity) { 204142108689Sksagiyam DM cdm; 204242108689Sksagiyam 204342108689Sksagiyam PetscCall(DMGetCoordinateDM(*dm, &cdm)); 204442108689Sksagiyam PetscCall(DMPlexSetMaxProjectionHeight(cdm, localizationHeight)); 204542108689Sksagiyam PetscCall(DMSetSparseLocalize(*dm, sparseLocalize)); 204642108689Sksagiyam PetscCall(DMLocalizeCoordinates(*dm)); 204742108689Sksagiyam } 20483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20499318fe57SMatthew G. Knepley } 2050fdbf62faSLisandro Dalcin 2051d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeBoxMesh_Internal(DM dm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[]) 2052d71ae5a4SJacob Faibussowitsch { 20539318fe57SMatthew G. Knepley DM bdm, vol; 20549318fe57SMatthew G. Knepley PetscInt i; 20559318fe57SMatthew G. Knepley 20569318fe57SMatthew G. Knepley PetscFunctionBegin; 20571fcf445aSMatthew G. Knepley // TODO Now we can support periodicity 205808401ef6SPierre Jolivet for (i = 0; i < 3; ++i) PetscCheck(periodicity[i] == DM_BOUNDARY_NONE, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Periodicity not yet supported"); 20599566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &bdm)); 20609566063dSJacob Faibussowitsch PetscCall(DMSetType(bdm, DMPLEX)); 20619566063dSJacob Faibussowitsch PetscCall(DMSetDimension(bdm, 2)); 206246139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, bdm, 0, 0, 0)); 20639566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxMesh_Simplex_Internal(bdm, 2, faces, lower, upper, periodicity, PETSC_TRUE)); 20641fcf445aSMatthew G. Knepley PetscCall(DMPlexExtrude(bdm, faces[2], upper[2] - lower[2], PETSC_TRUE, PETSC_FALSE, PETSC_FALSE, NULL, NULL, &vol)); 206546139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, bdm, 0, 0, 0)); 20669566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 206769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 20689318fe57SMatthew G. Knepley if (lower[2] != 0.0) { 20699318fe57SMatthew G. Knepley Vec v; 20709318fe57SMatthew G. Knepley PetscScalar *x; 20719318fe57SMatthew G. Knepley PetscInt cDim, n; 20729318fe57SMatthew G. Knepley 20739566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &v)); 20749566063dSJacob Faibussowitsch PetscCall(VecGetBlockSize(v, &cDim)); 20759566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(v, &n)); 20769566063dSJacob Faibussowitsch PetscCall(VecGetArray(v, &x)); 20779318fe57SMatthew G. Knepley x += cDim; 20789318fe57SMatthew G. Knepley for (i = 0; i < n; i += cDim) x[i] += lower[2]; 20799566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(v, &x)); 20809566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, v)); 20819318fe57SMatthew G. Knepley } 20823ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2083552f7358SJed Brown } 2084552f7358SJed Brown 208500dabe28SStefano Zampini /*@ 208639f4f5dbSPierre Jolivet DMPlexCreateWedgeBoxMesh - Creates a 3-D mesh tessellating the (x,y) plane and extruding in the third direction using wedge cells. 208700dabe28SStefano Zampini 2088d083f849SBarry Smith Collective 208900dabe28SStefano Zampini 209000dabe28SStefano Zampini Input Parameters: 2091a1cb98faSBarry Smith + comm - The communicator for the `DM` object 209220f4b53cSBarry Smith . faces - Number of faces per dimension, or `NULL` for (1, 1, 1) 209320f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 209420f4b53cSBarry Smith . upper - The upper right corner, or `NULL` for (1, 1, 1) 209520f4b53cSBarry Smith . periodicity - The boundary type for the X,Y,Z direction, or `NULL` for `DM_BOUNDARY_NONE` 2096a1cb98faSBarry Smith . orderHeight - If `PETSC_TRUE`, orders the extruded cells in the height first. Otherwise, orders the cell on the layers first 209700dabe28SStefano Zampini - interpolate - Flag to create intermediate mesh pieces (edges, faces) 209800dabe28SStefano Zampini 209900dabe28SStefano Zampini Output Parameter: 2100a1cb98faSBarry Smith . dm - The `DM` object 210100dabe28SStefano Zampini 210200dabe28SStefano Zampini Level: beginner 210300dabe28SStefano Zampini 21041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateWedgeCylinderMesh()`, `DMExtrude()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 210500dabe28SStefano Zampini @*/ 2106d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeBoxMesh(MPI_Comm comm, const PetscInt faces[], const PetscReal lower[], const PetscReal upper[], const DMBoundaryType periodicity[], PetscBool orderHeight, PetscBool interpolate, DM *dm) 2107d71ae5a4SJacob Faibussowitsch { 21089318fe57SMatthew G. Knepley PetscInt fac[3] = {1, 1, 1}; 210900dabe28SStefano Zampini PetscReal low[3] = {0, 0, 0}; 211000dabe28SStefano Zampini PetscReal upp[3] = {1, 1, 1}; 211100dabe28SStefano Zampini DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 211200dabe28SStefano Zampini 211300dabe28SStefano Zampini PetscFunctionBegin; 21149566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 21159566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 21169566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(*dm, faces ? faces : fac, lower ? lower : low, upper ? upper : upp, periodicity ? periodicity : bdt)); 2117d410b0cfSMatthew G. Knepley if (!interpolate) { 2118d410b0cfSMatthew G. Knepley DM udm; 211900dabe28SStefano Zampini 21209566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 212169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(*dm, &udm)); 212200dabe28SStefano Zampini } 21237ff04441SMatthew G. Knepley if (periodicity) PetscCall(DMLocalizeCoordinates(*dm)); 21243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 212500dabe28SStefano Zampini } 212600dabe28SStefano Zampini 2127cfb853baSMatthew G. Knepley /* 2128cfb853baSMatthew 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. 2129cfb853baSMatthew G. Knepley 2130cfb853baSMatthew G. Knepley Input Parameters: 2131cfb853baSMatthew G. Knepley + len - The length of the tuple 2132cfb853baSMatthew G. Knepley . max - The maximum for each dimension, so values are in [0, max) 2133cfb853baSMatthew G. Knepley - tup - A tuple of length len+1: tup[len] > 0 indicates a stopping condition 2134cfb853baSMatthew G. Knepley 2135cfb853baSMatthew G. Knepley Output Parameter: 213620f4b53cSBarry Smith . tup - A tuple of `len` integers whose entries are at most `max` 2137cfb853baSMatthew G. Knepley 2138cfb853baSMatthew G. Knepley Level: developer 2139cfb853baSMatthew G. Knepley 214020f4b53cSBarry Smith Note: 214120f4b53cSBarry Smith Ordering is lexicographic with lowest index as least significant in ordering. 214220f4b53cSBarry 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}. 214320f4b53cSBarry Smith 2144cfb853baSMatthew G. Knepley .seealso: PetscDualSpaceTensorPointLexicographic_Internal(), PetscDualSpaceLatticePointLexicographic_Internal() 2145cfb853baSMatthew G. Knepley */ 2146cfb853baSMatthew G. Knepley static PetscErrorCode DMPlexTensorPointLexicographic_Private(PetscInt len, const PetscInt max[], PetscInt tup[]) 2147cfb853baSMatthew G. Knepley { 2148cfb853baSMatthew G. Knepley PetscInt i; 2149cfb853baSMatthew G. Knepley 2150cfb853baSMatthew G. Knepley PetscFunctionBegin; 2151cfb853baSMatthew G. Knepley for (i = 0; i < len; ++i) { 2152cfb853baSMatthew G. Knepley if (tup[i] < max[i] - 1) { 2153cfb853baSMatthew G. Knepley break; 2154cfb853baSMatthew G. Knepley } else { 2155cfb853baSMatthew G. Knepley tup[i] = 0; 2156cfb853baSMatthew G. Knepley } 2157cfb853baSMatthew G. Knepley } 2158cfb853baSMatthew G. Knepley if (i == len) tup[i - 1] = max[i - 1]; 2159cfb853baSMatthew G. Knepley else ++tup[i]; 21603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2161cfb853baSMatthew G. Knepley } 2162cfb853baSMatthew G. Knepley 2163cfb853baSMatthew G. Knepley static PetscInt TupleToIndex_Private(PetscInt len, const PetscInt max[], const PetscInt tup[]) 2164cfb853baSMatthew G. Knepley { 21658d2ec52aSSatish Balay PetscInt idx = tup[len - 1]; 2166cfb853baSMatthew G. Knepley 21678d2ec52aSSatish Balay for (PetscInt i = len - 2; i >= 0; --i) { 2168cfb853baSMatthew G. Knepley idx *= max[i]; 2169cfb853baSMatthew G. Knepley idx += tup[i]; 2170cfb853baSMatthew G. Knepley } 2171cfb853baSMatthew G. Knepley return idx; 2172cfb853baSMatthew G. Knepley } 2173cfb853baSMatthew G. Knepley 21748d2ec52aSSatish Balay static void IndexToTuple_Private(PetscInt len, const PetscInt max[], PetscInt idx, PetscInt tup[]) 2175cfb853baSMatthew G. Knepley { 21768d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21778d2ec52aSSatish Balay tup[i] = idx % max[i]; 21788d2ec52aSSatish Balay idx = (idx - tup[i]) / max[i]; 21798d2ec52aSSatish Balay } 21808d2ec52aSSatish Balay } 21818d2ec52aSSatish Balay 21828d2ec52aSSatish Balay static void TupleToRanks_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt tup[], PetscInt ranks[]) 21838d2ec52aSSatish Balay { 21848d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21858d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 21868d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 21878d2ec52aSSatish Balay const PetscInt idx = (tup[i] < 0 ? max[i] + tup[i] : tup[i]) % max[i]; 21888d2ec52aSSatish Balay 21898d2ec52aSSatish Balay if (idx < rem * (div + 1)) ranks[i] = idx / (div + 1); 21908d2ec52aSSatish Balay else ranks[i] = rem + (idx - rem * (div + 1)) / div; 21918d2ec52aSSatish Balay } 21928d2ec52aSSatish Balay } 21938d2ec52aSSatish Balay 21948d2ec52aSSatish Balay static void RanksToSizes_Private(PetscInt len, const PetscInt max[], const PetscInt procs[], const PetscInt ranks[], PetscInt sizes[]) 21958d2ec52aSSatish Balay { 21968d2ec52aSSatish Balay for (PetscInt i = 0; i < len; ++i) { 21978d2ec52aSSatish Balay const PetscInt div = max[i] / procs[i]; 21988d2ec52aSSatish Balay const PetscInt rem = max[i] % procs[i]; 21998d2ec52aSSatish Balay 22008d2ec52aSSatish Balay sizes[i] = ranks[i] < rem ? div + 1 : div; 22018d2ec52aSSatish Balay } 22028d2ec52aSSatish Balay } 22038d2ec52aSSatish Balay 22048d2ec52aSSatish Balay /* 22058d2ec52aSSatish 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. 22068d2ec52aSSatish Balay 22078d2ec52aSSatish 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. 22088d2ec52aSSatish Balay 22098d2ec52aSSatish 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. 2210dfe9cfe5SMatthew Knepley 2211dfe9cfe5SMatthew Knepley Parallel Layout: 2212dfe9cfe5SMatthew Knepley 2213dfe9cfe5SMatthew 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. 22148d2ec52aSSatish Balay */ 22158d2ec52aSSatish Balay static PetscErrorCode DMPlexCreateHypercubicMesh_Internal(DM dm, PetscInt dim, const PetscReal lower[], const PetscReal upper[], const PetscInt edges[], PetscInt overlap, const DMBoundaryType bd[]) 22168d2ec52aSSatish Balay { 22178d2ec52aSSatish Balay const PetscInt debug = ((DM_Plex *)dm->data)->printAdj; 22188d2ec52aSSatish Balay PetscSF sf; 2219cfb853baSMatthew G. Knepley Vec coordinates; 2220cfb853baSMatthew G. Knepley PetscSection coordSection; 2221cfb853baSMatthew G. Knepley DMLabel cutLabel = NULL; 2222cfb853baSMatthew G. Knepley PetscBool cutMarker = PETSC_FALSE; 2223cfb853baSMatthew G. Knepley PetscBool periodic = PETSC_FALSE; 22248d2ec52aSSatish Balay PetscInt numCells = 1; 22258d2ec52aSSatish Balay PetscInt numVertices = 1; 22268d2ec52aSSatish Balay PetscSFNode *remotes; 2227cfb853baSMatthew G. Knepley PetscScalar *coords; 22288d2ec52aSSatish Balay PetscInt *procs; // The number of processes along each dimension 22298d2ec52aSSatish Balay PetscInt *lrank; // Rank in each dimension, lrank[d] \in [0, procs[d]) 22308d2ec52aSSatish Balay PetscInt *ledges; // The number of edges along each dimension for this process 22318d2ec52aSSatish Balay PetscInt *vstart; // The first vertex along each dimension on this processes 22328d2ec52aSSatish Balay PetscInt *vertices; // The number of vertices along each dimension on this process 22338d2ec52aSSatish Balay PetscInt *rvert; // The global (not local) vertex number along each dimension 22348d2ec52aSSatish Balay PetscInt *rrank; // The rank along each dimension for the process owning rvert[] 22358d2ec52aSSatish Balay PetscInt *rvertices; // The number of vertices along each dimension for the process rrank[] 22368d2ec52aSSatish Balay PetscInt *vert, *vtmp, *supp, cone[2], *leaves; 22378d2ec52aSSatish Balay PetscInt cell = 0, coordSize, Nl = 0, Nl2 = 0; 22388d2ec52aSSatish Balay PetscMPIInt rank, size; 22398d2ec52aSSatish Balay MPI_Comm comm; 2240cfb853baSMatthew G. Knepley 2241cfb853baSMatthew G. Knepley PetscFunctionBegin; 22428d2ec52aSSatish Balay PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 22438d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_rank(comm, &rank)); 22448d2ec52aSSatish Balay PetscCallMPI(MPI_Comm_size(comm, &size)); 2245cfb853baSMatthew G. Knepley PetscCall(DMSetDimension(dm, dim)); 22468d2ec52aSSatish Balay PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 22478d2ec52aSSatish Balay PetscCall(PetscCalloc4(dim, &procs, dim, &lrank, dim, &rrank, 2 * dim, &supp)); 22488d2ec52aSSatish Balay PetscCall(PetscCalloc7(dim, &ledges, dim, &vertices, dim, &rvertices, dim, &vert, dim, &rvert, dim, &vstart, dim, &vtmp)); 2249cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 2250cfb853baSMatthew G. Knepley PetscCall(PetscOptionsGetBool(((PetscObject)dm)->options, ((PetscObject)dm)->prefix, "-dm_plex_periodic_cut", &cutMarker, NULL)); 22518d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) periodic = (periodic || bd[d] == DM_BOUNDARY_PERIODIC) ? PETSC_TRUE : PETSC_FALSE; 2252cfb853baSMatthew G. Knepley if (periodic && cutMarker) { 2253cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "periodic_cut")); 2254cfb853baSMatthew G. Knepley PetscCall(DMGetLabel(dm, "periodic_cut", &cutLabel)); 2255cfb853baSMatthew G. Knepley } 22568d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCheck(bd[d] == DM_BOUNDARY_PERIODIC, comm, PETSC_ERR_SUP, "Hypercubic mesh must be periodic now"); 22578d2ec52aSSatish Balay overlap = overlap == PETSC_DETERMINE ? 1 : overlap; 22588d2ec52aSSatish Balay PetscCheck(overlap >= 1, comm, PETSC_ERR_SUP, "Overlap %" PetscInt_FMT " must be greater than 0", overlap); 22598d2ec52aSSatish Balay if (size > 1) { 22608d2ec52aSSatish Balay PetscInt Npr = 1; 22618d2ec52aSSatish Balay 22628d2ec52aSSatish Balay // Make process grid 22638d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "Process grid:")); 22648d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22658d2ec52aSSatish Balay procs[d] = PetscRintReal(PetscPowReal(size, 1. / dim)); 22668d2ec52aSSatish Balay Npr *= procs[d]; 22678d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, " %" PetscInt_FMT, procs[d])); 22688d2ec52aSSatish Balay } 22698d2ec52aSSatish Balay if (debug) PetscCall(PetscPrintf(comm, "\n")); 22708d2ec52aSSatish Balay PetscCheck(Npr == size, comm, PETSC_ERR_PLIB, "Process grid size %" PetscInt_FMT " != %d comm size", Npr, size); 22718d2ec52aSSatish Balay IndexToTuple_Private(dim, procs, rank, lrank); 22728d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22738d2ec52aSSatish Balay ledges[d] = edges[d] / procs[d] + (edges[d] % procs[d] > lrank[d] ? 1 : 0); 22748d2ec52aSSatish Balay vstart[d] = 0; 22758d2ec52aSSatish Balay for (PetscInt r = 0; r < lrank[d]; ++r) vstart[d] += edges[d] / procs[d] + (edges[d] % procs[d] > r ? 1 : 0); 22768d2ec52aSSatish Balay vstart[d] -= overlap; // For halo 22778d2ec52aSSatish Balay } 22788d2ec52aSSatish Balay } else { 22798d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22808d2ec52aSSatish Balay procs[d] = 1; 22818d2ec52aSSatish Balay ledges[d] = edges[d]; 22828d2ec52aSSatish Balay } 22838d2ec52aSSatish Balay } 22848d2ec52aSSatish Balay // Calculate local patch size 22858d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 22868d2ec52aSSatish Balay vertices[d] = ledges[d] + (procs[d] > 1 ? 2 * overlap : 0); 2287cfb853baSMatthew G. Knepley numVertices *= vertices[d]; 2288cfb853baSMatthew G. Knepley } 2289cfb853baSMatthew G. Knepley numCells = numVertices * dim; 2290cfb853baSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 22918d2ec52aSSatish Balay for (PetscInt c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, 2)); 22928d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetSupportSize(dm, v, 2 * dim)); 2293cfb853baSMatthew G. Knepley PetscCall(DMSetUp(dm)); /* Allocate space for cones and supports */ 2294cfb853baSMatthew G. Knepley /* Build cell cones and vertex supports */ 2295cfb853baSMatthew G. Knepley PetscCall(DMCreateLabel(dm, "celltype")); 22968d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Topology for rank %d:\n", rank)); 2297cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2298cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert) + numCells; 2299cfb853baSMatthew G. Knepley PetscInt s = 0; 23008d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2301cfb853baSMatthew G. Knepley 23028d2ec52aSSatish Balay if (debug) { 23038d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 23048d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d])); 23058d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 23068d2ec52aSSatish Balay } 2307cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, vertex, DM_POLYTOPE_POINT)); 23088d2ec52aSSatish Balay // Define edge cones 23098d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23108d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2311cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + 1) % vertices[d]; 2312cfb853baSMatthew G. Knepley cone[0] = vertex; 2313cfb853baSMatthew G. Knepley cone[1] = TupleToIndex_Private(dim, vertices, vtmp) + numCells; 23148d2ec52aSSatish Balay if (debug) { 23158d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, " Vertex %" PetscInt_FMT ":", cone[1])); 23168d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vtmp[e])); 23178d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 23188d2ec52aSSatish Balay } 2319cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCone(dm, cell, cone)); 2320cfb853baSMatthew G. Knepley PetscCall(DMPlexSetCellType(dm, cell, DM_POLYTOPE_SEGMENT)); 23218d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, " Edge %" PetscInt_FMT " (%" PetscInt_FMT " %" PetscInt_FMT ")\n", cell, cone[0], cone[1])); 2322cfb853baSMatthew G. Knepley ++cell; 23238d2ec52aSSatish Balay // Shared vertices are any in the first or last overlap layers 23248d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 2325cfb853baSMatthew G. Knepley } 23268d2ec52aSSatish Balay if (size > 1 && leaf) ++Nl; 23278d2ec52aSSatish Balay // Define vertex supports 23288d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23298d2ec52aSSatish Balay for (PetscInt e = 0; e < dim; ++e) vtmp[e] = vert[e]; 2330cfb853baSMatthew G. Knepley vtmp[d] = (vert[d] + vertices[d] - 1) % vertices[d]; 2331cfb853baSMatthew G. Knepley supp[s++] = TupleToIndex_Private(dim, vertices, vtmp) * dim + d; 2332cfb853baSMatthew G. Knepley supp[s++] = (vertex - numCells) * dim + d; 2333cfb853baSMatthew G. Knepley PetscCall(DMPlexSetSupport(dm, vertex, supp)); 2334cfb853baSMatthew G. Knepley } 2335cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2336cfb853baSMatthew G. Knepley } 23378d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2338cfb853baSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 23398d2ec52aSSatish Balay // Allocate for SF 23408d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &leaves)); 23418d2ec52aSSatish Balay PetscCall(PetscMalloc1(Nl, &remotes)); 23428d2ec52aSSatish Balay // Build coordinates 2343cfb853baSMatthew G. Knepley PetscCall(DMGetCoordinateSection(dm, &coordSection)); 2344cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetNumFields(coordSection, 1)); 2345cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 2346cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 23478d2ec52aSSatish Balay for (PetscInt v = numCells; v < numCells + numVertices; ++v) { 2348cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetDof(coordSection, v, dim)); 2349cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 2350cfb853baSMatthew G. Knepley } 2351cfb853baSMatthew G. Knepley PetscCall(PetscSectionSetUp(coordSection)); 2352cfb853baSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 23538d2ec52aSSatish Balay PetscCall(VecCreate(comm, &coordinates)); 2354cfb853baSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 2355cfb853baSMatthew G. Knepley PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 2356cfb853baSMatthew G. Knepley PetscCall(VecSetBlockSize(coordinates, dim)); 2357cfb853baSMatthew G. Knepley PetscCall(VecSetType(coordinates, VECSTANDARD)); 2358cfb853baSMatthew G. Knepley PetscCall(VecGetArray(coordinates, &coords)); 23598d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Geometry for rank %d:\n", rank)); 23608d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) vert[d] = 0; 2361cfb853baSMatthew G. Knepley while (vert[dim - 1] < vertices[dim - 1]) { 2362cfb853baSMatthew G. Knepley const PetscInt vertex = TupleToIndex_Private(dim, vertices, vert); 23638d2ec52aSSatish Balay PetscBool leaf = PETSC_FALSE; 2364cfb853baSMatthew G. Knepley 23658d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23668d2ec52aSSatish Balay coords[vertex * dim + d] = lower[d] + ((upper[d] - lower[d]) / edges[d]) * (vert[d] + vstart[d]); 23678d2ec52aSSatish Balay if (vert[d] < overlap || vert[d] >= vertices[d] - overlap) leaf = PETSC_TRUE; 23688d2ec52aSSatish Balay } 23698d2ec52aSSatish Balay if (size > 1 && leaf) { 23708d2ec52aSSatish Balay PetscInt rnumCells = 1; 23718d2ec52aSSatish Balay 23728d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) rvert[d] = vert[d] + vstart[d]; 23738d2ec52aSSatish Balay TupleToRanks_Private(dim, edges, procs, rvert, rrank); 23748d2ec52aSSatish Balay leaves[Nl2] = vertex + numCells; 23758d2ec52aSSatish Balay remotes[Nl2].rank = TupleToIndex_Private(dim, procs, rrank); 23768d2ec52aSSatish Balay RanksToSizes_Private(dim, edges, procs, rrank, rvertices); 23778d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23788d2ec52aSSatish Balay rvertices[d] += 2 * overlap; // Add halo 23798d2ec52aSSatish Balay rnumCells *= rvertices[d]; 23808d2ec52aSSatish Balay } 23818d2ec52aSSatish Balay rnumCells *= dim; 23828d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 23838d2ec52aSSatish Balay const PetscInt diff = rrank[d] - lrank[d]; 23848d2ec52aSSatish Balay 23858d2ec52aSSatish Balay if (!diff) rvert[d] = vert[d]; // Vertex is local 23868d2ec52aSSatish Balay else if (rvert[d] < 0) rvert[d] = rvertices[d] - 1 + rvert[d]; // Wrap around at the bottom 23878d2ec52aSSatish Balay else if (rvert[d] >= edges[d]) rvert[d] = rvert[d] - edges[d] + 1; // Wrap around at the top 23888d2ec52aSSatish Balay else if (diff == -1) rvert[d] = rvertices[d] - 1 + (vert[d] - overlap); 23898d2ec52aSSatish Balay else if (diff == 1) rvert[d] = (vertices[d] - vert[d] - 1) + overlap; 23908d2ec52aSSatish Balay else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Process distance %" PetscInt_FMT " in direction %" PetscInt_FMT " should not be possible", diff, d); 23918d2ec52aSSatish Balay } 23928d2ec52aSSatish Balay remotes[Nl2].index = TupleToIndex_Private(dim, rvertices, rvert) + rnumCells; 23938d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedPrintf(comm, "Shared Vertex %" PetscInt_FMT " (%" PetscInt_FMT ", %" PetscInt_FMT ")\n", leaves[Nl2], remotes[Nl2].rank, remotes[Nl2].index)); 23948d2ec52aSSatish Balay ++Nl2; 23958d2ec52aSSatish Balay } 23968d2ec52aSSatish Balay if (debug) { 23978d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "Vertex %" PetscInt_FMT ":", vertex)); 23988d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %" PetscInt_FMT, vert[d] + vstart[d])); 23998d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %g", (double)PetscRealPart(coords[vertex * dim + d]))); 24008d2ec52aSSatish Balay PetscCall(PetscSynchronizedPrintf(comm, "\n")); 24018d2ec52aSSatish Balay } 2402cfb853baSMatthew G. Knepley PetscCall(DMPlexTensorPointLexicographic_Private(dim, vertices, vert)); 2403cfb853baSMatthew G. Knepley } 24048d2ec52aSSatish Balay if (debug) PetscCall(PetscSynchronizedFlush(comm, NULL)); 2405cfb853baSMatthew G. Knepley PetscCall(VecRestoreArray(coordinates, &coords)); 2406cfb853baSMatthew G. Knepley PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 2407cfb853baSMatthew G. Knepley PetscCall(VecDestroy(&coordinates)); 24088d2ec52aSSatish Balay // Build SF 24098d2ec52aSSatish Balay PetscCheck(Nl == Nl2, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Initial number of leaves %" PetscInt_FMT " != %" PetscInt_FMT " final number", Nl, Nl2); 24108d2ec52aSSatish Balay PetscCall(DMGetPointSF(dm, &sf)); 24118d2ec52aSSatish Balay PetscCall(PetscSFSetGraph(sf, numCells + numVertices, Nl, leaves, PETSC_OWN_POINTER, remotes, PETSC_OWN_POINTER)); 24128d2ec52aSSatish Balay if (debug) PetscCall(PetscSFView(sf, PETSC_VIEWER_STDOUT_WORLD)); 2413cfb853baSMatthew G. Knepley //PetscCall(DMSetPeriodicity(dm, NULL, lower, upper)); 2414cfb853baSMatthew G. Knepley // Attach the extent 2415cfb853baSMatthew G. Knepley { 2416cfb853baSMatthew G. Knepley PetscContainer c; 24178d2ec52aSSatish Balay PetscInt *extent, *lextent; 2418cfb853baSMatthew G. Knepley 2419cfb853baSMatthew G. Knepley PetscCall(PetscMalloc1(dim, &extent)); 24208d2ec52aSSatish Balay PetscCall(PetscMalloc1(dim, &lextent)); 24218d2ec52aSSatish Balay for (PetscInt d = 0; d < dim; ++d) { 24228d2ec52aSSatish Balay extent[d] = edges[d]; 24238d2ec52aSSatish Balay lextent[d] = ledges[d]; 24248d2ec52aSSatish Balay } 2425cfb853baSMatthew G. Knepley PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 242649abdd8aSBarry Smith PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 2427cfb853baSMatthew G. Knepley PetscCall(PetscContainerSetPointer(c, extent)); 2428cfb853baSMatthew G. Knepley PetscCall(PetscObjectCompose((PetscObject)dm, "_extent", (PetscObject)c)); 2429cfb853baSMatthew G. Knepley PetscCall(PetscContainerDestroy(&c)); 24308d2ec52aSSatish Balay PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &c)); 24318d2ec52aSSatish Balay PetscCall(PetscContainerSetCtxDestroy(c, PetscCtxDestroyDefault)); 24328d2ec52aSSatish Balay PetscCall(PetscContainerSetPointer(c, lextent)); 24338d2ec52aSSatish Balay PetscCall(PetscObjectCompose((PetscObject)dm, "_lextent", (PetscObject)c)); 24348d2ec52aSSatish Balay PetscCall(PetscContainerDestroy(&c)); 2435cfb853baSMatthew G. Knepley } 24368d2ec52aSSatish Balay PetscCall(PetscFree4(procs, lrank, rrank, supp)); 24378d2ec52aSSatish Balay PetscCall(PetscFree7(ledges, vertices, rvertices, vert, rvert, vstart, vtmp)); 24383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2439cfb853baSMatthew G. Knepley } 2440cfb853baSMatthew G. Knepley 2441cfb853baSMatthew G. Knepley /*@C 2442aaa8cc7dSPierre Jolivet DMPlexCreateHypercubicMesh - Creates a periodic mesh on the tensor product of unit intervals using only vertices and edges. 2443cfb853baSMatthew G. Knepley 2444cfb853baSMatthew G. Knepley Collective 2445cfb853baSMatthew G. Knepley 2446cfb853baSMatthew G. Knepley Input Parameters: 24478d2ec52aSSatish Balay + comm - The communicator for the `DM` object 2448cfb853baSMatthew G. Knepley . dim - The spatial dimension 244920f4b53cSBarry Smith . edges - Number of edges per dimension, or `NULL` for (1,) in 1D and (2, 2) in 2D and (1, 1, 1) in 3D 245020f4b53cSBarry Smith . lower - The lower left corner, or `NULL` for (0, 0, 0) 24518d2ec52aSSatish Balay . upper - The upper right corner, or `NULL` for (1, 1, 1) 24528d2ec52aSSatish Balay - overlap - The number of vertices in each direction to include in the overlap (default is 1) 2453cfb853baSMatthew G. Knepley 2454cfb853baSMatthew G. Knepley Output Parameter: 2455cfb853baSMatthew G. Knepley . dm - The DM object 2456cfb853baSMatthew G. Knepley 245720f4b53cSBarry Smith Level: beginner 245820f4b53cSBarry Smith 245920f4b53cSBarry Smith Note: 246020f4b53cSBarry Smith If you want to customize this mesh using options, you just need to 246120f4b53cSBarry Smith .vb 246220f4b53cSBarry Smith DMCreate(comm, &dm); 246320f4b53cSBarry Smith DMSetType(dm, DMPLEX); 246420f4b53cSBarry Smith DMSetFromOptions(dm); 246520f4b53cSBarry Smith .ve 246620f4b53cSBarry Smith and use the options on the `DMSetFromOptions()` page. 2467cfb853baSMatthew G. Knepley 2468cfb853baSMatthew G. Knepley The vertices are numbered is lexicographic order, and the dim edges exiting a vertex in the positive orthant are number consecutively, 246920f4b53cSBarry Smith .vb 247020f4b53cSBarry Smith 18--0-19--2-20--4-18 247120f4b53cSBarry Smith | | | | 247220f4b53cSBarry Smith 13 15 17 13 247320f4b53cSBarry Smith | | | | 247420f4b53cSBarry Smith 24-12-25-14-26-16-24 247520f4b53cSBarry Smith | | | | 247620f4b53cSBarry Smith 7 9 11 7 247720f4b53cSBarry Smith | | | | 247820f4b53cSBarry Smith 21--6-22--8-23-10-21 247920f4b53cSBarry Smith | | | | 248020f4b53cSBarry Smith 1 3 5 1 248120f4b53cSBarry Smith | | | | 248220f4b53cSBarry Smith 18--0-19--2-20--4-18 248320f4b53cSBarry Smith .ve 2484cfb853baSMatthew G. Knepley 248576fbde31SPierre Jolivet .seealso: `DMSetFromOptions()`, `DMPlexCreateFromFile()`, `DMPlexCreateHexCylinderMesh()`, `DMSetType()`, `DMCreate()` 2486cfb853baSMatthew G. Knepley @*/ 24878d2ec52aSSatish Balay PetscErrorCode DMPlexCreateHypercubicMesh(MPI_Comm comm, PetscInt dim, const PetscInt edges[], const PetscReal lower[], const PetscReal upper[], PetscInt overlap, DM *dm) 2488cfb853baSMatthew G. Knepley { 2489cfb853baSMatthew G. Knepley PetscInt *edg; 2490cfb853baSMatthew G. Knepley PetscReal *low, *upp; 2491cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 2492cfb853baSMatthew G. Knepley PetscInt d; 2493cfb853baSMatthew G. Knepley 2494cfb853baSMatthew G. Knepley PetscFunctionBegin; 2495cfb853baSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 2496cfb853baSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 2497cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edg, dim, &low, dim, &upp, dim, &bdt)); 2498cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 2499cfb853baSMatthew G. Knepley edg[d] = edges ? edges[d] : 1; 2500cfb853baSMatthew G. Knepley low[d] = lower ? lower[d] : 0.; 2501cfb853baSMatthew G. Knepley upp[d] = upper ? upper[d] : 1.; 2502cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 2503cfb853baSMatthew G. Knepley } 25048d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(*dm, dim, low, upp, edg, overlap, bdt)); 2505cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edg, low, upp, bdt)); 25063ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2507cfb853baSMatthew G. Knepley } 2508cfb853baSMatthew G. Knepley 2509cc4c1da9SBarry Smith /*@ 2510a1cb98faSBarry Smith DMPlexSetOptionsPrefix - Sets the prefix used for searching for all `DM` options in the database. 2511a9074c1eSMatthew G. Knepley 251220f4b53cSBarry Smith Logically Collective 2513a9074c1eSMatthew G. Knepley 2514a9074c1eSMatthew G. Knepley Input Parameters: 251520f4b53cSBarry Smith + dm - the `DM` context 2516a9074c1eSMatthew G. Knepley - prefix - the prefix to prepend to all option names 2517a9074c1eSMatthew G. Knepley 2518a1cb98faSBarry Smith Level: advanced 2519a1cb98faSBarry Smith 2520a1cb98faSBarry Smith Note: 2521a9074c1eSMatthew G. Knepley A hyphen (-) must NOT be given at the beginning of the prefix name. 2522a9074c1eSMatthew G. Knepley The first character of all runtime options is AUTOMATICALLY the hyphen. 2523a9074c1eSMatthew G. Knepley 25241cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `SNESSetFromOptions()` 2525a9074c1eSMatthew G. Knepley @*/ 2526d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexSetOptionsPrefix(DM dm, const char prefix[]) 2527d71ae5a4SJacob Faibussowitsch { 2528a9074c1eSMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 2529a9074c1eSMatthew G. Knepley 2530a9074c1eSMatthew G. Knepley PetscFunctionBegin; 2531a9074c1eSMatthew G. Knepley PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 25329566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, prefix)); 25339566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)mesh->partitioner, prefix)); 25343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2535a9074c1eSMatthew G. Knepley } 2536a9074c1eSMatthew G. Knepley 25379318fe57SMatthew G. Knepley /* Remap geometry to cylinder 253861a622f3SMatthew G. Knepley TODO: This only works for a single refinement, then it is broken 253961a622f3SMatthew G. Knepley 25409318fe57SMatthew G. Knepley Interior square: Linear interpolation is correct 25419318fe57SMatthew G. Knepley The other cells all have vertices on rays from the origin. We want to uniformly expand the spacing 25429318fe57SMatthew G. Knepley such that the last vertex is on the unit circle. So the closest and farthest vertices are at distance 25430510c589SMatthew G. Knepley 25449318fe57SMatthew G. Knepley phi = arctan(y/x) 25459318fe57SMatthew G. Knepley d_close = sqrt(1/8 + 1/4 sin^2(phi)) 25469318fe57SMatthew G. Knepley d_far = sqrt(1/2 + sin^2(phi)) 25470510c589SMatthew G. Knepley 25489318fe57SMatthew G. Knepley so we remap them using 25490510c589SMatthew G. Knepley 25509318fe57SMatthew G. Knepley x_new = x_close + (x - x_close) (1 - d_close) / (d_far - d_close) 25519318fe57SMatthew G. Knepley y_new = y_close + (y - y_close) (1 - d_close) / (d_far - d_close) 25520510c589SMatthew G. Knepley 25539318fe57SMatthew G. Knepley If pi/4 < phi < 3pi/4 or -3pi/4 < phi < -pi/4, then we switch x and y. 25549318fe57SMatthew G. Knepley */ 2555d71ae5a4SJacob 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[]) 2556d71ae5a4SJacob Faibussowitsch { 25579318fe57SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 25589318fe57SMatthew G. Knepley const PetscReal ds2 = 0.5 * dis; 255922cc497dSMatthew G. Knepley 25609318fe57SMatthew G. Knepley if ((PetscAbsScalar(u[0]) <= ds2) && (PetscAbsScalar(u[1]) <= ds2)) { 25619318fe57SMatthew G. Knepley f0[0] = u[0]; 25629318fe57SMatthew G. Knepley f0[1] = u[1]; 25639318fe57SMatthew G. Knepley } else { 25649318fe57SMatthew G. Knepley PetscReal phi, sinp, cosp, dc, df, x, y, xc, yc; 25650510c589SMatthew G. Knepley 25669318fe57SMatthew G. Knepley x = PetscRealPart(u[0]); 25679318fe57SMatthew G. Knepley y = PetscRealPart(u[1]); 25689318fe57SMatthew G. Knepley phi = PetscAtan2Real(y, x); 25699318fe57SMatthew G. Knepley sinp = PetscSinReal(phi); 25709318fe57SMatthew G. Knepley cosp = PetscCosReal(phi); 25719318fe57SMatthew G. Knepley if ((PetscAbsReal(phi) > PETSC_PI / 4.0) && (PetscAbsReal(phi) < 3.0 * PETSC_PI / 4.0)) { 25729318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / sinp); 25739318fe57SMatthew G. Knepley df = PetscAbsReal(dis / sinp); 25749318fe57SMatthew G. Knepley xc = ds2 * x / PetscAbsReal(y); 25759318fe57SMatthew G. Knepley yc = ds2 * PetscSignReal(y); 25769318fe57SMatthew G. Knepley } else { 25779318fe57SMatthew G. Knepley dc = PetscAbsReal(ds2 / cosp); 25789318fe57SMatthew G. Knepley df = PetscAbsReal(dis / cosp); 25799318fe57SMatthew G. Knepley xc = ds2 * PetscSignReal(x); 25809318fe57SMatthew G. Knepley yc = ds2 * y / PetscAbsReal(x); 25819318fe57SMatthew G. Knepley } 25829318fe57SMatthew G. Knepley f0[0] = xc + (u[0] - xc) * (1.0 - dc) / (df - dc); 25839318fe57SMatthew G. Knepley f0[1] = yc + (u[1] - yc) * (1.0 - dc) / (df - dc); 25849318fe57SMatthew G. Knepley } 25859318fe57SMatthew G. Knepley f0[2] = u[2]; 25869318fe57SMatthew G. Knepley } 25870510c589SMatthew G. Knepley 258849704ca5SMatthew G. Knepley static PetscErrorCode DMPlexCreateHexCylinderMesh_Internal(DM dm, DMBoundaryType periodicZ, PetscInt Nr) 2589d71ae5a4SJacob Faibussowitsch { 25900510c589SMatthew G. Knepley const PetscInt dim = 3; 25919318fe57SMatthew G. Knepley PetscInt numCells, numVertices; 2592d8c47e87SMatthew G. Knepley PetscMPIInt rank; 25930510c589SMatthew G. Knepley 25940510c589SMatthew G. Knepley PetscFunctionBegin; 259546139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 25969566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 25979566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 25980510c589SMatthew G. Knepley /* Create topology */ 25990510c589SMatthew G. Knepley { 26000510c589SMatthew G. Knepley PetscInt cone[8], c; 26010510c589SMatthew G. Knepley 2602dd400576SPatrick Sanan numCells = rank == 0 ? 5 : 0; 2603dd400576SPatrick Sanan numVertices = rank == 0 ? 16 : 0; 2604006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 2605ae8bcbbbSMatthew G. Knepley numCells *= 3; 2606dd400576SPatrick Sanan numVertices = rank == 0 ? 24 : 0; 2607006a8963SMatthew G. Knepley } 26089566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 26099566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 8)); 26109566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 2611dd400576SPatrick Sanan if (rank == 0) { 2612006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 26139371c9d4SSatish Balay cone[0] = 15; 26149371c9d4SSatish Balay cone[1] = 18; 26159371c9d4SSatish Balay cone[2] = 17; 26169371c9d4SSatish Balay cone[3] = 16; 26179371c9d4SSatish Balay cone[4] = 31; 26189371c9d4SSatish Balay cone[5] = 32; 26199371c9d4SSatish Balay cone[6] = 33; 26209371c9d4SSatish Balay cone[7] = 34; 26219566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 26229371c9d4SSatish Balay cone[0] = 16; 26239371c9d4SSatish Balay cone[1] = 17; 26249371c9d4SSatish Balay cone[2] = 24; 26259371c9d4SSatish Balay cone[3] = 23; 26269371c9d4SSatish Balay cone[4] = 32; 26279371c9d4SSatish Balay cone[5] = 36; 26289371c9d4SSatish Balay cone[6] = 37; 26299371c9d4SSatish Balay cone[7] = 33; /* 22 25 26 21 */ 26309566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 26319371c9d4SSatish Balay cone[0] = 18; 26329371c9d4SSatish Balay cone[1] = 27; 26339371c9d4SSatish Balay cone[2] = 24; 26349371c9d4SSatish Balay cone[3] = 17; 26359371c9d4SSatish Balay cone[4] = 34; 26369371c9d4SSatish Balay cone[5] = 33; 26379371c9d4SSatish Balay cone[6] = 37; 26389371c9d4SSatish Balay cone[7] = 38; 26399566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 26409371c9d4SSatish Balay cone[0] = 29; 26419371c9d4SSatish Balay cone[1] = 27; 26429371c9d4SSatish Balay cone[2] = 18; 26439371c9d4SSatish Balay cone[3] = 15; 26449371c9d4SSatish Balay cone[4] = 35; 26459371c9d4SSatish Balay cone[5] = 31; 26469371c9d4SSatish Balay cone[6] = 34; 26479371c9d4SSatish Balay cone[7] = 38; 26489566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 26499371c9d4SSatish Balay cone[0] = 29; 26509371c9d4SSatish Balay cone[1] = 15; 26519371c9d4SSatish Balay cone[2] = 16; 26529371c9d4SSatish Balay cone[3] = 23; 26539371c9d4SSatish Balay cone[4] = 35; 26549371c9d4SSatish Balay cone[5] = 36; 26559371c9d4SSatish Balay cone[6] = 32; 26569371c9d4SSatish Balay cone[7] = 31; 26579566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2658006a8963SMatthew G. Knepley 26599371c9d4SSatish Balay cone[0] = 31; 26609371c9d4SSatish Balay cone[1] = 34; 26619371c9d4SSatish Balay cone[2] = 33; 26629371c9d4SSatish Balay cone[3] = 32; 26639371c9d4SSatish Balay cone[4] = 19; 26649371c9d4SSatish Balay cone[5] = 22; 26659371c9d4SSatish Balay cone[6] = 21; 26669371c9d4SSatish Balay cone[7] = 20; 26679566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 26689371c9d4SSatish Balay cone[0] = 32; 26699371c9d4SSatish Balay cone[1] = 33; 26709371c9d4SSatish Balay cone[2] = 37; 26719371c9d4SSatish Balay cone[3] = 36; 26729371c9d4SSatish Balay cone[4] = 22; 26739371c9d4SSatish Balay cone[5] = 25; 26749371c9d4SSatish Balay cone[6] = 26; 26759371c9d4SSatish Balay cone[7] = 21; 26769566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 6, cone)); 26779371c9d4SSatish Balay cone[0] = 34; 26789371c9d4SSatish Balay cone[1] = 38; 26799371c9d4SSatish Balay cone[2] = 37; 26809371c9d4SSatish Balay cone[3] = 33; 26819371c9d4SSatish Balay cone[4] = 20; 26829371c9d4SSatish Balay cone[5] = 21; 26839371c9d4SSatish Balay cone[6] = 26; 26849371c9d4SSatish Balay cone[7] = 28; 26859566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 7, cone)); 26869371c9d4SSatish Balay cone[0] = 35; 26879371c9d4SSatish Balay cone[1] = 38; 26889371c9d4SSatish Balay cone[2] = 34; 26899371c9d4SSatish Balay cone[3] = 31; 26909371c9d4SSatish Balay cone[4] = 30; 26919371c9d4SSatish Balay cone[5] = 19; 26929371c9d4SSatish Balay cone[6] = 20; 26939371c9d4SSatish Balay cone[7] = 28; 26949566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 8, cone)); 26959371c9d4SSatish Balay cone[0] = 35; 26969371c9d4SSatish Balay cone[1] = 31; 26979371c9d4SSatish Balay cone[2] = 32; 26989371c9d4SSatish Balay cone[3] = 36; 26999371c9d4SSatish Balay cone[4] = 30; 27009371c9d4SSatish Balay cone[5] = 25; 27019371c9d4SSatish Balay cone[6] = 22; 27029371c9d4SSatish Balay cone[7] = 19; 27039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 9, cone)); 2704ae8bcbbbSMatthew G. Knepley 27059371c9d4SSatish Balay cone[0] = 19; 27069371c9d4SSatish Balay cone[1] = 20; 27079371c9d4SSatish Balay cone[2] = 21; 27089371c9d4SSatish Balay cone[3] = 22; 27099371c9d4SSatish Balay cone[4] = 15; 27109371c9d4SSatish Balay cone[5] = 16; 27119371c9d4SSatish Balay cone[6] = 17; 27129371c9d4SSatish Balay cone[7] = 18; 27139566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 10, cone)); 27149371c9d4SSatish Balay cone[0] = 22; 27159371c9d4SSatish Balay cone[1] = 21; 27169371c9d4SSatish Balay cone[2] = 26; 27179371c9d4SSatish Balay cone[3] = 25; 27189371c9d4SSatish Balay cone[4] = 16; 27199371c9d4SSatish Balay cone[5] = 23; 27209371c9d4SSatish Balay cone[6] = 24; 27219371c9d4SSatish Balay cone[7] = 17; 27229566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 11, cone)); 27239371c9d4SSatish Balay cone[0] = 20; 27249371c9d4SSatish Balay cone[1] = 28; 27259371c9d4SSatish Balay cone[2] = 26; 27269371c9d4SSatish Balay cone[3] = 21; 27279371c9d4SSatish Balay cone[4] = 18; 27289371c9d4SSatish Balay cone[5] = 17; 27299371c9d4SSatish Balay cone[6] = 24; 27309371c9d4SSatish Balay cone[7] = 27; 27319566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 12, cone)); 27329371c9d4SSatish Balay cone[0] = 30; 27339371c9d4SSatish Balay cone[1] = 28; 27349371c9d4SSatish Balay cone[2] = 20; 27359371c9d4SSatish Balay cone[3] = 19; 27369371c9d4SSatish Balay cone[4] = 29; 27379371c9d4SSatish Balay cone[5] = 15; 27389371c9d4SSatish Balay cone[6] = 18; 27399371c9d4SSatish Balay cone[7] = 27; 27409566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 13, cone)); 27419371c9d4SSatish Balay cone[0] = 30; 27429371c9d4SSatish Balay cone[1] = 19; 27439371c9d4SSatish Balay cone[2] = 22; 27449371c9d4SSatish Balay cone[3] = 25; 27459371c9d4SSatish Balay cone[4] = 29; 27469371c9d4SSatish Balay cone[5] = 23; 27479371c9d4SSatish Balay cone[6] = 16; 27489371c9d4SSatish Balay cone[7] = 15; 27499566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 2750006a8963SMatthew G. Knepley } else { 27519371c9d4SSatish Balay cone[0] = 5; 27529371c9d4SSatish Balay cone[1] = 8; 27539371c9d4SSatish Balay cone[2] = 7; 27549371c9d4SSatish Balay cone[3] = 6; 27559371c9d4SSatish Balay cone[4] = 9; 27569371c9d4SSatish Balay cone[5] = 12; 27579371c9d4SSatish Balay cone[6] = 11; 27589371c9d4SSatish Balay cone[7] = 10; 27599566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 27609371c9d4SSatish Balay cone[0] = 6; 27619371c9d4SSatish Balay cone[1] = 7; 27629371c9d4SSatish Balay cone[2] = 14; 27639371c9d4SSatish Balay cone[3] = 13; 27649371c9d4SSatish Balay cone[4] = 12; 27659371c9d4SSatish Balay cone[5] = 15; 27669371c9d4SSatish Balay cone[6] = 16; 27679371c9d4SSatish Balay cone[7] = 11; 27689566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 27699371c9d4SSatish Balay cone[0] = 8; 27709371c9d4SSatish Balay cone[1] = 17; 27719371c9d4SSatish Balay cone[2] = 14; 27729371c9d4SSatish Balay cone[3] = 7; 27739371c9d4SSatish Balay cone[4] = 10; 27749371c9d4SSatish Balay cone[5] = 11; 27759371c9d4SSatish Balay cone[6] = 16; 27769371c9d4SSatish Balay cone[7] = 18; 27779566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 27789371c9d4SSatish Balay cone[0] = 19; 27799371c9d4SSatish Balay cone[1] = 17; 27809371c9d4SSatish Balay cone[2] = 8; 27819371c9d4SSatish Balay cone[3] = 5; 27829371c9d4SSatish Balay cone[4] = 20; 27839371c9d4SSatish Balay cone[5] = 9; 27849371c9d4SSatish Balay cone[6] = 10; 27859371c9d4SSatish Balay cone[7] = 18; 27869566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 27879371c9d4SSatish Balay cone[0] = 19; 27889371c9d4SSatish Balay cone[1] = 5; 27899371c9d4SSatish Balay cone[2] = 6; 27909371c9d4SSatish Balay cone[3] = 13; 27919371c9d4SSatish Balay cone[4] = 20; 27929371c9d4SSatish Balay cone[5] = 15; 27939371c9d4SSatish Balay cone[6] = 12; 27949371c9d4SSatish Balay cone[7] = 9; 27959566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 2796006a8963SMatthew G. Knepley } 2797d8c47e87SMatthew G. Knepley } 27989566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 27999566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 28000510c589SMatthew G. Knepley } 2801dbc1dc17SMatthew G. Knepley /* Create cube geometry */ 28020510c589SMatthew G. Knepley { 28030510c589SMatthew G. Knepley Vec coordinates; 28040510c589SMatthew G. Knepley PetscSection coordSection; 28050510c589SMatthew G. Knepley PetscScalar *coords; 28060510c589SMatthew G. Knepley PetscInt coordSize, v; 28070510c589SMatthew G. Knepley const PetscReal dis = 1.0 / PetscSqrtReal(2.0); 28080510c589SMatthew G. Knepley const PetscReal ds2 = dis / 2.0; 28090510c589SMatthew G. Knepley 28100510c589SMatthew G. Knepley /* Build coordinates */ 28119566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 28129566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 28139566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 28149566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 28150510c589SMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 28169566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 28179566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 28180510c589SMatthew G. Knepley } 28199566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 28209566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 28219566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 28229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 28239566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 28249566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 28259566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 28269566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 2827dd400576SPatrick Sanan if (rank == 0) { 28289371c9d4SSatish Balay coords[0 * dim + 0] = -ds2; 28299371c9d4SSatish Balay coords[0 * dim + 1] = -ds2; 28309371c9d4SSatish Balay coords[0 * dim + 2] = 0.0; 28319371c9d4SSatish Balay coords[1 * dim + 0] = ds2; 28329371c9d4SSatish Balay coords[1 * dim + 1] = -ds2; 28339371c9d4SSatish Balay coords[1 * dim + 2] = 0.0; 28349371c9d4SSatish Balay coords[2 * dim + 0] = ds2; 28359371c9d4SSatish Balay coords[2 * dim + 1] = ds2; 28369371c9d4SSatish Balay coords[2 * dim + 2] = 0.0; 28379371c9d4SSatish Balay coords[3 * dim + 0] = -ds2; 28389371c9d4SSatish Balay coords[3 * dim + 1] = ds2; 28399371c9d4SSatish Balay coords[3 * dim + 2] = 0.0; 28409371c9d4SSatish Balay coords[4 * dim + 0] = -ds2; 28419371c9d4SSatish Balay coords[4 * dim + 1] = -ds2; 28429371c9d4SSatish Balay coords[4 * dim + 2] = 1.0; 28439371c9d4SSatish Balay coords[5 * dim + 0] = -ds2; 28449371c9d4SSatish Balay coords[5 * dim + 1] = ds2; 28459371c9d4SSatish Balay coords[5 * dim + 2] = 1.0; 28469371c9d4SSatish Balay coords[6 * dim + 0] = ds2; 28479371c9d4SSatish Balay coords[6 * dim + 1] = ds2; 28489371c9d4SSatish Balay coords[6 * dim + 2] = 1.0; 28499371c9d4SSatish Balay coords[7 * dim + 0] = ds2; 28509371c9d4SSatish Balay coords[7 * dim + 1] = -ds2; 28519371c9d4SSatish Balay coords[7 * dim + 2] = 1.0; 28529371c9d4SSatish Balay coords[8 * dim + 0] = dis; 28539371c9d4SSatish Balay coords[8 * dim + 1] = -dis; 28549371c9d4SSatish Balay coords[8 * dim + 2] = 0.0; 28559371c9d4SSatish Balay coords[9 * dim + 0] = dis; 28569371c9d4SSatish Balay coords[9 * dim + 1] = dis; 28579371c9d4SSatish Balay coords[9 * dim + 2] = 0.0; 28589371c9d4SSatish Balay coords[10 * dim + 0] = dis; 28599371c9d4SSatish Balay coords[10 * dim + 1] = -dis; 28609371c9d4SSatish Balay coords[10 * dim + 2] = 1.0; 28619371c9d4SSatish Balay coords[11 * dim + 0] = dis; 28629371c9d4SSatish Balay coords[11 * dim + 1] = dis; 28639371c9d4SSatish Balay coords[11 * dim + 2] = 1.0; 28649371c9d4SSatish Balay coords[12 * dim + 0] = -dis; 28659371c9d4SSatish Balay coords[12 * dim + 1] = dis; 28669371c9d4SSatish Balay coords[12 * dim + 2] = 0.0; 28679371c9d4SSatish Balay coords[13 * dim + 0] = -dis; 28689371c9d4SSatish Balay coords[13 * dim + 1] = dis; 28699371c9d4SSatish Balay coords[13 * dim + 2] = 1.0; 28709371c9d4SSatish Balay coords[14 * dim + 0] = -dis; 28719371c9d4SSatish Balay coords[14 * dim + 1] = -dis; 28729371c9d4SSatish Balay coords[14 * dim + 2] = 0.0; 28739371c9d4SSatish Balay coords[15 * dim + 0] = -dis; 28749371c9d4SSatish Balay coords[15 * dim + 1] = -dis; 28759371c9d4SSatish Balay coords[15 * dim + 2] = 1.0; 2876ae8bcbbbSMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC) { 28779371c9d4SSatish Balay /* 15 31 19 */ coords[16 * dim + 0] = -ds2; 28789371c9d4SSatish Balay coords[16 * dim + 1] = -ds2; 28799371c9d4SSatish Balay coords[16 * dim + 2] = 0.5; 28809371c9d4SSatish Balay /* 16 32 22 */ coords[17 * dim + 0] = ds2; 28819371c9d4SSatish Balay coords[17 * dim + 1] = -ds2; 28829371c9d4SSatish Balay coords[17 * dim + 2] = 0.5; 28839371c9d4SSatish Balay /* 17 33 21 */ coords[18 * dim + 0] = ds2; 28849371c9d4SSatish Balay coords[18 * dim + 1] = ds2; 28859371c9d4SSatish Balay coords[18 * dim + 2] = 0.5; 28869371c9d4SSatish Balay /* 18 34 20 */ coords[19 * dim + 0] = -ds2; 28879371c9d4SSatish Balay coords[19 * dim + 1] = ds2; 28889371c9d4SSatish Balay coords[19 * dim + 2] = 0.5; 28899371c9d4SSatish Balay /* 29 35 30 */ coords[20 * dim + 0] = -dis; 28909371c9d4SSatish Balay coords[20 * dim + 1] = -dis; 28919371c9d4SSatish Balay coords[20 * dim + 2] = 0.5; 28929371c9d4SSatish Balay /* 23 36 25 */ coords[21 * dim + 0] = dis; 28939371c9d4SSatish Balay coords[21 * dim + 1] = -dis; 28949371c9d4SSatish Balay coords[21 * dim + 2] = 0.5; 28959371c9d4SSatish Balay /* 24 37 26 */ coords[22 * dim + 0] = dis; 28969371c9d4SSatish Balay coords[22 * dim + 1] = dis; 28979371c9d4SSatish Balay coords[22 * dim + 2] = 0.5; 28989371c9d4SSatish Balay /* 27 38 28 */ coords[23 * dim + 0] = -dis; 28999371c9d4SSatish Balay coords[23 * dim + 1] = dis; 29009371c9d4SSatish Balay coords[23 * dim + 2] = 0.5; 2901ae8bcbbbSMatthew G. Knepley } 2902d8c47e87SMatthew G. Knepley } 29039566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 29049566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 29059566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 29060510c589SMatthew G. Knepley } 2907006a8963SMatthew G. Knepley /* Create periodicity */ 2908006a8963SMatthew G. Knepley if (periodicZ == DM_BOUNDARY_PERIODIC || periodicZ == DM_BOUNDARY_TWIST) { 29096858538eSMatthew G. Knepley PetscReal L[3] = {-1., -1., 0.}; 29106858538eSMatthew G. Knepley PetscReal maxCell[3] = {-1., -1., 0.}; 2911006a8963SMatthew G. Knepley PetscReal lower[3] = {0.0, 0.0, 0.0}; 2912ae8bcbbbSMatthew G. Knepley PetscReal upper[3] = {1.0, 1.0, 1.5}; 29136858538eSMatthew G. Knepley PetscInt numZCells = 3; 2914006a8963SMatthew G. Knepley 29156858538eSMatthew G. Knepley L[2] = upper[2] - lower[2]; 29166858538eSMatthew G. Knepley maxCell[2] = 1.1 * (L[2] / numZCells); 29174fb89dddSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, maxCell, lower, L)); 2918006a8963SMatthew G. Knepley } 2919dbc1dc17SMatthew G. Knepley { 29209318fe57SMatthew G. Knepley DM cdm; 29219318fe57SMatthew G. Knepley PetscDS cds; 29229318fe57SMatthew G. Knepley PetscScalar c[2] = {1.0, 1.0}; 2923dbc1dc17SMatthew G. Knepley 2924*4c712d99Sksagiyam PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE, NULL)); 29259566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 29269566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 29279566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 2, c)); 2928dbc1dc17SMatthew G. Knepley } 292946139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 293046139095SJed Brown 29319318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 29329566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 293349704ca5SMatthew G. Knepley 293449704ca5SMatthew G. Knepley char oldprefix[PETSC_MAX_PATH_LEN]; 293549704ca5SMatthew G. Knepley const char *prefix; 293649704ca5SMatthew G. Knepley 293749704ca5SMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 293849704ca5SMatthew G. Knepley PetscCall(PetscStrncpy(oldprefix, prefix, PETSC_MAX_PATH_LEN)); 293949704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, "petsc_cyl_ref_")); 294049704ca5SMatthew G. Knepley for (PetscInt r = 0; r < PetscMax(0, Nr); ++r) { 294149704ca5SMatthew G. Knepley DM rdm; 294249704ca5SMatthew G. Knepley 294349704ca5SMatthew G. Knepley PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 294449704ca5SMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &rdm)); 294549704ca5SMatthew G. Knepley } 294649704ca5SMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldprefix)); 294749704ca5SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, snapToCylinder)); 294849704ca5SMatthew G. Knepley 294949704ca5SMatthew G. Knepley DMLabel bdlabel, edgelabel; 295049704ca5SMatthew G. Knepley IS faceIS; 295149704ca5SMatthew G. Knepley const PetscInt *faces; 295249704ca5SMatthew G. Knepley PetscInt Nf; 295349704ca5SMatthew G. Knepley 295449704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "marker")); 295549704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 295649704ca5SMatthew G. Knepley PetscCall(DMCreateLabel(dm, "generatrix")); 295749704ca5SMatthew G. Knepley PetscCall(DMGetLabel(dm, "generatrix", &edgelabel)); 295849704ca5SMatthew G. Knepley PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 295949704ca5SMatthew G. Knepley // Remove faces on top and bottom 296049704ca5SMatthew G. Knepley PetscCall(DMLabelGetStratumIS(bdlabel, 1, &faceIS)); 2961ba1b3593SJeremy L Thompson if (faceIS) { 296249704ca5SMatthew G. Knepley PetscCall(ISGetLocalSize(faceIS, &Nf)); 296349704ca5SMatthew G. Knepley PetscCall(ISGetIndices(faceIS, &faces)); 296449704ca5SMatthew G. Knepley for (PetscInt f = 0; f < Nf; ++f) { 296549704ca5SMatthew G. Knepley PetscReal vol, normal[3]; 296649704ca5SMatthew G. Knepley 296749704ca5SMatthew G. Knepley PetscCall(DMPlexComputeCellGeometryFVM(dm, faces[f], &vol, NULL, normal)); 296849704ca5SMatthew G. Knepley if (PetscAbsReal(normal[2]) < PETSC_SMALL) PetscCall(DMLabelSetValue(edgelabel, faces[f], 1)); 296949704ca5SMatthew G. Knepley } 297049704ca5SMatthew G. Knepley PetscCall(ISRestoreIndices(faceIS, &faces)); 297149704ca5SMatthew G. Knepley PetscCall(ISDestroy(&faceIS)); 2972ba1b3593SJeremy L Thompson } 297349704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, bdlabel)); 297449704ca5SMatthew G. Knepley PetscCall(DMPlexLabelComplete(dm, edgelabel)); 29753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 29760510c589SMatthew G. Knepley } 29770510c589SMatthew G. Knepley 297824119c2aSMatthew G. Knepley /*@ 29799318fe57SMatthew G. Knepley DMPlexCreateHexCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using hexahedra. 298024119c2aSMatthew G. Knepley 2981d083f849SBarry Smith Collective 298224119c2aSMatthew G. Knepley 298324119c2aSMatthew G. Knepley Input Parameters: 2984a1cb98faSBarry Smith + comm - The communicator for the `DM` object 298549704ca5SMatthew G. Knepley . periodicZ - The boundary type for the Z direction 298649704ca5SMatthew G. Knepley - Nr - The number of refinements to carry out 298724119c2aSMatthew G. Knepley 298824119c2aSMatthew G. Knepley Output Parameter: 298920f4b53cSBarry Smith . dm - The `DM` object 299024119c2aSMatthew G. Knepley 299124119c2aSMatthew G. Knepley Level: beginner 299224119c2aSMatthew G. Knepley 2993a1cb98faSBarry Smith Note: 2994a4e35b19SJacob Faibussowitsch Here is the output numbering looking from the bottom of the cylinder\: 2995a1cb98faSBarry Smith .vb 2996a1cb98faSBarry Smith 17-----14 2997a1cb98faSBarry Smith | | 2998a1cb98faSBarry Smith | 2 | 2999a1cb98faSBarry Smith | | 3000a1cb98faSBarry Smith 17-----8-----7-----14 3001a1cb98faSBarry Smith | | | | 3002a1cb98faSBarry Smith | 3 | 0 | 1 | 3003a1cb98faSBarry Smith | | | | 3004a1cb98faSBarry Smith 19-----5-----6-----13 3005a1cb98faSBarry Smith | | 3006a1cb98faSBarry Smith | 4 | 3007a1cb98faSBarry Smith | | 3008a1cb98faSBarry Smith 19-----13 3009a1cb98faSBarry Smith 3010a1cb98faSBarry Smith and up through the top 3011a1cb98faSBarry Smith 3012a1cb98faSBarry Smith 18-----16 3013a1cb98faSBarry Smith | | 3014a1cb98faSBarry Smith | 2 | 3015a1cb98faSBarry Smith | | 3016a1cb98faSBarry Smith 18----10----11-----16 3017a1cb98faSBarry Smith | | | | 3018a1cb98faSBarry Smith | 3 | 0 | 1 | 3019a1cb98faSBarry Smith | | | | 3020a1cb98faSBarry Smith 20-----9----12-----15 3021a1cb98faSBarry Smith | | 3022a1cb98faSBarry Smith | 4 | 3023a1cb98faSBarry Smith | | 3024a1cb98faSBarry Smith 20-----15 3025a1cb98faSBarry Smith .ve 3026a1cb98faSBarry Smith 30271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 302824119c2aSMatthew G. Knepley @*/ 302949704ca5SMatthew G. Knepley PetscErrorCode DMPlexCreateHexCylinderMesh(MPI_Comm comm, DMBoundaryType periodicZ, PetscInt Nr, DM *dm) 3030d71ae5a4SJacob Faibussowitsch { 30319318fe57SMatthew G. Knepley PetscFunctionBegin; 303249704ca5SMatthew G. Knepley PetscAssertPointer(dm, 4); 30339566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 30349566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 303549704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(*dm, periodicZ, Nr)); 30363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30379318fe57SMatthew G. Knepley } 30389318fe57SMatthew G. Knepley 3039d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateWedgeCylinderMesh_Internal(DM dm, PetscInt n, PetscBool interpolate) 3040d71ae5a4SJacob Faibussowitsch { 304124119c2aSMatthew G. Knepley const PetscInt dim = 3; 3042412e9a14SMatthew G. Knepley PetscInt numCells, numVertices, v; 30439fe9f049SMatthew G. Knepley PetscMPIInt rank; 304424119c2aSMatthew G. Knepley 304524119c2aSMatthew G. Knepley PetscFunctionBegin; 304663a3b9bcSJacob Faibussowitsch PetscCheck(n >= 0, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of wedges %" PetscInt_FMT " cannot be negative", n); 304746139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 30489566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 30499566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 3050412e9a14SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 30519566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "celltype")); 305224119c2aSMatthew G. Knepley /* Create topology */ 305324119c2aSMatthew G. Knepley { 305424119c2aSMatthew G. Knepley PetscInt cone[6], c; 305524119c2aSMatthew G. Knepley 3056dd400576SPatrick Sanan numCells = rank == 0 ? n : 0; 3057dd400576SPatrick Sanan numVertices = rank == 0 ? 2 * (n + 1) : 0; 30589566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 30599566063dSJacob Faibussowitsch for (c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 6)); 30609566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 306124119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 30629371c9d4SSatish Balay cone[0] = c + n * 1; 30639371c9d4SSatish Balay cone[1] = (c + 1) % n + n * 1; 30649371c9d4SSatish Balay cone[2] = 0 + 3 * n; 30659371c9d4SSatish Balay cone[3] = c + n * 2; 30669371c9d4SSatish Balay cone[4] = (c + 1) % n + n * 2; 30679371c9d4SSatish Balay cone[5] = 1 + 3 * n; 30689566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c, cone)); 30699566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(dm, c, DM_POLYTOPE_TRI_PRISM_TENSOR)); 307024119c2aSMatthew G. Knepley } 30719566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 30729566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 307324119c2aSMatthew G. Knepley } 307448a46eb9SPierre Jolivet for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(dm, v, DM_POLYTOPE_POINT)); 307524119c2aSMatthew G. Knepley /* Create cylinder geometry */ 307624119c2aSMatthew G. Knepley { 307724119c2aSMatthew G. Knepley Vec coordinates; 307824119c2aSMatthew G. Knepley PetscSection coordSection; 307924119c2aSMatthew G. Knepley PetscScalar *coords; 3080412e9a14SMatthew G. Knepley PetscInt coordSize, c; 308124119c2aSMatthew G. Knepley 308224119c2aSMatthew G. Knepley /* Build coordinates */ 30839566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 30849566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 30859566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dim)); 30869566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices)); 308724119c2aSMatthew G. Knepley for (v = numCells; v < numCells + numVertices; ++v) { 30889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dim)); 30899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dim)); 309024119c2aSMatthew G. Knepley } 30919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 30929566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 30939566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 30949566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 30959566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 30969566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, dim)); 30979566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 30989566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 309924119c2aSMatthew G. Knepley for (c = 0; c < numCells; c++) { 31009371c9d4SSatish Balay coords[(c + 0 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 31019371c9d4SSatish Balay coords[(c + 0 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 31029371c9d4SSatish Balay coords[(c + 0 * n) * dim + 2] = 1.0; 31039371c9d4SSatish Balay coords[(c + 1 * n) * dim + 0] = PetscCosReal(2.0 * c * PETSC_PI / n); 31049371c9d4SSatish Balay coords[(c + 1 * n) * dim + 1] = PetscSinReal(2.0 * c * PETSC_PI / n); 31059371c9d4SSatish Balay coords[(c + 1 * n) * dim + 2] = 0.0; 310624119c2aSMatthew G. Knepley } 3107dd400576SPatrick Sanan if (rank == 0) { 31089371c9d4SSatish Balay coords[(2 * n + 0) * dim + 0] = 0.0; 31099371c9d4SSatish Balay coords[(2 * n + 0) * dim + 1] = 0.0; 31109371c9d4SSatish Balay coords[(2 * n + 0) * dim + 2] = 1.0; 31119371c9d4SSatish Balay coords[(2 * n + 1) * dim + 0] = 0.0; 31129371c9d4SSatish Balay coords[(2 * n + 1) * dim + 1] = 0.0; 31139371c9d4SSatish Balay coords[(2 * n + 1) * dim + 2] = 0.0; 31149fe9f049SMatthew G. Knepley } 31159566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 31169566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 31179566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 311824119c2aSMatthew G. Knepley } 311946139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 31209318fe57SMatthew G. Knepley /* Interpolate */ 31219566063dSJacob Faibussowitsch if (interpolate) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 31223ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 31239318fe57SMatthew G. Knepley } 31249318fe57SMatthew G. Knepley 31259318fe57SMatthew G. Knepley /*@ 31269318fe57SMatthew G. Knepley DMPlexCreateWedgeCylinderMesh - Creates a mesh on the tensor product of the unit interval with the circle (cylinder) using wedges. 31279318fe57SMatthew G. Knepley 31289318fe57SMatthew G. Knepley Collective 31299318fe57SMatthew G. Knepley 31309318fe57SMatthew G. Knepley Input Parameters: 3131a1cb98faSBarry Smith + comm - The communicator for the `DM` object 31329318fe57SMatthew G. Knepley . n - The number of wedges around the origin 31339318fe57SMatthew G. Knepley - interpolate - Create edges and faces 31349318fe57SMatthew G. Knepley 31359318fe57SMatthew G. Knepley Output Parameter: 3136a1cb98faSBarry Smith . dm - The `DM` object 31379318fe57SMatthew G. Knepley 31389318fe57SMatthew G. Knepley Level: beginner 31399318fe57SMatthew G. Knepley 31401cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateHexCylinderMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 31419318fe57SMatthew G. Knepley @*/ 3142d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateWedgeCylinderMesh(MPI_Comm comm, PetscInt n, PetscBool interpolate, DM *dm) 3143d71ae5a4SJacob Faibussowitsch { 31449318fe57SMatthew G. Knepley PetscFunctionBegin; 31454f572ea9SToby Isaac PetscAssertPointer(dm, 4); 31469566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 31479566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 31489566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(*dm, n, interpolate)); 31493ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 315024119c2aSMatthew G. Knepley } 315124119c2aSMatthew G. Knepley 3152d71ae5a4SJacob Faibussowitsch static inline PetscReal DiffNormReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 3153d71ae5a4SJacob Faibussowitsch { 315465a81367SMatthew G. Knepley PetscReal prod = 0.0; 315565a81367SMatthew G. Knepley PetscInt i; 315665a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += PetscSqr(x[i] - y[i]); 315765a81367SMatthew G. Knepley return PetscSqrtReal(prod); 315865a81367SMatthew G. Knepley } 3159dd2b43ebSStefano Zampini 3160d71ae5a4SJacob Faibussowitsch static inline PetscReal DotReal(PetscInt dim, const PetscReal x[], const PetscReal y[]) 3161d71ae5a4SJacob Faibussowitsch { 316265a81367SMatthew G. Knepley PetscReal prod = 0.0; 316365a81367SMatthew G. Knepley PetscInt i; 316465a81367SMatthew G. Knepley for (i = 0; i < dim; ++i) prod += x[i] * y[i]; 316565a81367SMatthew G. Knepley return prod; 316665a81367SMatthew G. Knepley } 316765a81367SMatthew G. Knepley 316851a74b61SMatthew G. Knepley /* The first constant is the sphere radius */ 3169d71ae5a4SJacob 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[]) 3170d71ae5a4SJacob Faibussowitsch { 317151a74b61SMatthew G. Knepley PetscReal r = PetscRealPart(constants[0]); 317251a74b61SMatthew G. Knepley PetscReal norm2 = 0.0, fac; 317351a74b61SMatthew G. Knepley PetscInt n = uOff[1] - uOff[0], d; 317451a74b61SMatthew G. Knepley 317551a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) norm2 += PetscSqr(PetscRealPart(u[d])); 317651a74b61SMatthew G. Knepley fac = r / PetscSqrtReal(norm2); 317751a74b61SMatthew G. Knepley for (d = 0; d < n; ++d) f0[d] = u[d] * fac; 317851a74b61SMatthew G. Knepley } 317951a74b61SMatthew G. Knepley 3180d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateSphereMesh_Internal(DM dm, PetscInt dim, PetscBool simplex, PetscReal R) 3181d71ae5a4SJacob Faibussowitsch { 318265a81367SMatthew G. Knepley const PetscInt embedDim = dim + 1; 318365a81367SMatthew G. Knepley PetscSection coordSection; 318465a81367SMatthew G. Knepley Vec coordinates; 318565a81367SMatthew G. Knepley PetscScalar *coords; 318665a81367SMatthew G. Knepley PetscReal *coordsIn; 318707c565c5SJose E. Roman PetscInt numCells, numEdges, numVerts = 0, firstVertex = 0, v, firstEdge, coordSize, d, e; 318865a81367SMatthew G. Knepley PetscMPIInt rank; 318965a81367SMatthew G. Knepley 319065a81367SMatthew G. Knepley PetscFunctionBegin; 31919318fe57SMatthew G. Knepley PetscValidLogicalCollectiveBool(dm, simplex, 3); 319246139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 31939566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, dim)); 31949566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, dim + 1)); 31959566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 319665a81367SMatthew G. Knepley switch (dim) { 31975c344501SMatthew G. Knepley case 1: 31985c344501SMatthew G. Knepley numCells = 16; 31995c344501SMatthew G. Knepley numVerts = numCells; 32005c344501SMatthew G. Knepley 32015c344501SMatthew G. Knepley // Build Topology 32025c344501SMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 32035c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 32045c344501SMatthew G. Knepley PetscCall(DMSetUp(dm)); 32055c344501SMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 32065c344501SMatthew G. Knepley PetscInt cone[2]; 32075c344501SMatthew G. Knepley 32085c344501SMatthew G. Knepley cone[0] = c + numCells; 32095c344501SMatthew G. Knepley cone[1] = (c + 1) % numVerts + numCells; 32105c344501SMatthew G. Knepley PetscCall(DMPlexSetCone(dm, c, cone)); 32115c344501SMatthew G. Knepley } 32125c344501SMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 32135c344501SMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 32145c344501SMatthew G. Knepley PetscCall(PetscMalloc1(numVerts * embedDim, &coordsIn)); 32155c344501SMatthew G. Knepley for (PetscInt v = 0; v < numVerts; ++v) { 32165c344501SMatthew G. Knepley const PetscReal rad = 2. * PETSC_PI * v / numVerts; 32175c344501SMatthew G. Knepley 32185c344501SMatthew G. Knepley coordsIn[v * embedDim + 0] = PetscCosReal(rad); 32195c344501SMatthew G. Knepley coordsIn[v * embedDim + 1] = PetscSinReal(rad); 32205c344501SMatthew G. Knepley } 32215c344501SMatthew G. Knepley break; 322265a81367SMatthew G. Knepley case 2: 322365a81367SMatthew G. Knepley if (simplex) { 322451a74b61SMatthew G. Knepley const PetscReal radius = PetscSqrtReal(1 + PETSC_PHI * PETSC_PHI) / (1.0 + PETSC_PHI); 322551a74b61SMatthew G. Knepley const PetscReal edgeLen = 2.0 / (1.0 + PETSC_PHI) * (R / radius); 322665a81367SMatthew G. Knepley const PetscInt degree = 5; 322751a74b61SMatthew G. Knepley PetscReal vertex[3] = {0.0, 1.0 / (1.0 + PETSC_PHI), PETSC_PHI / (1.0 + PETSC_PHI)}; 322865a81367SMatthew G. Knepley PetscInt s[3] = {1, 1, 1}; 322965a81367SMatthew G. Knepley PetscInt cone[3]; 323007c565c5SJose E. Roman PetscInt *graph; 323165a81367SMatthew G. Knepley 32329371c9d4SSatish Balay vertex[0] *= R / radius; 32339371c9d4SSatish Balay vertex[1] *= R / radius; 32349371c9d4SSatish Balay vertex[2] *= R / radius; 3235dd400576SPatrick Sanan numCells = rank == 0 ? 20 : 0; 3236dd400576SPatrick Sanan numVerts = rank == 0 ? 12 : 0; 323765a81367SMatthew G. Knepley firstVertex = numCells; 323851a74b61SMatthew G. Knepley /* Use icosahedron, which for a R-sphere has coordinates which are all cyclic permutations of 323965a81367SMatthew G. Knepley 324065a81367SMatthew G. Knepley (0, \pm 1/\phi+1, \pm \phi/\phi+1) 324165a81367SMatthew G. Knepley 324265a81367SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 324351a74b61SMatthew G. Knepley length is then given by 2/(1+\phi) = 2 * 0.38197 = 0.76393. 324465a81367SMatthew G. Knepley */ 324565a81367SMatthew G. Knepley /* Construct vertices */ 32469566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3247dd400576SPatrick Sanan if (rank == 0) { 324807c565c5SJose E. Roman for (PetscInt p = 0, i = 0; p < embedDim; ++p) { 324965a81367SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 325065a81367SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 325165a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertex[(d + p) % embedDim]; 325265a81367SMatthew G. Knepley ++i; 325365a81367SMatthew G. Knepley } 325465a81367SMatthew G. Knepley } 325565a81367SMatthew G. Knepley } 325645da822fSValeria Barra } 325765a81367SMatthew G. Knepley /* Construct graph */ 32589566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 325907c565c5SJose E. Roman for (PetscInt i = 0; i < numVerts; ++i) { 326007c565c5SJose E. Roman PetscInt k = 0; 326107c565c5SJose E. Roman for (PetscInt j = 0; j < numVerts; ++j) { 32629371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 32639371c9d4SSatish Balay graph[i * numVerts + j] = 1; 32649371c9d4SSatish Balay ++k; 32659371c9d4SSatish Balay } 326665a81367SMatthew G. Knepley } 326763a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid icosahedron, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 326865a81367SMatthew G. Knepley } 326965a81367SMatthew G. Knepley /* Build Topology */ 32709566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 327107c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 32729566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 327365a81367SMatthew G. Knepley /* Cells */ 327407c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 327507c565c5SJose E. Roman for (PetscInt j = 0; j < i; ++j) { 327607c565c5SJose E. Roman for (PetscInt k = 0; k < j; ++k) { 327765a81367SMatthew G. Knepley if (graph[i * numVerts + j] && graph[j * numVerts + k] && graph[k * numVerts + i]) { 32789371c9d4SSatish Balay cone[0] = firstVertex + i; 32799371c9d4SSatish Balay cone[1] = firstVertex + j; 32809371c9d4SSatish Balay cone[2] = firstVertex + k; 328165a81367SMatthew G. Knepley /* Check orientation */ 328265a81367SMatthew G. Knepley { 32839371c9d4SSatish Balay const PetscInt epsilon[3][3][3] = { 32849371c9d4SSatish Balay {{0, 0, 0}, {0, 0, 1}, {0, -1, 0}}, 32859371c9d4SSatish Balay {{0, 0, -1}, {0, 0, 0}, {1, 0, 0} }, 32869371c9d4SSatish Balay {{0, 1, 0}, {-1, 0, 0}, {0, 0, 0} } 32879371c9d4SSatish Balay }; 328865a81367SMatthew G. Knepley PetscReal normal[3]; 328965a81367SMatthew G. Knepley PetscInt e, f; 329065a81367SMatthew G. Knepley 329165a81367SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 329265a81367SMatthew G. Knepley normal[d] = 0.0; 329365a81367SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3294ad540459SPierre 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]); 329565a81367SMatthew G. Knepley } 329665a81367SMatthew G. Knepley } 32979371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 32989371c9d4SSatish Balay PetscInt tmp = cone[1]; 32999371c9d4SSatish Balay cone[1] = cone[2]; 33009371c9d4SSatish Balay cone[2] = tmp; 330165a81367SMatthew G. Knepley } 330265a81367SMatthew G. Knepley } 33039566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 330465a81367SMatthew G. Knepley } 330565a81367SMatthew G. Knepley } 330665a81367SMatthew G. Knepley } 330765a81367SMatthew G. Knepley } 33089566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 33099566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 33109566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 331165a81367SMatthew G. Knepley } else { 33122829fed8SMatthew G. Knepley /* 33132829fed8SMatthew G. Knepley 12-21--13 33142829fed8SMatthew G. Knepley | | 33152829fed8SMatthew G. Knepley 25 4 24 33162829fed8SMatthew G. Knepley | | 33172829fed8SMatthew G. Knepley 12-25--9-16--8-24--13 33182829fed8SMatthew G. Knepley | | | | 33192829fed8SMatthew G. Knepley 23 5 17 0 15 3 22 33202829fed8SMatthew G. Knepley | | | | 33212829fed8SMatthew G. Knepley 10-20--6-14--7-19--11 33222829fed8SMatthew G. Knepley | | 33232829fed8SMatthew G. Knepley 20 1 19 33242829fed8SMatthew G. Knepley | | 33252829fed8SMatthew G. Knepley 10-18--11 33262829fed8SMatthew G. Knepley | | 33272829fed8SMatthew G. Knepley 23 2 22 33282829fed8SMatthew G. Knepley | | 33292829fed8SMatthew G. Knepley 12-21--13 33302829fed8SMatthew G. Knepley */ 33312829fed8SMatthew G. Knepley PetscInt cone[4], ornt[4]; 33322829fed8SMatthew G. Knepley 3333dd400576SPatrick Sanan numCells = rank == 0 ? 6 : 0; 3334dd400576SPatrick Sanan numEdges = rank == 0 ? 12 : 0; 3335dd400576SPatrick Sanan numVerts = rank == 0 ? 8 : 0; 333665a81367SMatthew G. Knepley firstVertex = numCells; 333765a81367SMatthew G. Knepley firstEdge = numCells + numVerts; 33382829fed8SMatthew G. Knepley /* Build Topology */ 33399566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numEdges + numVerts)); 334007c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, 4)); 334148a46eb9SPierre Jolivet for (e = firstEdge; e < firstEdge + numEdges; ++e) PetscCall(DMPlexSetConeSize(dm, e, 2)); 33429566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3343dd400576SPatrick Sanan if (rank == 0) { 33442829fed8SMatthew G. Knepley /* Cell 0 */ 33459371c9d4SSatish Balay cone[0] = 14; 33469371c9d4SSatish Balay cone[1] = 15; 33479371c9d4SSatish Balay cone[2] = 16; 33489371c9d4SSatish Balay cone[3] = 17; 33499566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 0, cone)); 33509371c9d4SSatish Balay ornt[0] = 0; 33519371c9d4SSatish Balay ornt[1] = 0; 33529371c9d4SSatish Balay ornt[2] = 0; 33539371c9d4SSatish Balay ornt[3] = 0; 33549566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 0, ornt)); 33552829fed8SMatthew G. Knepley /* Cell 1 */ 33569371c9d4SSatish Balay cone[0] = 18; 33579371c9d4SSatish Balay cone[1] = 19; 33589371c9d4SSatish Balay cone[2] = 14; 33599371c9d4SSatish Balay cone[3] = 20; 33609566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 1, cone)); 33619371c9d4SSatish Balay ornt[0] = 0; 33629371c9d4SSatish Balay ornt[1] = 0; 33639371c9d4SSatish Balay ornt[2] = -1; 33649371c9d4SSatish Balay ornt[3] = 0; 33659566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 1, ornt)); 33662829fed8SMatthew G. Knepley /* Cell 2 */ 33679371c9d4SSatish Balay cone[0] = 21; 33689371c9d4SSatish Balay cone[1] = 22; 33699371c9d4SSatish Balay cone[2] = 18; 33709371c9d4SSatish Balay cone[3] = 23; 33719566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 2, cone)); 33729371c9d4SSatish Balay ornt[0] = 0; 33739371c9d4SSatish Balay ornt[1] = 0; 33749371c9d4SSatish Balay ornt[2] = -1; 33759371c9d4SSatish Balay ornt[3] = 0; 33769566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 2, ornt)); 33772829fed8SMatthew G. Knepley /* Cell 3 */ 33789371c9d4SSatish Balay cone[0] = 19; 33799371c9d4SSatish Balay cone[1] = 22; 33809371c9d4SSatish Balay cone[2] = 24; 33819371c9d4SSatish Balay cone[3] = 15; 33829566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 3, cone)); 33839371c9d4SSatish Balay ornt[0] = -1; 33849371c9d4SSatish Balay ornt[1] = -1; 33859371c9d4SSatish Balay ornt[2] = 0; 33869371c9d4SSatish Balay ornt[3] = -1; 33879566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 3, ornt)); 33882829fed8SMatthew G. Knepley /* Cell 4 */ 33899371c9d4SSatish Balay cone[0] = 16; 33909371c9d4SSatish Balay cone[1] = 24; 33919371c9d4SSatish Balay cone[2] = 21; 33929371c9d4SSatish Balay cone[3] = 25; 33939566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 4, cone)); 33949371c9d4SSatish Balay ornt[0] = -1; 33959371c9d4SSatish Balay ornt[1] = -1; 33969371c9d4SSatish Balay ornt[2] = -1; 33979371c9d4SSatish Balay ornt[3] = 0; 33989566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 4, ornt)); 33992829fed8SMatthew G. Knepley /* Cell 5 */ 34009371c9d4SSatish Balay cone[0] = 20; 34019371c9d4SSatish Balay cone[1] = 17; 34029371c9d4SSatish Balay cone[2] = 25; 34039371c9d4SSatish Balay cone[3] = 23; 34049566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 5, cone)); 34059371c9d4SSatish Balay ornt[0] = -1; 34069371c9d4SSatish Balay ornt[1] = -1; 34079371c9d4SSatish Balay ornt[2] = -1; 34089371c9d4SSatish Balay ornt[3] = -1; 34099566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, 5, ornt)); 34102829fed8SMatthew G. Knepley /* Edges */ 34119371c9d4SSatish Balay cone[0] = 6; 34129371c9d4SSatish Balay cone[1] = 7; 34139566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 14, cone)); 34149371c9d4SSatish Balay cone[0] = 7; 34159371c9d4SSatish Balay cone[1] = 8; 34169566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 15, cone)); 34179371c9d4SSatish Balay cone[0] = 8; 34189371c9d4SSatish Balay cone[1] = 9; 34199566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 16, cone)); 34209371c9d4SSatish Balay cone[0] = 9; 34219371c9d4SSatish Balay cone[1] = 6; 34229566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 17, cone)); 34239371c9d4SSatish Balay cone[0] = 10; 34249371c9d4SSatish Balay cone[1] = 11; 34259566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 18, cone)); 34269371c9d4SSatish Balay cone[0] = 11; 34279371c9d4SSatish Balay cone[1] = 7; 34289566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 19, cone)); 34299371c9d4SSatish Balay cone[0] = 6; 34309371c9d4SSatish Balay cone[1] = 10; 34319566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 20, cone)); 34329371c9d4SSatish Balay cone[0] = 12; 34339371c9d4SSatish Balay cone[1] = 13; 34349566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 21, cone)); 34359371c9d4SSatish Balay cone[0] = 13; 34369371c9d4SSatish Balay cone[1] = 11; 34379566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 22, cone)); 34389371c9d4SSatish Balay cone[0] = 10; 34399371c9d4SSatish Balay cone[1] = 12; 34409566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 23, cone)); 34419371c9d4SSatish Balay cone[0] = 13; 34429371c9d4SSatish Balay cone[1] = 8; 34439566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 24, cone)); 34449371c9d4SSatish Balay cone[0] = 12; 34459371c9d4SSatish Balay cone[1] = 9; 34469566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, 25, cone)); 344745da822fSValeria Barra } 34489566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 34499566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 34502829fed8SMatthew G. Knepley /* Build coordinates */ 34519566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3452dd400576SPatrick Sanan if (rank == 0) { 34539371c9d4SSatish Balay coordsIn[0 * embedDim + 0] = -R; 34549371c9d4SSatish Balay coordsIn[0 * embedDim + 1] = R; 34559371c9d4SSatish Balay coordsIn[0 * embedDim + 2] = -R; 34569371c9d4SSatish Balay coordsIn[1 * embedDim + 0] = R; 34579371c9d4SSatish Balay coordsIn[1 * embedDim + 1] = R; 34589371c9d4SSatish Balay coordsIn[1 * embedDim + 2] = -R; 34599371c9d4SSatish Balay coordsIn[2 * embedDim + 0] = R; 34609371c9d4SSatish Balay coordsIn[2 * embedDim + 1] = -R; 34619371c9d4SSatish Balay coordsIn[2 * embedDim + 2] = -R; 34629371c9d4SSatish Balay coordsIn[3 * embedDim + 0] = -R; 34639371c9d4SSatish Balay coordsIn[3 * embedDim + 1] = -R; 34649371c9d4SSatish Balay coordsIn[3 * embedDim + 2] = -R; 34659371c9d4SSatish Balay coordsIn[4 * embedDim + 0] = -R; 34669371c9d4SSatish Balay coordsIn[4 * embedDim + 1] = R; 34679371c9d4SSatish Balay coordsIn[4 * embedDim + 2] = R; 34689371c9d4SSatish Balay coordsIn[5 * embedDim + 0] = R; 34699371c9d4SSatish Balay coordsIn[5 * embedDim + 1] = R; 34709371c9d4SSatish Balay coordsIn[5 * embedDim + 2] = R; 34719371c9d4SSatish Balay coordsIn[6 * embedDim + 0] = -R; 34729371c9d4SSatish Balay coordsIn[6 * embedDim + 1] = -R; 34739371c9d4SSatish Balay coordsIn[6 * embedDim + 2] = R; 34749371c9d4SSatish Balay coordsIn[7 * embedDim + 0] = R; 34759371c9d4SSatish Balay coordsIn[7 * embedDim + 1] = -R; 34769371c9d4SSatish Balay coordsIn[7 * embedDim + 2] = R; 347765a81367SMatthew G. Knepley } 347845da822fSValeria Barra } 347965a81367SMatthew G. Knepley break; 348065a81367SMatthew G. Knepley case 3: 3481116ded15SMatthew G. Knepley if (simplex) { 3482116ded15SMatthew G. Knepley const PetscReal edgeLen = 1.0 / PETSC_PHI; 348351a74b61SMatthew G. Knepley PetscReal vertexA[4] = {0.5, 0.5, 0.5, 0.5}; 348451a74b61SMatthew G. Knepley PetscReal vertexB[4] = {1.0, 0.0, 0.0, 0.0}; 348551a74b61SMatthew G. Knepley PetscReal vertexC[4] = {0.5, 0.5 * PETSC_PHI, 0.5 / PETSC_PHI, 0.0}; 3486116ded15SMatthew G. Knepley const PetscInt degree = 12; 3487116ded15SMatthew G. Knepley PetscInt s[4] = {1, 1, 1}; 34889371c9d4SSatish Balay PetscInt evenPerm[12][4] = { 34899371c9d4SSatish Balay {0, 1, 2, 3}, 34909371c9d4SSatish Balay {0, 2, 3, 1}, 34919371c9d4SSatish Balay {0, 3, 1, 2}, 34929371c9d4SSatish Balay {1, 0, 3, 2}, 34939371c9d4SSatish Balay {1, 2, 0, 3}, 34949371c9d4SSatish Balay {1, 3, 2, 0}, 34959371c9d4SSatish Balay {2, 0, 1, 3}, 34969371c9d4SSatish Balay {2, 1, 3, 0}, 34979371c9d4SSatish Balay {2, 3, 0, 1}, 34989371c9d4SSatish Balay {3, 0, 2, 1}, 34999371c9d4SSatish Balay {3, 1, 0, 2}, 35009371c9d4SSatish Balay {3, 2, 1, 0} 35019371c9d4SSatish Balay }; 3502116ded15SMatthew G. Knepley PetscInt cone[4]; 3503116ded15SMatthew G. Knepley PetscInt *graph, p, i, j, k, l; 3504116ded15SMatthew G. Knepley 35059371c9d4SSatish Balay vertexA[0] *= R; 35069371c9d4SSatish Balay vertexA[1] *= R; 35079371c9d4SSatish Balay vertexA[2] *= R; 35089371c9d4SSatish Balay vertexA[3] *= R; 35099371c9d4SSatish Balay vertexB[0] *= R; 35109371c9d4SSatish Balay vertexB[1] *= R; 35119371c9d4SSatish Balay vertexB[2] *= R; 35129371c9d4SSatish Balay vertexB[3] *= R; 35139371c9d4SSatish Balay vertexC[0] *= R; 35149371c9d4SSatish Balay vertexC[1] *= R; 35159371c9d4SSatish Balay vertexC[2] *= R; 35169371c9d4SSatish Balay vertexC[3] *= R; 3517dd400576SPatrick Sanan numCells = rank == 0 ? 600 : 0; 3518dd400576SPatrick Sanan numVerts = rank == 0 ? 120 : 0; 3519116ded15SMatthew G. Knepley firstVertex = numCells; 3520116ded15SMatthew G. Knepley /* Use the 600-cell, which for a unit sphere has coordinates which are 3521116ded15SMatthew G. Knepley 3522116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm 1, \pm 1, \pm 1) 16 3523116ded15SMatthew G. Knepley (\pm 1, 0, 0, 0) all cyclic permutations 8 3524116ded15SMatthew G. Knepley 1/2 (\pm 1, \pm phi, \pm 1/phi, 0) all even permutations 96 3525116ded15SMatthew G. Knepley 3526116ded15SMatthew G. Knepley where \phi^2 - \phi - 1 = 0, meaning \phi is the golden ratio \frac{1 + \sqrt{5}}{2}. The edge 35276333ae4fSvaleriabarra length is then given by 1/\phi = 0.61803. 3528116ded15SMatthew G. Knepley 3529116ded15SMatthew G. Knepley http://buzzard.pugetsound.edu/sage-practice/ch03s03.html 3530116ded15SMatthew G. Knepley http://mathworld.wolfram.com/600-Cell.html 3531116ded15SMatthew G. Knepley */ 3532116ded15SMatthew G. Knepley /* Construct vertices */ 35339566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * embedDim, &coordsIn)); 3534116ded15SMatthew G. Knepley i = 0; 3535dd400576SPatrick Sanan if (rank == 0) { 3536116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3537116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3538116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3539116ded15SMatthew G. Knepley for (s[3] = -1; s[3] < 2; s[3] += 2) { 3540116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[d] * vertexA[d]; 3541116ded15SMatthew G. Knepley ++i; 3542116ded15SMatthew G. Knepley } 3543116ded15SMatthew G. Knepley } 3544116ded15SMatthew G. Knepley } 3545116ded15SMatthew G. Knepley } 3546116ded15SMatthew G. Knepley for (p = 0; p < embedDim; ++p) { 3547116ded15SMatthew G. Knepley s[1] = s[2] = s[3] = 1; 3548116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3549116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[(d + p) % embedDim] * vertexB[(d + p) % embedDim]; 3550116ded15SMatthew G. Knepley ++i; 3551116ded15SMatthew G. Knepley } 3552116ded15SMatthew G. Knepley } 3553116ded15SMatthew G. Knepley for (p = 0; p < 12; ++p) { 3554116ded15SMatthew G. Knepley s[3] = 1; 3555116ded15SMatthew G. Knepley for (s[0] = -1; s[0] < 2; s[0] += 2) { 3556116ded15SMatthew G. Knepley for (s[1] = -1; s[1] < 2; s[1] += 2) { 3557116ded15SMatthew G. Knepley for (s[2] = -1; s[2] < 2; s[2] += 2) { 3558116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) coordsIn[i * embedDim + d] = s[evenPerm[p][d]] * vertexC[evenPerm[p][d]]; 3559116ded15SMatthew G. Knepley ++i; 3560116ded15SMatthew G. Knepley } 3561116ded15SMatthew G. Knepley } 3562116ded15SMatthew G. Knepley } 3563116ded15SMatthew G. Knepley } 356445da822fSValeria Barra } 356563a3b9bcSJacob Faibussowitsch PetscCheck(i == numVerts, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertices %" PetscInt_FMT " != %" PetscInt_FMT, i, numVerts); 3566116ded15SMatthew G. Knepley /* Construct graph */ 35679566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numVerts * numVerts, &graph)); 3568116ded15SMatthew G. Knepley for (i = 0; i < numVerts; ++i) { 3569116ded15SMatthew G. Knepley for (j = 0, k = 0; j < numVerts; ++j) { 35709371c9d4SSatish Balay if (PetscAbsReal(DiffNormReal(embedDim, &coordsIn[i * embedDim], &coordsIn[j * embedDim]) - edgeLen) < PETSC_SMALL) { 35719371c9d4SSatish Balay graph[i * numVerts + j] = 1; 35729371c9d4SSatish Balay ++k; 35739371c9d4SSatish Balay } 3574116ded15SMatthew G. Knepley } 357563a3b9bcSJacob Faibussowitsch PetscCheck(k == degree, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid 600-cell, vertex %" PetscInt_FMT " degree %" PetscInt_FMT " != %" PetscInt_FMT, i, k, degree); 3576116ded15SMatthew G. Knepley } 3577116ded15SMatthew G. Knepley /* Build Topology */ 35789566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerts)); 357907c565c5SJose E. Roman for (PetscInt c = 0; c < numCells; c++) PetscCall(DMPlexSetConeSize(dm, c, embedDim)); 35809566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 3581116ded15SMatthew G. Knepley /* Cells */ 3582dd400576SPatrick Sanan if (rank == 0) { 358307c565c5SJose E. Roman for (PetscInt i = 0, c = 0; i < numVerts; ++i) { 3584116ded15SMatthew G. Knepley for (j = 0; j < i; ++j) { 3585116ded15SMatthew G. Knepley for (k = 0; k < j; ++k) { 3586116ded15SMatthew G. Knepley for (l = 0; l < k; ++l) { 35879371c9d4SSatish 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]) { 35889371c9d4SSatish Balay cone[0] = firstVertex + i; 35899371c9d4SSatish Balay cone[1] = firstVertex + j; 35909371c9d4SSatish Balay cone[2] = firstVertex + k; 35919371c9d4SSatish Balay cone[3] = firstVertex + l; 3592116ded15SMatthew G. Knepley /* Check orientation: https://ef.gy/linear-algebra:normal-vectors-in-higher-dimensional-spaces */ 3593116ded15SMatthew G. Knepley { 35949371c9d4SSatish Balay const PetscInt epsilon[4][4][4][4] = { 35959371c9d4SSatish 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}}}, 3596116ded15SMatthew G. Knepley 35979371c9d4SSatish 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}}}, 3598116ded15SMatthew G. Knepley 35999371c9d4SSatish 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}}}, 3600116ded15SMatthew G. Knepley 36019371c9d4SSatish 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}} } 36029371c9d4SSatish Balay }; 3603116ded15SMatthew G. Knepley PetscReal normal[4]; 3604116ded15SMatthew G. Knepley PetscInt e, f, g; 3605116ded15SMatthew G. Knepley 3606116ded15SMatthew G. Knepley for (d = 0; d < embedDim; ++d) { 3607116ded15SMatthew G. Knepley normal[d] = 0.0; 3608116ded15SMatthew G. Knepley for (e = 0; e < embedDim; ++e) { 3609116ded15SMatthew G. Knepley for (f = 0; f < embedDim; ++f) { 3610116ded15SMatthew G. Knepley for (g = 0; g < embedDim; ++g) { 3611116ded15SMatthew 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]); 3612116ded15SMatthew G. Knepley } 3613116ded15SMatthew G. Knepley } 3614116ded15SMatthew G. Knepley } 3615116ded15SMatthew G. Knepley } 36169371c9d4SSatish Balay if (DotReal(embedDim, normal, &coordsIn[i * embedDim]) < 0) { 36179371c9d4SSatish Balay PetscInt tmp = cone[1]; 36189371c9d4SSatish Balay cone[1] = cone[2]; 36199371c9d4SSatish Balay cone[2] = tmp; 36209371c9d4SSatish Balay } 3621116ded15SMatthew G. Knepley } 36229566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, c++, cone)); 3623116ded15SMatthew G. Knepley } 3624116ded15SMatthew G. Knepley } 3625116ded15SMatthew G. Knepley } 3626116ded15SMatthew G. Knepley } 3627116ded15SMatthew G. Knepley } 362845da822fSValeria Barra } 36299566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 36309566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 36319566063dSJacob Faibussowitsch PetscCall(PetscFree(graph)); 3632116ded15SMatthew G. Knepley } 3633f4d061e9SPierre Jolivet break; 3634d71ae5a4SJacob Faibussowitsch default: 3635d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Unsupported dimension for sphere: %" PetscInt_FMT, dim); 363665a81367SMatthew G. Knepley } 363765a81367SMatthew G. Knepley /* Create coordinates */ 36389566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 36399566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 36409566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, embedDim)); 36419566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numVerts)); 36422829fed8SMatthew G. Knepley for (v = firstVertex; v < firstVertex + numVerts; ++v) { 36439566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, embedDim)); 36449566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, embedDim)); 36452829fed8SMatthew G. Knepley } 36469566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 36479566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 36489566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 36499566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, embedDim)); 36509566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 36519566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 36529566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 36539566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 36549371c9d4SSatish Balay for (v = 0; v < numVerts; ++v) 3655ad540459SPierre Jolivet for (d = 0; d < embedDim; ++d) coords[v * embedDim + d] = coordsIn[v * embedDim + d]; 36569566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 36579566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 36589566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 36599566063dSJacob Faibussowitsch PetscCall(PetscFree(coordsIn)); 366051a74b61SMatthew G. Knepley { 366151a74b61SMatthew G. Knepley DM cdm; 366251a74b61SMatthew G. Knepley PetscDS cds; 36639318fe57SMatthew G. Knepley PetscScalar c = R; 366451a74b61SMatthew G. Knepley 3665509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, snapToSphere)); 3666*4c712d99Sksagiyam PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE, NULL)); 36679566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 36689566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 36699566063dSJacob Faibussowitsch PetscCall(PetscDSSetConstants(cds, 1, &c)); 367051a74b61SMatthew G. Knepley } 367146139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 36729318fe57SMatthew G. Knepley /* Wait for coordinate creation before doing in-place modification */ 36739566063dSJacob Faibussowitsch if (simplex) PetscCall(DMPlexInterpolateInPlace_Internal(dm)); 36743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 36759318fe57SMatthew G. Knepley } 36769318fe57SMatthew G. Knepley 3677b7f5c055SJed Brown typedef void (*TPSEvaluateFunc)(const PetscReal[], PetscReal *, PetscReal[], PetscReal (*)[3]); 3678b7f5c055SJed Brown 3679b7f5c055SJed Brown /* 3680b7f5c055SJed Brown The Schwarz P implicit surface is 3681b7f5c055SJed Brown 3682b7f5c055SJed Brown f(x) = cos(x0) + cos(x1) + cos(x2) = 0 3683b7f5c055SJed Brown */ 3684d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_SchwarzP(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3685d71ae5a4SJacob Faibussowitsch { 3686b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(y[0] * PETSC_PI), PetscCosReal(y[1] * PETSC_PI), PetscCosReal(y[2] * PETSC_PI)}; 3687b7f5c055SJed Brown PetscReal g[3] = {-PetscSinReal(y[0] * PETSC_PI), -PetscSinReal(y[1] * PETSC_PI), -PetscSinReal(y[2] * PETSC_PI)}; 3688b7f5c055SJed Brown f[0] = c[0] + c[1] + c[2]; 3689b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3690b7f5c055SJed Brown grad[i] = PETSC_PI * g[i]; 3691ad540459SPierre Jolivet for (PetscInt j = 0; j < 3; j++) hess[i][j] = (i == j) ? -PetscSqr(PETSC_PI) * c[i] : 0.; 3692b7f5c055SJed Brown } 3693b7f5c055SJed Brown } 3694b7f5c055SJed Brown 36954663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3696d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_SchwarzP(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3697d71ae5a4SJacob Faibussowitsch { 3698ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) u[i] = -PETSC_PI * PetscSinReal(x[i] * PETSC_PI); 36993ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 37004663dae6SJed Brown } 37014663dae6SJed Brown 3702b7f5c055SJed Brown /* 3703b7f5c055SJed Brown The Gyroid implicit surface is 3704b7f5c055SJed Brown 3705b7f5c055SJed 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) 3706b7f5c055SJed Brown 3707b7f5c055SJed Brown */ 3708d71ae5a4SJacob Faibussowitsch static void TPSEvaluate_Gyroid(const PetscReal y[3], PetscReal *f, PetscReal grad[], PetscReal (*hess)[3]) 3709d71ae5a4SJacob Faibussowitsch { 3710b7f5c055SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * y[0]), PetscSinReal(PETSC_PI * (y[1] + .5)), PetscSinReal(PETSC_PI * (y[2] + .25))}; 3711b7f5c055SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * y[0]), PetscCosReal(PETSC_PI * (y[1] + .5)), PetscCosReal(PETSC_PI * (y[2] + .25))}; 3712b7f5c055SJed Brown f[0] = s[0] * c[1] + s[1] * c[2] + s[2] * c[0]; 3713b7f5c055SJed Brown grad[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 3714b7f5c055SJed Brown grad[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 3715b7f5c055SJed Brown grad[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 3716b7f5c055SJed Brown hess[0][0] = -PetscSqr(PETSC_PI) * (s[0] * c[1] + s[2] * c[0]); 3717b7f5c055SJed Brown hess[0][1] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3718b7f5c055SJed Brown hess[0][2] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3719b7f5c055SJed Brown hess[1][0] = -PetscSqr(PETSC_PI) * (s[1] * c[2] + s[0] * c[1]); 3720b7f5c055SJed Brown hess[1][1] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3721b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[0] * s[1]); 3722b7f5c055SJed Brown hess[2][0] = -PetscSqr(PETSC_PI) * (s[2] * c[0] + s[1] * c[2]); 3723b7f5c055SJed Brown hess[2][1] = -PetscSqr(PETSC_PI) * (c[2] * s[0]); 3724b7f5c055SJed Brown hess[2][2] = -PetscSqr(PETSC_PI) * (c[1] * s[2]); 3725b7f5c055SJed Brown } 3726b7f5c055SJed Brown 37274663dae6SJed Brown // u[] is a tentative normal on input. Replace with the implicit function gradient in the same direction 3728d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSExtrudeNormalFunc_Gyroid(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt r, PetscScalar u[], void *ctx) 3729d71ae5a4SJacob Faibussowitsch { 37304663dae6SJed Brown PetscReal s[3] = {PetscSinReal(PETSC_PI * x[0]), PetscSinReal(PETSC_PI * (x[1] + .5)), PetscSinReal(PETSC_PI * (x[2] + .25))}; 37314663dae6SJed Brown PetscReal c[3] = {PetscCosReal(PETSC_PI * x[0]), PetscCosReal(PETSC_PI * (x[1] + .5)), PetscCosReal(PETSC_PI * (x[2] + .25))}; 37324663dae6SJed Brown u[0] = PETSC_PI * (c[0] * c[1] - s[2] * s[0]); 37334663dae6SJed Brown u[1] = PETSC_PI * (c[1] * c[2] - s[0] * s[1]); 37344663dae6SJed Brown u[2] = PETSC_PI * (c[2] * c[0] - s[1] * s[2]); 37353ba16761SJacob Faibussowitsch return PETSC_SUCCESS; 37364663dae6SJed Brown } 37374663dae6SJed Brown 3738b7f5c055SJed Brown /* 3739b7f5c055SJed Brown We wish to solve 3740b7f5c055SJed Brown 3741b7f5c055SJed Brown min_y || y - x ||^2 subject to f(y) = 0 3742b7f5c055SJed Brown 3743b7f5c055SJed Brown Let g(y) = grad(f). The minimization problem is equivalent to asking to satisfy 3744b7f5c055SJed 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 3745b7f5c055SJed Brown tangent space and ask for both components in the tangent space to be zero. 3746b7f5c055SJed Brown 3747b7f5c055SJed Brown Take g to be a column vector and compute the "full QR" factorization Q R = g, 3748b7f5c055SJed Brown where Q = I - 2 n n^T is a symmetric orthogonal matrix. 3749b7f5c055SJed Brown The first column of Q is parallel to g so the remaining two columns span the null space. 3750b7f5c055SJed Brown Let Qn = Q[:,1:] be those remaining columns. Then Qn Qn^T is an orthogonal projector into the tangent space. 3751da81f932SPierre Jolivet Since Q is symmetric, this is equivalent to multiplying by Q and taking the last two entries. 3752b7f5c055SJed Brown In total, we have a system of 3 equations in 3 unknowns: 3753b7f5c055SJed Brown 3754b7f5c055SJed Brown f(y) = 0 1 equation 3755b7f5c055SJed Brown Qn^T (y - x) = 0 2 equations 3756b7f5c055SJed Brown 3757b7f5c055SJed Brown Here, we compute the residual and Jacobian of this system. 3758b7f5c055SJed Brown */ 3759d71ae5a4SJacob Faibussowitsch static void TPSNearestPointResJac(TPSEvaluateFunc feval, const PetscScalar x[], const PetscScalar y[], PetscScalar res[], PetscScalar J[]) 3760d71ae5a4SJacob Faibussowitsch { 3761b7f5c055SJed Brown PetscReal yreal[3] = {PetscRealPart(y[0]), PetscRealPart(y[1]), PetscRealPart(y[2])}; 3762b7f5c055SJed Brown PetscReal d[3] = {PetscRealPart(y[0] - x[0]), PetscRealPart(y[1] - x[1]), PetscRealPart(y[2] - x[2])}; 37632f0490c0SSatish Balay PetscReal f, grad[3], n[3], norm, norm_y[3], nd, nd_y[3], sign; 37649371c9d4SSatish Balay PetscReal n_y[3][3] = { 37659371c9d4SSatish Balay {0, 0, 0}, 37669371c9d4SSatish Balay {0, 0, 0}, 37679371c9d4SSatish Balay {0, 0, 0} 37689371c9d4SSatish Balay }; 3769b7f5c055SJed Brown 3770b7f5c055SJed Brown feval(yreal, &f, grad, n_y); 3771b7f5c055SJed Brown 3772b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n[i] = grad[i]; 3773b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3774ad540459SPierre Jolivet for (PetscInt i = 0; i < 3; i++) norm_y[i] = 1. / norm * n[i] * n_y[i][i]; 3775b7f5c055SJed Brown 3776b7f5c055SJed Brown // Define the Householder reflector 3777b7f5c055SJed Brown sign = n[0] >= 0 ? 1. : -1.; 3778b7f5c055SJed Brown n[0] += norm * sign; 3779b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) n_y[0][i] += norm_y[i] * sign; 3780b7f5c055SJed Brown 3781b7f5c055SJed Brown norm = PetscSqrtReal(PetscSqr(n[0]) + PetscSqr(n[1]) + PetscSqr(n[2])); 3782b7f5c055SJed Brown norm_y[0] = 1. / norm * (n[0] * n_y[0][0]); 3783b7f5c055SJed Brown norm_y[1] = 1. / norm * (n[0] * n_y[0][1] + n[1] * n_y[1][1]); 3784b7f5c055SJed Brown norm_y[2] = 1. / norm * (n[0] * n_y[0][2] + n[2] * n_y[2][2]); 3785b7f5c055SJed Brown 3786b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) { 3787b7f5c055SJed Brown n[i] /= norm; 3788b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3789b7f5c055SJed Brown // note that n[i] is n_old[i]/norm when executing the code below 3790b7f5c055SJed Brown n_y[i][j] = n_y[i][j] / norm - n[i] / norm * norm_y[j]; 3791b7f5c055SJed Brown } 3792b7f5c055SJed Brown } 3793b7f5c055SJed Brown 3794b7f5c055SJed Brown nd = n[0] * d[0] + n[1] * d[1] + n[2] * d[2]; 3795b7f5c055SJed 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]; 3796b7f5c055SJed Brown 3797b7f5c055SJed Brown res[0] = f; 3798b7f5c055SJed Brown res[1] = d[1] - 2 * n[1] * nd; 3799b7f5c055SJed Brown res[2] = d[2] - 2 * n[2] * nd; 3800b7f5c055SJed Brown // J[j][i] is J_{ij} (column major) 3801b7f5c055SJed Brown for (PetscInt j = 0; j < 3; j++) { 3802b7f5c055SJed Brown J[0 + j * 3] = grad[j]; 3803b7f5c055SJed Brown J[1 + j * 3] = (j == 1) * 1. - 2 * (n_y[1][j] * nd + n[1] * nd_y[j]); 3804b7f5c055SJed Brown J[2 + j * 3] = (j == 2) * 1. - 2 * (n_y[2][j] * nd + n[2] * nd_y[j]); 3805b7f5c055SJed Brown } 3806b7f5c055SJed Brown } 3807b7f5c055SJed Brown 3808b7f5c055SJed Brown /* 3809b7f5c055SJed Brown Project x to the nearest point on the implicit surface using Newton's method. 3810b7f5c055SJed Brown */ 3811d71ae5a4SJacob Faibussowitsch static PetscErrorCode TPSNearestPoint(TPSEvaluateFunc feval, PetscScalar x[]) 3812d71ae5a4SJacob Faibussowitsch { 3813b7f5c055SJed Brown PetscScalar y[3] = {x[0], x[1], x[2]}; // Initial guess 3814b7f5c055SJed Brown 3815b7f5c055SJed Brown PetscFunctionBegin; 3816b7f5c055SJed Brown for (PetscInt iter = 0; iter < 10; iter++) { 3817b7f5c055SJed Brown PetscScalar res[3], J[9]; 3818b7f5c055SJed Brown PetscReal resnorm; 3819b7f5c055SJed Brown TPSNearestPointResJac(feval, x, y, res, J); 3820b7f5c055SJed Brown resnorm = PetscSqrtReal(PetscSqr(PetscRealPart(res[0])) + PetscSqr(PetscRealPart(res[1])) + PetscSqr(PetscRealPart(res[2]))); 3821b7f5c055SJed Brown if (0) { // Turn on this monitor if you need to confirm quadratic convergence 382263a3b9bcSJacob 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]))); 3823b7f5c055SJed Brown } 3824b7f5c055SJed Brown if (resnorm < PETSC_SMALL) break; 3825b7f5c055SJed Brown 3826b7f5c055SJed Brown // Take the Newton step 38279566063dSJacob Faibussowitsch PetscCall(PetscKernel_A_gets_inverse_A_3(J, 0., PETSC_FALSE, NULL)); 3828b7f5c055SJed Brown PetscKernel_v_gets_v_minus_A_times_w_3(y, J, res); 3829b7f5c055SJed Brown } 3830b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) x[i] = y[i]; 38313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3832b7f5c055SJed Brown } 3833b7f5c055SJed Brown 3834b7f5c055SJed Brown const char *const DMPlexTPSTypes[] = {"SCHWARZ_P", "GYROID", "DMPlexTPSType", "DMPLEX_TPS_", NULL}; 3835b7f5c055SJed Brown 3836d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateTPSMesh_Internal(DM dm, DMPlexTPSType tpstype, const PetscInt extent[], const DMBoundaryType periodic[], PetscBool tps_distribute, PetscInt refinements, PetscInt layers, PetscReal thickness) 3837d71ae5a4SJacob Faibussowitsch { 3838b7f5c055SJed Brown PetscMPIInt rank; 3839b7f5c055SJed Brown PetscInt topoDim = 2, spaceDim = 3, numFaces = 0, numVertices = 0, numEdges = 0; 3840b7f5c055SJed Brown PetscInt (*edges)[2] = NULL, *edgeSets = NULL; 3841b7f5c055SJed Brown PetscInt *cells_flat = NULL; 3842b7f5c055SJed Brown PetscReal *vtxCoords = NULL; 3843b7f5c055SJed Brown TPSEvaluateFunc evalFunc = NULL; 38448434afd1SBarry Smith PetscSimplePointFn *normalFunc = NULL; 3845b7f5c055SJed Brown DMLabel label; 3846b7f5c055SJed Brown 3847b7f5c055SJed Brown PetscFunctionBegin; 384846139095SJed Brown PetscCall(PetscLogEventBegin(DMPLEX_Generate, dm, 0, 0, 0)); 38499566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 385063a3b9bcSJacob 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); 3851b7f5c055SJed Brown switch (tpstype) { 3852b7f5c055SJed Brown case DMPLEX_TPS_SCHWARZ_P: 3853b7f5c055SJed 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"); 3854c5853193SPierre Jolivet if (rank == 0) { 3855b7f5c055SJed Brown PetscInt (*cells)[6][4][4] = NULL; // [junction, junction-face, cell, conn] 3856b7f5c055SJed Brown PetscInt Njunctions = 0, Ncuts = 0, Npipes[3], vcount; 3857b7f5c055SJed Brown PetscReal L = 1; 3858b7f5c055SJed Brown 3859b7f5c055SJed Brown Npipes[0] = (extent[0] + 1) * extent[1] * extent[2]; 3860b7f5c055SJed Brown Npipes[1] = extent[0] * (extent[1] + 1) * extent[2]; 3861b7f5c055SJed Brown Npipes[2] = extent[0] * extent[1] * (extent[2] + 1); 3862b7f5c055SJed Brown Njunctions = extent[0] * extent[1] * extent[2]; 3863b7f5c055SJed Brown Ncuts = 2 * (extent[0] * extent[1] + extent[1] * extent[2] + extent[2] * extent[0]); 3864b7f5c055SJed Brown numVertices = 4 * (Npipes[0] + Npipes[1] + Npipes[2]) + 8 * Njunctions; 38659566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(3 * numVertices, &vtxCoords)); 38669566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Njunctions, &cells)); 38679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edges)); 38689566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(Ncuts * 4, &edgeSets)); 3869b7f5c055SJed Brown // x-normal pipes 3870b7f5c055SJed Brown vcount = 0; 3871b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0] + 1; i++) { 3872b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3873b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3874b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3875b7f5c055SJed Brown vtxCoords[vcount++] = (2 * i - 1) * L; 3876b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3877b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3878b7f5c055SJed Brown } 3879b7f5c055SJed Brown } 3880b7f5c055SJed Brown } 3881b7f5c055SJed Brown } 3882b7f5c055SJed Brown // y-normal pipes 3883b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3884b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1] + 1; j++) { 3885b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3886b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3887b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3888b7f5c055SJed Brown vtxCoords[vcount++] = (2 * j - 1) * L; 3889b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3890b7f5c055SJed Brown } 3891b7f5c055SJed Brown } 3892b7f5c055SJed Brown } 3893b7f5c055SJed Brown } 3894b7f5c055SJed Brown // z-normal pipes 3895b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3896b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3897b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2] + 1; k++) { 3898b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { 3899b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + PetscCosReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3900b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + PetscSinReal((2 * l + 1) * PETSC_PI / 4) * L / 2; 3901b7f5c055SJed Brown vtxCoords[vcount++] = (2 * k - 1) * L; 3902b7f5c055SJed Brown } 3903b7f5c055SJed Brown } 3904b7f5c055SJed Brown } 3905b7f5c055SJed Brown } 3906b7f5c055SJed Brown // junctions 3907b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 3908b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 3909b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 3910b7f5c055SJed Brown const PetscInt J = (i * extent[1] + j) * extent[2] + k, Jvoff = (Npipes[0] + Npipes[1] + Npipes[2]) * 4 + J * 8; 3911b7f5c055SJed Brown PetscCheck(vcount / 3 == Jvoff, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Unexpected vertex count"); 3912b7f5c055SJed Brown for (PetscInt ii = 0; ii < 2; ii++) { 3913b7f5c055SJed Brown for (PetscInt jj = 0; jj < 2; jj++) { 3914b7f5c055SJed Brown for (PetscInt kk = 0; kk < 2; kk++) { 3915b7f5c055SJed Brown double Ls = (1 - sqrt(2) / 4) * L; 3916b7f5c055SJed Brown vtxCoords[vcount++] = 2 * i * L + (2 * ii - 1) * Ls; 3917b7f5c055SJed Brown vtxCoords[vcount++] = 2 * j * L + (2 * jj - 1) * Ls; 3918b7f5c055SJed Brown vtxCoords[vcount++] = 2 * k * L + (2 * kk - 1) * Ls; 3919b7f5c055SJed Brown } 3920b7f5c055SJed Brown } 3921b7f5c055SJed Brown } 3922b7f5c055SJed Brown const PetscInt jfaces[3][2][4] = { 3923b7f5c055SJed Brown {{3, 1, 0, 2}, {7, 5, 4, 6}}, // x-aligned 3924b7f5c055SJed Brown {{5, 4, 0, 1}, {7, 6, 2, 3}}, // y-aligned 3925b7f5c055SJed Brown {{6, 2, 0, 4}, {7, 3, 1, 5}} // z-aligned 3926b7f5c055SJed Brown }; 3927b7f5c055SJed Brown const PetscInt pipe_lo[3] = {// vertex numbers of pipes 39289371c9d4SSatish 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}; 3929b7f5c055SJed Brown const PetscInt pipe_hi[3] = {// vertex numbers of pipes 39309371c9d4SSatish 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}; 3931b7f5c055SJed Brown for (PetscInt dir = 0; dir < 3; dir++) { // x,y,z 3932b7f5c055SJed Brown const PetscInt ijk[3] = {i, j, k}; 3933b7f5c055SJed Brown for (PetscInt l = 0; l < 4; l++) { // rotations 3934b7f5c055SJed Brown cells[J][dir * 2 + 0][l][0] = pipe_lo[dir] + l; 3935b7f5c055SJed Brown cells[J][dir * 2 + 0][l][1] = Jvoff + jfaces[dir][0][l]; 3936b7f5c055SJed Brown cells[J][dir * 2 + 0][l][2] = Jvoff + jfaces[dir][0][(l - 1 + 4) % 4]; 3937b7f5c055SJed Brown cells[J][dir * 2 + 0][l][3] = pipe_lo[dir] + (l - 1 + 4) % 4; 3938b7f5c055SJed Brown cells[J][dir * 2 + 1][l][0] = Jvoff + jfaces[dir][1][l]; 3939b7f5c055SJed Brown cells[J][dir * 2 + 1][l][1] = pipe_hi[dir] + l; 3940b7f5c055SJed Brown cells[J][dir * 2 + 1][l][2] = pipe_hi[dir] + (l - 1 + 4) % 4; 3941b7f5c055SJed Brown cells[J][dir * 2 + 1][l][3] = Jvoff + jfaces[dir][1][(l - 1 + 4) % 4]; 3942b7f5c055SJed Brown if (ijk[dir] == 0) { 3943b7f5c055SJed Brown edges[numEdges][0] = pipe_lo[dir] + l; 3944b7f5c055SJed Brown edges[numEdges][1] = pipe_lo[dir] + (l + 1) % 4; 3945b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 1; 3946b7f5c055SJed Brown numEdges++; 3947b7f5c055SJed Brown } 3948b7f5c055SJed Brown if (ijk[dir] + 1 == extent[dir]) { 3949b7f5c055SJed Brown edges[numEdges][0] = pipe_hi[dir] + l; 3950b7f5c055SJed Brown edges[numEdges][1] = pipe_hi[dir] + (l + 1) % 4; 3951b7f5c055SJed Brown edgeSets[numEdges] = dir * 2 + 2; 3952b7f5c055SJed Brown numEdges++; 3953b7f5c055SJed Brown } 3954b7f5c055SJed Brown } 3955b7f5c055SJed Brown } 3956b7f5c055SJed Brown } 3957b7f5c055SJed Brown } 3958b7f5c055SJed Brown } 395963a3b9bcSJacob Faibussowitsch PetscCheck(numEdges == Ncuts * 4, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Edge count %" PetscInt_FMT " incompatible with number of cuts %" PetscInt_FMT, numEdges, Ncuts); 3960b7f5c055SJed Brown numFaces = 24 * Njunctions; 3961b7f5c055SJed Brown cells_flat = cells[0][0][0]; 3962b7f5c055SJed Brown } 3963b7f5c055SJed Brown evalFunc = TPSEvaluate_SchwarzP; 39644663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_SchwarzP; 3965b7f5c055SJed Brown break; 3966b7f5c055SJed Brown case DMPLEX_TPS_GYROID: 3967c5853193SPierre Jolivet if (rank == 0) { 3968b7f5c055SJed Brown // This is a coarse mesh approximation of the gyroid shifted to being the zero of the level set 3969b7f5c055SJed Brown // 3970b7f5c055SJed 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) 3971b7f5c055SJed Brown // 3972b7f5c055SJed Brown // on the cell [0,2]^3. 3973b7f5c055SJed Brown // 3974b7f5c055SJed Brown // Think about dividing that cell into four columns, and focus on the column [0,1]x[0,1]x[0,2]. 3975b7f5c055SJed Brown // If you looked at the gyroid in that column at different slices of z you would see that it kind of spins 3976b7f5c055SJed Brown // like a boomerang: 3977b7f5c055SJed Brown // 3978b7f5c055SJed Brown // z = 0 z = 1/4 z = 1/2 z = 3/4 // 3979b7f5c055SJed Brown // ----- ------- ------- ------- // 3980b7f5c055SJed Brown // // 3981b7f5c055SJed Brown // + + + + + + + \ + // 3982b7f5c055SJed Brown // \ / \ // 3983b7f5c055SJed Brown // \ `-_ _-' / } // 3984b7f5c055SJed Brown // *-_ `-' _-' / // 3985b7f5c055SJed Brown // + `-+ + + +-' + + / + // 3986b7f5c055SJed Brown // // 3987b7f5c055SJed Brown // // 3988b7f5c055SJed Brown // z = 1 z = 5/4 z = 3/2 z = 7/4 // 3989b7f5c055SJed Brown // ----- ------- ------- ------- // 3990b7f5c055SJed Brown // // 3991b7f5c055SJed Brown // +-_ + + + + _-+ + / + // 3992b7f5c055SJed Brown // `-_ _-_ _-` / // 3993b7f5c055SJed Brown // \ _-' `-_ / { // 3994b7f5c055SJed Brown // \ / \ // 3995b7f5c055SJed Brown // + + + + + + + \ + // 3996b7f5c055SJed Brown // 3997b7f5c055SJed Brown // 3998b7f5c055SJed Brown // This course mesh approximates each of these slices by two line segments, 3999b7f5c055SJed Brown // and then connects the segments in consecutive layers with quadrilateral faces. 4000b7f5c055SJed Brown // All of the end points of the segments are multiples of 1/4 except for the 4001b7f5c055SJed Brown // point * in the picture for z = 0 above and the similar points in other layers. 4002b7f5c055SJed Brown // That point is at (gamma, gamma, 0), where gamma is calculated below. 4003b7f5c055SJed Brown // 4004b7f5c055SJed Brown // The column [1,2]x[1,2]x[0,2] looks the same as this column; 4005b7f5c055SJed Brown // The columns [1,2]x[0,1]x[0,2] and [0,1]x[1,2]x[0,2] are mirror images. 4006b7f5c055SJed Brown // 4007b7f5c055SJed Brown // As for how this method turned into the names given to the vertices: 4008b7f5c055SJed Brown // that was not systematic, it was just the way it worked out in my handwritten notes. 4009b7f5c055SJed Brown 4010b7f5c055SJed Brown PetscInt facesPerBlock = 64; 4011b7f5c055SJed Brown PetscInt vertsPerBlock = 56; 4012b7f5c055SJed Brown PetscInt extentPlus[3]; 4013b7f5c055SJed Brown PetscInt numBlocks, numBlocksPlus; 40149371c9d4SSatish 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; 40159371c9d4SSatish Balay const PetscInt pattern[64][4] = { 40169371c9d4SSatish Balay /* face to vertex within the coarse discretization of a single gyroid block */ 4017b7f5c055SJed Brown /* layer 0 */ 40189371c9d4SSatish Balay {A, C, K, G }, 40199371c9d4SSatish Balay {C, B, II, K }, 40209371c9d4SSatish Balay {D, A, H, L }, 40219371c9d4SSatish Balay {B + 56 * 1, D, L, J }, 40229371c9d4SSatish Balay {E, B + 56 * 1, J, N }, 40239371c9d4SSatish Balay {A + 56 * 2, E, N, H + 56 * 2 }, 40249371c9d4SSatish Balay {F, A + 56 * 2, G + 56 * 2, M }, 40259371c9d4SSatish Balay {B, F, M, II }, 4026b7f5c055SJed Brown /* layer 1 */ 40279371c9d4SSatish Balay {G, K, Q, O }, 40289371c9d4SSatish Balay {K, II, P, Q }, 40299371c9d4SSatish Balay {L, H, O + 56 * 1, R }, 40309371c9d4SSatish Balay {J, L, R, P }, 40319371c9d4SSatish Balay {N, J, P, S }, 40329371c9d4SSatish Balay {H + 56 * 2, N, S, O + 56 * 3 }, 40339371c9d4SSatish Balay {M, G + 56 * 2, O + 56 * 2, T }, 40349371c9d4SSatish Balay {II, M, T, P }, 4035b7f5c055SJed Brown /* layer 2 */ 40369371c9d4SSatish Balay {O, Q, Y, U }, 40379371c9d4SSatish Balay {Q, P, W, Y }, 40389371c9d4SSatish Balay {R, O + 56 * 1, U + 56 * 1, Ap }, 40399371c9d4SSatish Balay {P, R, Ap, W }, 40409371c9d4SSatish Balay {S, P, X, Bp }, 40419371c9d4SSatish Balay {O + 56 * 3, S, Bp, V + 56 * 1 }, 40429371c9d4SSatish Balay {T, O + 56 * 2, V, Z }, 40439371c9d4SSatish Balay {P, T, Z, X }, 4044b7f5c055SJed Brown /* layer 3 */ 40459371c9d4SSatish Balay {U, Y, Ep, Dp }, 40469371c9d4SSatish Balay {Y, W, Cp, Ep }, 40479371c9d4SSatish Balay {Ap, U + 56 * 1, Dp + 56 * 1, Gp }, 40489371c9d4SSatish Balay {W, Ap, Gp, Cp }, 40499371c9d4SSatish Balay {Bp, X, Cp + 56 * 2, Fp }, 40509371c9d4SSatish Balay {V + 56 * 1, Bp, Fp, Dp + 56 * 1}, 40519371c9d4SSatish Balay {Z, V, Dp, Hp }, 40529371c9d4SSatish Balay {X, Z, Hp, Cp + 56 * 2}, 4053b7f5c055SJed Brown /* layer 4 */ 40549371c9d4SSatish Balay {Dp, Ep, Mp, Kp }, 40559371c9d4SSatish Balay {Ep, Cp, Ip, Mp }, 40569371c9d4SSatish Balay {Gp, Dp + 56 * 1, Lp, Np }, 40579371c9d4SSatish Balay {Cp, Gp, Np, Jp }, 40589371c9d4SSatish Balay {Fp, Cp + 56 * 2, Jp + 56 * 2, Pp }, 40599371c9d4SSatish Balay {Dp + 56 * 1, Fp, Pp, Lp }, 40609371c9d4SSatish Balay {Hp, Dp, Kp, Op }, 40619371c9d4SSatish Balay {Cp + 56 * 2, Hp, Op, Ip + 56 * 2}, 4062b7f5c055SJed Brown /* layer 5 */ 40639371c9d4SSatish Balay {Kp, Mp, Sp, Rp }, 40649371c9d4SSatish Balay {Mp, Ip, Qp, Sp }, 40659371c9d4SSatish Balay {Np, Lp, Rp, Tp }, 40669371c9d4SSatish Balay {Jp, Np, Tp, Qp + 56 * 1}, 40679371c9d4SSatish Balay {Pp, Jp + 56 * 2, Qp + 56 * 3, Up }, 40689371c9d4SSatish Balay {Lp, Pp, Up, Rp }, 40699371c9d4SSatish Balay {Op, Kp, Rp, Vp }, 40709371c9d4SSatish Balay {Ip + 56 * 2, Op, Vp, Qp + 56 * 2}, 4071b7f5c055SJed Brown /* layer 6 */ 40729371c9d4SSatish Balay {Rp, Sp, Aq, Yp }, 40739371c9d4SSatish Balay {Sp, Qp, Wp, Aq }, 40749371c9d4SSatish Balay {Tp, Rp, Yp, Cq }, 40759371c9d4SSatish Balay {Qp + 56 * 1, Tp, Cq, Wp + 56 * 1}, 40769371c9d4SSatish Balay {Up, Qp + 56 * 3, Xp + 56 * 1, Dq }, 40779371c9d4SSatish Balay {Rp, Up, Dq, Zp }, 40789371c9d4SSatish Balay {Vp, Rp, Zp, Bq }, 40799371c9d4SSatish Balay {Qp + 56 * 2, Vp, Bq, Xp }, 4080b7f5c055SJed Brown /* layer 7 (the top is the periodic image of the bottom of layer 0) */ 40819371c9d4SSatish Balay {Yp, Aq, C + 56 * 4, A + 56 * 4 }, 40829371c9d4SSatish Balay {Aq, Wp, B + 56 * 4, C + 56 * 4 }, 40839371c9d4SSatish Balay {Cq, Yp, A + 56 * 4, D + 56 * 4 }, 40849371c9d4SSatish Balay {Wp + 56 * 1, Cq, D + 56 * 4, B + 56 * 5 }, 40859371c9d4SSatish Balay {Dq, Xp + 56 * 1, B + 56 * 5, E + 56 * 4 }, 40869371c9d4SSatish Balay {Zp, Dq, E + 56 * 4, A + 56 * 6 }, 40879371c9d4SSatish Balay {Bq, Zp, A + 56 * 6, F + 56 * 4 }, 40889371c9d4SSatish Balay {Xp, Bq, F + 56 * 4, B + 56 * 4 } 4089b7f5c055SJed Brown }; 4090b7f5c055SJed Brown const PetscReal gamma = PetscAcosReal((PetscSqrtReal(3.) - 1.) / PetscSqrtReal(2.)) / PETSC_PI; 40919371c9d4SSatish Balay const PetscReal patternCoords[56][3] = { 4092bee3fc89SBarry Smith {1., 0., 0. }, /* A */ 4093bee3fc89SBarry Smith {0., 1., 0. }, /* B */ 4094bee3fc89SBarry Smith {gamma, gamma, 0. }, /* C */ 4095bee3fc89SBarry Smith {1 + gamma, 1 - gamma, 0. }, /* D */ 4096bee3fc89SBarry Smith {2 - gamma, 2 - gamma, 0. }, /* E */ 4097bee3fc89SBarry Smith {1 - gamma, 1 + gamma, 0. }, /* F */ 4098b7f5c055SJed Brown 4099bee3fc89SBarry Smith {.5, 0, .25 }, /* G */ 4100bee3fc89SBarry Smith {1.5, 0., .25 }, /* H */ 4101bee3fc89SBarry Smith {.5, 1., .25 }, /* II */ 4102bee3fc89SBarry Smith {1.5, 1., .25 }, /* J */ 4103bee3fc89SBarry Smith {.25, .5, .25 }, /* K */ 4104bee3fc89SBarry Smith {1.25, .5, .25 }, /* L */ 4105bee3fc89SBarry Smith {.75, 1.5, .25 }, /* M */ 4106bee3fc89SBarry Smith {1.75, 1.5, .25 }, /* N */ 4107b7f5c055SJed Brown 4108bee3fc89SBarry Smith {0., 0., .5 }, /* O */ 4109bee3fc89SBarry Smith {1., 1., .5 }, /* P */ 4110bee3fc89SBarry Smith {gamma, 1 - gamma, .5 }, /* Q */ 4111bee3fc89SBarry Smith {1 + gamma, gamma, .5 }, /* R */ 4112bee3fc89SBarry Smith {2 - gamma, 1 + gamma, .5 }, /* S */ 4113bee3fc89SBarry Smith {1 - gamma, 2 - gamma, .5 }, /* T */ 4114b7f5c055SJed Brown 4115bee3fc89SBarry Smith {0., .5, .75 }, /* U */ 4116bee3fc89SBarry Smith {0., 1.5, .75 }, /* V */ 4117bee3fc89SBarry Smith {1., .5, .75 }, /* W */ 4118bee3fc89SBarry Smith {1., 1.5, .75 }, /* X */ 4119bee3fc89SBarry Smith {.5, .75, .75 }, /* Y */ 4120bee3fc89SBarry Smith {.5, 1.75, .75 }, /* Z */ 4121bee3fc89SBarry Smith {1.5, .25, .75 }, /* Ap */ 4122bee3fc89SBarry Smith {1.5, 1.25, .75 }, /* Bp */ 4123b7f5c055SJed Brown 4124bee3fc89SBarry Smith {1., 0., 1. }, /* Cp */ 4125bee3fc89SBarry Smith {0., 1., 1. }, /* Dp */ 4126bee3fc89SBarry Smith {1 - gamma, 1 - gamma, 1. }, /* Ep */ 4127bee3fc89SBarry Smith {1 + gamma, 1 + gamma, 1. }, /* Fp */ 4128bee3fc89SBarry Smith {2 - gamma, gamma, 1. }, /* Gp */ 4129bee3fc89SBarry Smith {gamma, 2 - gamma, 1. }, /* Hp */ 4130b7f5c055SJed Brown 4131bee3fc89SBarry Smith {.5, 0., 1.25}, /* Ip */ 4132bee3fc89SBarry Smith {1.5, 0., 1.25}, /* Jp */ 4133bee3fc89SBarry Smith {.5, 1., 1.25}, /* Kp */ 4134bee3fc89SBarry Smith {1.5, 1., 1.25}, /* Lp */ 4135bee3fc89SBarry Smith {.75, .5, 1.25}, /* Mp */ 4136bee3fc89SBarry Smith {1.75, .5, 1.25}, /* Np */ 4137bee3fc89SBarry Smith {.25, 1.5, 1.25}, /* Op */ 4138bee3fc89SBarry Smith {1.25, 1.5, 1.25}, /* Pp */ 4139b7f5c055SJed Brown 4140bee3fc89SBarry Smith {0., 0., 1.5 }, /* Qp */ 4141bee3fc89SBarry Smith {1., 1., 1.5 }, /* Rp */ 4142bee3fc89SBarry Smith {1 - gamma, gamma, 1.5 }, /* Sp */ 4143bee3fc89SBarry Smith {2 - gamma, 1 - gamma, 1.5 }, /* Tp */ 4144bee3fc89SBarry Smith {1 + gamma, 2 - gamma, 1.5 }, /* Up */ 4145bee3fc89SBarry Smith {gamma, 1 + gamma, 1.5 }, /* Vp */ 4146b7f5c055SJed Brown 4147bee3fc89SBarry Smith {0., .5, 1.75}, /* Wp */ 4148bee3fc89SBarry Smith {0., 1.5, 1.75}, /* Xp */ 4149bee3fc89SBarry Smith {1., .5, 1.75}, /* Yp */ 4150bee3fc89SBarry Smith {1., 1.5, 1.75}, /* Zp */ 4151bee3fc89SBarry Smith {.5, .25, 1.75}, /* Aq */ 4152bee3fc89SBarry Smith {.5, 1.25, 1.75}, /* Bq */ 4153bee3fc89SBarry Smith {1.5, .75, 1.75}, /* Cq */ 4154bee3fc89SBarry Smith {1.5, 1.75, 1.75}, /* Dq */ 4155b7f5c055SJed Brown }; 4156b7f5c055SJed Brown PetscInt (*cells)[64][4] = NULL; 4157b7f5c055SJed Brown PetscBool *seen; 4158b7f5c055SJed Brown PetscInt *vertToTrueVert; 4159b7f5c055SJed Brown PetscInt count; 4160b7f5c055SJed Brown 4161b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) extentPlus[i] = extent[i] + 1; 4162b7f5c055SJed Brown numBlocks = 1; 4163b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocks *= extent[i]; 4164b7f5c055SJed Brown numBlocksPlus = 1; 4165b7f5c055SJed Brown for (PetscInt i = 0; i < 3; i++) numBlocksPlus *= extentPlus[i]; 4166b7f5c055SJed Brown numFaces = numBlocks * facesPerBlock; 41679566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocks, &cells)); 41689566063dSJacob Faibussowitsch PetscCall(PetscCalloc1(numBlocksPlus * vertsPerBlock, &seen)); 4169b7f5c055SJed Brown for (PetscInt k = 0; k < extent[2]; k++) { 4170b7f5c055SJed Brown for (PetscInt j = 0; j < extent[1]; j++) { 4171b7f5c055SJed Brown for (PetscInt i = 0; i < extent[0]; i++) { 4172b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 4173b7f5c055SJed Brown for (PetscInt v = 0; v < 4; v++) { 4174b7f5c055SJed Brown PetscInt vertRaw = pattern[f][v]; 4175b7f5c055SJed Brown PetscInt blockidx = vertRaw / 56; 4176b7f5c055SJed Brown PetscInt patternvert = vertRaw % 56; 4177b7f5c055SJed Brown PetscInt xplus = (blockidx & 1); 4178b7f5c055SJed Brown PetscInt yplus = (blockidx & 2) >> 1; 4179b7f5c055SJed Brown PetscInt zplus = (blockidx & 4) >> 2; 4180b7f5c055SJed Brown PetscInt zcoord = (periodic && periodic[2] == DM_BOUNDARY_PERIODIC) ? ((k + zplus) % extent[2]) : (k + zplus); 4181b7f5c055SJed Brown PetscInt ycoord = (periodic && periodic[1] == DM_BOUNDARY_PERIODIC) ? ((j + yplus) % extent[1]) : (j + yplus); 4182b7f5c055SJed Brown PetscInt xcoord = (periodic && periodic[0] == DM_BOUNDARY_PERIODIC) ? ((i + xplus) % extent[0]) : (i + xplus); 4183b7f5c055SJed Brown PetscInt vert = ((zcoord * extentPlus[1] + ycoord) * extentPlus[0] + xcoord) * 56 + patternvert; 4184b7f5c055SJed Brown 4185b7f5c055SJed Brown cells[(k * extent[1] + j) * extent[0] + i][f][v] = vert; 4186b7f5c055SJed Brown seen[vert] = PETSC_TRUE; 4187b7f5c055SJed Brown } 4188b7f5c055SJed Brown } 4189b7f5c055SJed Brown } 4190b7f5c055SJed Brown } 4191b7f5c055SJed Brown } 41929371c9d4SSatish Balay for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) 41939371c9d4SSatish Balay if (seen[i]) numVertices++; 4194b7f5c055SJed Brown count = 0; 41959566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numBlocksPlus * vertsPerBlock, &vertToTrueVert)); 41969566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * 3, &vtxCoords)); 4197b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocksPlus * vertsPerBlock; i++) vertToTrueVert[i] = -1; 4198b7f5c055SJed Brown for (PetscInt k = 0; k < extentPlus[2]; k++) { 4199b7f5c055SJed Brown for (PetscInt j = 0; j < extentPlus[1]; j++) { 4200b7f5c055SJed Brown for (PetscInt i = 0; i < extentPlus[0]; i++) { 4201b7f5c055SJed Brown for (PetscInt v = 0; v < vertsPerBlock; v++) { 4202b7f5c055SJed Brown PetscInt vIdx = ((k * extentPlus[1] + j) * extentPlus[0] + i) * vertsPerBlock + v; 4203b7f5c055SJed Brown 4204b7f5c055SJed Brown if (seen[vIdx]) { 4205b7f5c055SJed Brown PetscInt thisVert; 4206b7f5c055SJed Brown 4207b7f5c055SJed Brown vertToTrueVert[vIdx] = thisVert = count++; 4208b7f5c055SJed Brown 4209b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) vtxCoords[3 * thisVert + d] = patternCoords[v][d]; 4210b7f5c055SJed Brown vtxCoords[3 * thisVert + 0] += i * 2; 4211b7f5c055SJed Brown vtxCoords[3 * thisVert + 1] += j * 2; 4212b7f5c055SJed Brown vtxCoords[3 * thisVert + 2] += k * 2; 4213b7f5c055SJed Brown } 4214b7f5c055SJed Brown } 4215b7f5c055SJed Brown } 4216b7f5c055SJed Brown } 4217b7f5c055SJed Brown } 4218b7f5c055SJed Brown for (PetscInt i = 0; i < numBlocks; i++) { 4219b7f5c055SJed Brown for (PetscInt f = 0; f < facesPerBlock; f++) { 4220ad540459SPierre Jolivet for (PetscInt v = 0; v < 4; v++) cells[i][f][v] = vertToTrueVert[cells[i][f][v]]; 4221b7f5c055SJed Brown } 4222b7f5c055SJed Brown } 42239566063dSJacob Faibussowitsch PetscCall(PetscFree(vertToTrueVert)); 42249566063dSJacob Faibussowitsch PetscCall(PetscFree(seen)); 4225b7f5c055SJed Brown cells_flat = cells[0][0]; 4226b7f5c055SJed Brown numEdges = 0; 4227b7f5c055SJed Brown for (PetscInt i = 0; i < numFaces; i++) { 4228b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 4229b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 4230b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 4231b7f5c055SJed Brown 4232b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 4233b7f5c055SJed Brown if (!periodic || periodic[0] != DM_BOUNDARY_PERIODIC) { 4234b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) numEdges++; 4235b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) numEdges++; 4236b7f5c055SJed Brown } 4237b7f5c055SJed Brown } 4238b7f5c055SJed Brown } 4239b7f5c055SJed Brown } 42409566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edges)); 42419566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numEdges, &edgeSets)); 4242b7f5c055SJed Brown for (PetscInt edge = 0, i = 0; i < numFaces; i++) { 4243b7f5c055SJed Brown for (PetscInt e = 0; e < 4; e++) { 4244b7f5c055SJed Brown PetscInt ev[] = {cells_flat[i * 4 + e], cells_flat[i * 4 + ((e + 1) % 4)]}; 4245b7f5c055SJed Brown const PetscReal *evCoords[] = {&vtxCoords[3 * ev[0]], &vtxCoords[3 * ev[1]]}; 4246b7f5c055SJed Brown 4247b7f5c055SJed Brown for (PetscInt d = 0; d < 3; d++) { 4248b7f5c055SJed Brown if (!periodic || periodic[d] != DM_BOUNDARY_PERIODIC) { 4249b7f5c055SJed Brown if (evCoords[0][d] == 0. && evCoords[1][d] == 0.) { 4250b7f5c055SJed Brown edges[edge][0] = ev[0]; 4251b7f5c055SJed Brown edges[edge][1] = ev[1]; 4252b7f5c055SJed Brown edgeSets[edge++] = 2 * d; 4253b7f5c055SJed Brown } 4254b7f5c055SJed Brown if (evCoords[0][d] == 2. * extent[d] && evCoords[1][d] == 2. * extent[d]) { 4255b7f5c055SJed Brown edges[edge][0] = ev[0]; 4256b7f5c055SJed Brown edges[edge][1] = ev[1]; 4257b7f5c055SJed Brown edgeSets[edge++] = 2 * d + 1; 4258b7f5c055SJed Brown } 4259b7f5c055SJed Brown } 4260b7f5c055SJed Brown } 4261b7f5c055SJed Brown } 4262b7f5c055SJed Brown } 4263b7f5c055SJed Brown } 4264b7f5c055SJed Brown evalFunc = TPSEvaluate_Gyroid; 42654663dae6SJed Brown normalFunc = TPSExtrudeNormalFunc_Gyroid; 4266b7f5c055SJed Brown break; 4267b7f5c055SJed Brown } 4268b7f5c055SJed Brown 42699566063dSJacob Faibussowitsch PetscCall(DMSetDimension(dm, topoDim)); 4270c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(dm, numFaces, numVertices, 4, cells_flat)); 42719566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(dm, 0, 0, 0, NULL)); 42729566063dSJacob Faibussowitsch PetscCall(PetscFree(cells_flat)); 4273b7f5c055SJed Brown { 4274b7f5c055SJed Brown DM idm; 42759566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 427669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 4277b7f5c055SJed Brown } 4278c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, vtxCoords)); 42799566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(dm, spaceDim, NULL)); 42809566063dSJacob Faibussowitsch PetscCall(PetscFree(vtxCoords)); 4281b7f5c055SJed Brown 42829566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "Face Sets")); 42839566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 4284b7f5c055SJed Brown for (PetscInt e = 0; e < numEdges; e++) { 4285b7f5c055SJed Brown PetscInt njoin; 4286b7f5c055SJed Brown const PetscInt *join, verts[] = {numFaces + edges[e][0], numFaces + edges[e][1]}; 42879566063dSJacob Faibussowitsch PetscCall(DMPlexGetJoin(dm, 2, verts, &njoin, &join)); 428863a3b9bcSJacob 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]); 42899566063dSJacob Faibussowitsch PetscCall(DMLabelSetValue(label, join[0], edgeSets[e])); 42909566063dSJacob Faibussowitsch PetscCall(DMPlexRestoreJoin(dm, 2, verts, &njoin, &join)); 4291b7f5c055SJed Brown } 42929566063dSJacob Faibussowitsch PetscCall(PetscFree(edges)); 42939566063dSJacob Faibussowitsch PetscCall(PetscFree(edgeSets)); 42941436d7faSJed Brown if (tps_distribute) { 42951436d7faSJed Brown DM pdm = NULL; 42961436d7faSJed Brown PetscPartitioner part; 42971436d7faSJed Brown 42989566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 42999566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 43009566063dSJacob Faibussowitsch PetscCall(DMPlexDistribute(dm, 0, NULL, &pdm)); 430148a46eb9SPierre Jolivet if (pdm) PetscCall(DMPlexReplace_Internal(dm, &pdm)); 43021436d7faSJed Brown // Do not auto-distribute again 43039566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 43041436d7faSJed Brown } 4305b7f5c055SJed Brown 43069566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 4307b7f5c055SJed Brown for (PetscInt refine = 0; refine < refinements; refine++) { 4308b7f5c055SJed Brown PetscInt m; 4309f1d4225fSZach Atkins DM dmf, cdm, cdmf; 4310b7f5c055SJed Brown Vec X; 4311b7f5c055SJed Brown PetscScalar *x; 4312f1d4225fSZach Atkins 43139566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, MPI_COMM_NULL, &dmf)); 4314f1d4225fSZach Atkins PetscCall(DMGetCoordinateDM(dm, &cdm)); 4315f1d4225fSZach Atkins PetscCall(DMGetCoordinateDM(dmf, &cdmf)); 4316f1d4225fSZach Atkins PetscCall(DMCopyDisc(cdm, cdmf)); 431769d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmf)); 4318b7f5c055SJed Brown 43199566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &X)); 43209566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(X, &m)); 43219566063dSJacob Faibussowitsch PetscCall(VecGetArray(X, &x)); 432248a46eb9SPierre Jolivet for (PetscInt i = 0; i < m; i += 3) PetscCall(TPSNearestPoint(evalFunc, &x[i])); 43239566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(X, &x)); 4324b7f5c055SJed Brown } 4325b7f5c055SJed Brown 4326b7f5c055SJed Brown // Face Sets has already been propagated to new vertices during refinement; this propagates to the initial vertices. 43279566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "Face Sets", &label)); 43289566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, label)); 4329b7f5c055SJed Brown 433046139095SJed Brown PetscCall(PetscLogEventEnd(DMPLEX_Generate, dm, 0, 0, 0)); 433146139095SJed Brown 4332b7f5c055SJed Brown if (thickness > 0) { 43334663dae6SJed Brown DM edm, cdm, ecdm; 43344663dae6SJed Brown DMPlexTransform tr; 43354663dae6SJed Brown const char *prefix; 43364663dae6SJed Brown PetscOptions options; 43374663dae6SJed Brown // Code from DMPlexExtrude 43384663dae6SJed Brown PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 43394663dae6SJed Brown PetscCall(DMPlexTransformSetDM(tr, dm)); 4340ce78bad3SBarry Smith PetscCall(DMPlexTransformSetType(tr, DMPLEXEXTRUDETYPE)); 43414663dae6SJed Brown PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 43424663dae6SJed Brown PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 43434663dae6SJed Brown PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 43444663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 43454663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetLayers(tr, layers)); 43464663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetThickness(tr, thickness)); 43474663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetTensor(tr, PETSC_FALSE)); 43484663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetSymmetric(tr, PETSC_TRUE)); 43494663dae6SJed Brown PetscCall(DMPlexTransformExtrudeSetNormalFunction(tr, normalFunc)); 43504663dae6SJed Brown PetscCall(DMPlexTransformSetFromOptions(tr)); 43514663dae6SJed Brown PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 43524663dae6SJed Brown PetscCall(DMPlexTransformSetUp(tr)); 43534663dae6SJed Brown PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_tps_transform_view")); 43544663dae6SJed Brown PetscCall(DMPlexTransformApply(tr, dm, &edm)); 43554663dae6SJed Brown PetscCall(DMCopyDisc(dm, edm)); 43564663dae6SJed Brown PetscCall(DMGetCoordinateDM(dm, &cdm)); 43574663dae6SJed Brown PetscCall(DMGetCoordinateDM(edm, &ecdm)); 43584663dae6SJed Brown PetscCall(DMCopyDisc(cdm, ecdm)); 43594663dae6SJed Brown PetscCall(DMPlexTransformCreateDiscLabels(tr, edm)); 43604663dae6SJed Brown PetscCall(DMPlexTransformDestroy(&tr)); 4361a77a5016SMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, edm)); 436269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 4363b7f5c055SJed Brown } 43643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4365b7f5c055SJed Brown } 4366b7f5c055SJed Brown 4367b7f5c055SJed Brown /*@ 4368b7f5c055SJed Brown DMPlexCreateTPSMesh - Create a distributed, interpolated mesh of a triply-periodic surface 4369b7f5c055SJed Brown 4370b7f5c055SJed Brown Collective 4371b7f5c055SJed Brown 4372b7f5c055SJed Brown Input Parameters: 4373a1cb98faSBarry Smith + comm - The communicator for the `DM` object 4374b7f5c055SJed Brown . tpstype - Type of triply-periodic surface 4375b7f5c055SJed Brown . extent - Array of length 3 containing number of periods in each direction 437620f4b53cSBarry Smith . periodic - array of length 3 with periodicity, or `NULL` for non-periodic 43771436d7faSJed Brown . tps_distribute - Distribute 2D manifold mesh prior to refinement and extrusion (more scalable) 4378817da375SSatish Balay . refinements - Number of factor-of-2 refinements of 2D manifold mesh 43791436d7faSJed Brown . layers - Number of cell layers extruded in normal direction 4380817da375SSatish Balay - thickness - Thickness in normal direction 4381b7f5c055SJed Brown 4382b7f5c055SJed Brown Output Parameter: 4383a1cb98faSBarry Smith . dm - The `DM` object 4384a1cb98faSBarry Smith 4385a1cb98faSBarry Smith Level: beginner 4386b7f5c055SJed Brown 4387b7f5c055SJed Brown Notes: 438815229ffcSPierre Jolivet This meshes the surface of the Schwarz P or Gyroid surfaces. Schwarz P is the simplest member of the triply-periodic minimal surfaces. 43891d27aa22SBarry Smith <https://en.wikipedia.org/wiki/Schwarz_minimal_surface#Schwarz_P_(%22Primitive%22)> and can be cut with "clean" boundaries. 43901d27aa22SBarry 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. 4391b7f5c055SJed Brown Our implementation creates a very coarse mesh of the surface and refines (by 4-way splitting) as many times as requested. 4392b7f5c055SJed Brown On each refinement, all vertices are projected to their nearest point on the surface. 4393b7f5c055SJed Brown This projection could readily be extended to related surfaces. 4394b7f5c055SJed Brown 43951d27aa22SBarry Smith See {cite}`maskery2018insights` 43961d27aa22SBarry Smith 43971d27aa22SBarry Smith The face (edge) sets for the Schwarz P surface are numbered $1(-x), 2(+x), 3(-y), 4(+y), 5(-z), 6(+z)$. 43981d27aa22SBarry Smith When the mesh is refined, "Face Sets" contain the new vertices (created during refinement). 43991d27aa22SBarry Smith Use `DMPlexLabelComplete()` to propagate to coarse-level vertices. 4400b7f5c055SJed Brown 440160225df5SJacob Faibussowitsch Developer Notes: 4402b7f5c055SJed Brown The Gyroid mesh does not currently mark boundary sets. 4403b7f5c055SJed Brown 44041cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMSetType()`, `DMCreate()` 4405b7f5c055SJed Brown @*/ 4406d71ae5a4SJacob 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) 4407d71ae5a4SJacob Faibussowitsch { 4408b7f5c055SJed Brown PetscFunctionBegin; 44099566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44109566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 44119566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(*dm, tpstype, extent, periodic, tps_distribute, refinements, layers, thickness)); 44123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4413b7f5c055SJed Brown } 4414b7f5c055SJed Brown 44159318fe57SMatthew G. Knepley /*@ 44169318fe57SMatthew G. Knepley DMPlexCreateSphereMesh - Creates a mesh on the d-dimensional sphere, S^d. 44179318fe57SMatthew G. Knepley 44189318fe57SMatthew G. Knepley Collective 44199318fe57SMatthew G. Knepley 44209318fe57SMatthew G. Knepley Input Parameters: 4421a1cb98faSBarry Smith + comm - The communicator for the `DM` object 44229318fe57SMatthew G. Knepley . dim - The dimension 44239318fe57SMatthew G. Knepley . simplex - Use simplices, or tensor product cells 44249318fe57SMatthew G. Knepley - R - The radius 44259318fe57SMatthew G. Knepley 44269318fe57SMatthew G. Knepley Output Parameter: 4427a1cb98faSBarry Smith . dm - The `DM` object 44289318fe57SMatthew G. Knepley 44299318fe57SMatthew G. Knepley Level: beginner 44309318fe57SMatthew G. Knepley 44311cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBallMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 44329318fe57SMatthew G. Knepley @*/ 4433d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateSphereMesh(MPI_Comm comm, PetscInt dim, PetscBool simplex, PetscReal R, DM *dm) 4434d71ae5a4SJacob Faibussowitsch { 44359318fe57SMatthew G. Knepley PetscFunctionBegin; 44364f572ea9SToby Isaac PetscAssertPointer(dm, 5); 44379566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44389566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 44399566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(*dm, dim, simplex, R)); 44403ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44419318fe57SMatthew G. Knepley } 44429318fe57SMatthew G. Knepley 4443d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBallMesh_Internal(DM dm, PetscInt dim, PetscReal R) 4444d71ae5a4SJacob Faibussowitsch { 44459318fe57SMatthew G. Knepley DM sdm, vol; 44469318fe57SMatthew G. Knepley DMLabel bdlabel; 4447dd2b43ebSStefano Zampini const char *prefix; 44489318fe57SMatthew G. Knepley 44499318fe57SMatthew G. Knepley PetscFunctionBegin; 44509566063dSJacob Faibussowitsch PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &sdm)); 44519566063dSJacob Faibussowitsch PetscCall(DMSetType(sdm, DMPLEX)); 4452dd2b43ebSStefano Zampini PetscCall(DMGetOptionsPrefix(dm, &prefix)); 4453dd2b43ebSStefano Zampini PetscCall(DMSetOptionsPrefix(sdm, prefix)); 4454dd2b43ebSStefano Zampini PetscCall(DMAppendOptionsPrefix(sdm, "bd_")); 4455dd2b43ebSStefano Zampini PetscCall(DMPlexDistributeSetDefault(sdm, PETSC_FALSE)); 44569566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(sdm, dim - 1, PETSC_TRUE, R)); 44579566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(sdm)); 44589566063dSJacob Faibussowitsch PetscCall(DMViewFromOptions(sdm, NULL, "-dm_view")); 44599566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(sdm, NULL, PETSC_TRUE, &vol)); 44609566063dSJacob Faibussowitsch PetscCall(DMDestroy(&sdm)); 446169d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &vol)); 44629566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, "marker")); 44639566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, "marker", &bdlabel)); 44649566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(dm, PETSC_DETERMINE, bdlabel)); 44659566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(dm, bdlabel)); 44663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 446751a74b61SMatthew G. Knepley } 446851a74b61SMatthew G. Knepley 446951a74b61SMatthew G. Knepley /*@ 447051a74b61SMatthew G. Knepley DMPlexCreateBallMesh - Creates a simplex mesh on the d-dimensional ball, B^d. 447151a74b61SMatthew G. Knepley 447251a74b61SMatthew G. Knepley Collective 447351a74b61SMatthew G. Knepley 447451a74b61SMatthew G. Knepley Input Parameters: 4475a1cb98faSBarry Smith + comm - The communicator for the `DM` object 447651a74b61SMatthew G. Knepley . dim - The dimension 447751a74b61SMatthew G. Knepley - R - The radius 447851a74b61SMatthew G. Knepley 447951a74b61SMatthew G. Knepley Output Parameter: 4480a1cb98faSBarry Smith . dm - The `DM` object 448151a74b61SMatthew G. Knepley 4482a1cb98faSBarry Smith Options Database Key: 448360225df5SJacob Faibussowitsch . bd_dm_refine - This will refine the surface mesh preserving the sphere geometry 448451a74b61SMatthew G. Knepley 448551a74b61SMatthew G. Knepley Level: beginner 448651a74b61SMatthew G. Knepley 44871cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateSphereMesh()`, `DMPlexCreateBoxMesh()`, `DMSetType()`, `DMCreate()` 448851a74b61SMatthew G. Knepley @*/ 4489d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateBallMesh(MPI_Comm comm, PetscInt dim, PetscReal R, DM *dm) 4490d71ae5a4SJacob Faibussowitsch { 449151a74b61SMatthew G. Knepley PetscFunctionBegin; 44929566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 44939566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 44949566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(*dm, dim, R)); 44953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 44962829fed8SMatthew G. Knepley } 44972829fed8SMatthew G. Knepley 4498d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateReferenceCell_Internal(DM rdm, DMPolytopeType ct) 4499d71ae5a4SJacob Faibussowitsch { 45000a6ba040SMatthew G. Knepley PetscFunctionBegin; 45019318fe57SMatthew G. Knepley switch (ct) { 45029371c9d4SSatish Balay case DM_POLYTOPE_POINT: { 45039318fe57SMatthew G. Knepley PetscInt numPoints[1] = {1}; 45049318fe57SMatthew G. Knepley PetscInt coneSize[1] = {0}; 45059318fe57SMatthew G. Knepley PetscInt cones[1] = {0}; 45069318fe57SMatthew G. Knepley PetscInt coneOrientations[1] = {0}; 45079318fe57SMatthew G. Knepley PetscScalar vertexCoords[1] = {0.0}; 45089318fe57SMatthew G. Knepley 45099566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 0)); 45109566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 0, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45119371c9d4SSatish Balay } break; 45129371c9d4SSatish Balay case DM_POLYTOPE_SEGMENT: { 45139318fe57SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 45149318fe57SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 45159318fe57SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 45169318fe57SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 45179318fe57SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 45189318fe57SMatthew G. Knepley 45199566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 45209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45219371c9d4SSatish Balay } break; 45229371c9d4SSatish Balay case DM_POLYTOPE_POINT_PRISM_TENSOR: { 4523b5a892a1SMatthew G. Knepley PetscInt numPoints[2] = {2, 1}; 4524b5a892a1SMatthew G. Knepley PetscInt coneSize[3] = {2, 0, 0}; 4525b5a892a1SMatthew G. Knepley PetscInt cones[2] = {1, 2}; 4526b5a892a1SMatthew G. Knepley PetscInt coneOrientations[2] = {0, 0}; 4527b5a892a1SMatthew G. Knepley PetscScalar vertexCoords[2] = {-1.0, 1.0}; 4528b5a892a1SMatthew G. Knepley 45299566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 1)); 45309566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45319371c9d4SSatish Balay } break; 45329371c9d4SSatish Balay case DM_POLYTOPE_TRIANGLE: { 45339318fe57SMatthew G. Knepley PetscInt numPoints[2] = {3, 1}; 45349318fe57SMatthew G. Knepley PetscInt coneSize[4] = {3, 0, 0, 0}; 45359318fe57SMatthew G. Knepley PetscInt cones[3] = {1, 2, 3}; 45369318fe57SMatthew G. Knepley PetscInt coneOrientations[3] = {0, 0, 0}; 45379318fe57SMatthew G. Knepley PetscScalar vertexCoords[6] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0}; 45389318fe57SMatthew G. Knepley 45399566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45409566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45419371c9d4SSatish Balay } break; 45429371c9d4SSatish Balay case DM_POLYTOPE_QUADRILATERAL: { 45439318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45449318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 45459318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45469318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 45479318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0}; 45489318fe57SMatthew G. Knepley 45499566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45509566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45519371c9d4SSatish Balay } break; 45529371c9d4SSatish Balay case DM_POLYTOPE_SEG_PRISM_TENSOR: { 45539318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45549318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 45559318fe57SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45569318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 45579318fe57SMatthew G. Knepley PetscScalar vertexCoords[8] = {-1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0}; 45589318fe57SMatthew G. Knepley 45599566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 2)); 45609566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45619371c9d4SSatish Balay } break; 45629371c9d4SSatish Balay case DM_POLYTOPE_TETRAHEDRON: { 45639318fe57SMatthew G. Knepley PetscInt numPoints[2] = {4, 1}; 45649318fe57SMatthew G. Knepley PetscInt coneSize[5] = {4, 0, 0, 0, 0}; 4565f0edb160SMatthew G. Knepley PetscInt cones[4] = {1, 2, 3, 4}; 45669318fe57SMatthew G. Knepley PetscInt coneOrientations[4] = {0, 0, 0, 0}; 4567f0edb160SMatthew 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}; 45689318fe57SMatthew G. Knepley 45699566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45709566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45719371c9d4SSatish Balay } break; 45729371c9d4SSatish Balay case DM_POLYTOPE_HEXAHEDRON: { 45739318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 45749318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 4575f0edb160SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 45769318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 45779371c9d4SSatish 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}; 45789318fe57SMatthew G. Knepley 45799566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45809566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45819371c9d4SSatish Balay } break; 45829371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM: { 45839318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 45849318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 4585f0edb160SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 45869318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 45879371c9d4SSatish 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}; 45889318fe57SMatthew G. Knepley 45899566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 45909566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 45919371c9d4SSatish Balay } break; 45929371c9d4SSatish Balay case DM_POLYTOPE_TRI_PRISM_TENSOR: { 45939318fe57SMatthew G. Knepley PetscInt numPoints[2] = {6, 1}; 45949318fe57SMatthew G. Knepley PetscInt coneSize[7] = {6, 0, 0, 0, 0, 0, 0}; 45959318fe57SMatthew G. Knepley PetscInt cones[6] = {1, 2, 3, 4, 5, 6}; 45969318fe57SMatthew G. Knepley PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 45979371c9d4SSatish 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}; 45989318fe57SMatthew G. Knepley 45999566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 46009566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 46019371c9d4SSatish Balay } break; 46029371c9d4SSatish Balay case DM_POLYTOPE_QUAD_PRISM_TENSOR: { 46039318fe57SMatthew G. Knepley PetscInt numPoints[2] = {8, 1}; 46049318fe57SMatthew G. Knepley PetscInt coneSize[9] = {8, 0, 0, 0, 0, 0, 0, 0, 0}; 46059318fe57SMatthew G. Knepley PetscInt cones[8] = {1, 2, 3, 4, 5, 6, 7, 8}; 46069318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 46079371c9d4SSatish 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}; 46089318fe57SMatthew G. Knepley 46099566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 46109566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 46119371c9d4SSatish Balay } break; 46129371c9d4SSatish Balay case DM_POLYTOPE_PYRAMID: { 46139318fe57SMatthew G. Knepley PetscInt numPoints[2] = {5, 1}; 46149318fe57SMatthew G. Knepley PetscInt coneSize[6] = {5, 0, 0, 0, 0, 0}; 4615f0edb160SMatthew G. Knepley PetscInt cones[5] = {1, 2, 3, 4, 5}; 46169318fe57SMatthew G. Knepley PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 46179371c9d4SSatish 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}; 46189318fe57SMatthew G. Knepley 46199566063dSJacob Faibussowitsch PetscCall(DMSetDimension(rdm, 3)); 46209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFromDAG(rdm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 46219371c9d4SSatish Balay } break; 4622d71ae5a4SJacob Faibussowitsch default: 4623d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)rdm), PETSC_ERR_ARG_WRONG, "Cannot create reference cell for cell type %s", DMPolytopeTypes[ct]); 46249318fe57SMatthew G. Knepley } 46259318fe57SMatthew G. Knepley { 46269318fe57SMatthew G. Knepley PetscInt Nv, v; 46279318fe57SMatthew G. Knepley 46289318fe57SMatthew G. Knepley /* Must create the celltype label here so that we do not automatically try to compute the types */ 46299566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(rdm, "celltype")); 46309566063dSJacob Faibussowitsch PetscCall(DMPlexSetCellType(rdm, 0, ct)); 46319566063dSJacob Faibussowitsch PetscCall(DMPlexGetChart(rdm, NULL, &Nv)); 46329566063dSJacob Faibussowitsch for (v = 1; v < Nv; ++v) PetscCall(DMPlexSetCellType(rdm, v, DM_POLYTOPE_POINT)); 46339318fe57SMatthew G. Knepley } 46349566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolateInPlace_Internal(rdm)); 46359566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)rdm, DMPolytopeTypes[ct])); 46363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46370a6ba040SMatthew G. Knepley } 46380a6ba040SMatthew G. Knepley 46399318fe57SMatthew G. Knepley /*@ 4640a1cb98faSBarry Smith DMPlexCreateReferenceCell - Create a `DMPLEX` with the appropriate FEM reference cell 46419318fe57SMatthew G. Knepley 46429318fe57SMatthew G. Knepley Collective 46439318fe57SMatthew G. Knepley 46449318fe57SMatthew G. Knepley Input Parameters: 46459318fe57SMatthew G. Knepley + comm - The communicator 46469318fe57SMatthew G. Knepley - ct - The cell type of the reference cell 46479318fe57SMatthew G. Knepley 46489318fe57SMatthew G. Knepley Output Parameter: 46499318fe57SMatthew G. Knepley . refdm - The reference cell 46509318fe57SMatthew G. Knepley 46519318fe57SMatthew G. Knepley Level: intermediate 46529318fe57SMatthew G. Knepley 465342747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateBoxMesh()` 46549318fe57SMatthew G. Knepley @*/ 4655d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateReferenceCell(MPI_Comm comm, DMPolytopeType ct, DM *refdm) 4656d71ae5a4SJacob Faibussowitsch { 46570a6ba040SMatthew G. Knepley PetscFunctionBegin; 46589566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, refdm)); 46599566063dSJacob Faibussowitsch PetscCall(DMSetType(*refdm, DMPLEX)); 46609566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(*refdm, ct)); 46613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46629318fe57SMatthew G. Knepley } 466379a015ccSMatthew G. Knepley 4664d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMPlexCreateBoundaryLabel_Private(DM dm, const char name[]) 4665d71ae5a4SJacob Faibussowitsch { 46669318fe57SMatthew G. Knepley DM plex; 46679318fe57SMatthew G. Knepley DMLabel label; 46689318fe57SMatthew G. Knepley PetscBool hasLabel; 46690a6ba040SMatthew G. Knepley 4670c22d3578SMatthew G. Knepley PetscFunctionBegin; 46719566063dSJacob Faibussowitsch PetscCall(DMHasLabel(dm, name, &hasLabel)); 46723ba16761SJacob Faibussowitsch if (hasLabel) PetscFunctionReturn(PETSC_SUCCESS); 46739566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(dm, name)); 46749566063dSJacob Faibussowitsch PetscCall(DMGetLabel(dm, name, &label)); 46759566063dSJacob Faibussowitsch PetscCall(DMConvert(dm, DMPLEX, &plex)); 46769566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(plex, 1, label)); 46771c8afea9SMatthew G. Knepley PetscCall(DMPlexLabelComplete(plex, label)); 46789566063dSJacob Faibussowitsch PetscCall(DMDestroy(&plex)); 46793ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46809318fe57SMatthew G. Knepley } 4681acdc6f61SToby Isaac 4682669647acSMatthew G. Knepley /* 4683669647acSMatthew 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. 4684669647acSMatthew G. Knepley 4685669647acSMatthew G. Knepley (x, y) -> (r, theta) = (x[1], (x[0] - lower[0]) * 2\pi/(upper[0] - lower[0])) 4686669647acSMatthew G. Knepley */ 4687d71ae5a4SJacob 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[]) 4688d71ae5a4SJacob Faibussowitsch { 4689669647acSMatthew G. Knepley const PetscReal low = PetscRealPart(constants[0]); 4690669647acSMatthew G. Knepley const PetscReal upp = PetscRealPart(constants[1]); 4691669647acSMatthew G. Knepley const PetscReal r = PetscRealPart(u[1]); 4692669647acSMatthew G. Knepley const PetscReal th = 2. * PETSC_PI * (PetscRealPart(u[0]) - low) / (upp - low); 4693669647acSMatthew G. Knepley 4694669647acSMatthew G. Knepley f0[0] = r * PetscCosReal(th); 4695669647acSMatthew G. Knepley f0[1] = r * PetscSinReal(th); 4696669647acSMatthew G. Knepley } 4697669647acSMatthew G. Knepley 46985390be7dSMatthew G. Knepley // Insert vertices and their joins, marked by depth 46995390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Vertices(DM dm, DMLabel label, DMLabel vlabel, PetscInt val, PetscInt n, const PetscInt vertices[]) 47005390be7dSMatthew G. Knepley { 47015390be7dSMatthew G. Knepley PetscFunctionBegin; 47025390be7dSMatthew G. Knepley PetscCall(DMPlexMarkSubmesh_Interpolated(dm, vlabel, val, PETSC_FALSE, PETSC_FALSE, label, NULL)); 47035390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 47045390be7dSMatthew G. Knepley } 47055390be7dSMatthew G. Knepley 47065390be7dSMatthew G. Knepley // Insert faces and their closures, marked by depth 47075390be7dSMatthew G. Knepley static PetscErrorCode ProcessCohesiveLabel_Faces(DM dm, DMLabel label, PetscInt n, const PetscInt faces[]) 47085390be7dSMatthew G. Knepley { 47095390be7dSMatthew G. Knepley PetscFunctionBegin; 47105390be7dSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) { 47115390be7dSMatthew G. Knepley const PetscInt point = faces[p]; 47125390be7dSMatthew G. Knepley PetscInt *closure = NULL; 47135390be7dSMatthew G. Knepley PetscInt clSize, pdepth; 47145390be7dSMatthew G. Knepley 47155390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, point, &pdepth)); 47165390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, point, pdepth)); 47175390be7dSMatthew G. Knepley PetscCall(DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 47185390be7dSMatthew G. Knepley for (PetscInt cl = 0; cl < clSize * 2; cl += 2) { 47195390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, closure[cl], &pdepth)); 47205390be7dSMatthew G. Knepley PetscCall(DMLabelSetValue(label, closure[cl], pdepth)); 47215390be7dSMatthew G. Knepley } 47225390be7dSMatthew G. Knepley PetscCall(DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &clSize, &closure)); 47235390be7dSMatthew G. Knepley } 47245390be7dSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 47255390be7dSMatthew G. Knepley } 47265390be7dSMatthew G. Knepley 47274e22dd4cSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscOptionsFindPairPrefix_Private(PetscOptions, const char pre[], const char name[], const char *option[], const char *value[], PetscBool *flg); 47284e22dd4cSMatthew G. Knepley 47295dca41c3SJed Brown const char *const DMPlexShapes[] = {"box", "box_surface", "ball", "sphere", "cylinder", "schwarz_p", "gyroid", "doublet", "annulus", "hypercubic", "zbox", "unknown", "DMPlexShape", "DM_SHAPE_", NULL}; 47309318fe57SMatthew G. Knepley 4731ce78bad3SBarry Smith static PetscErrorCode DMPlexCreateFromOptions_Internal(PetscOptionItems PetscOptionsObject, PetscBool *useCoordSpace, DM dm) 4732d71ae5a4SJacob Faibussowitsch { 47339318fe57SMatthew G. Knepley DMPlexShape shape = DM_SHAPE_BOX; 47349318fe57SMatthew G. Knepley DMPolytopeType cell = DM_POLYTOPE_TRIANGLE; 47359318fe57SMatthew G. Knepley PetscInt dim = 2; 4736b9da1bb3SMatthew G. Knepley PetscBool simplex = PETSC_TRUE, interpolate = PETSC_TRUE, orient = PETSC_FALSE, adjCone = PETSC_FALSE, adjClosure = PETSC_TRUE, refDomain = PETSC_FALSE; 4737d0812dedSMatthew G. Knepley PetscBool flg, flg2, fflg, strflg, bdfflg, nameflg; 47389318fe57SMatthew G. Knepley MPI_Comm comm; 4739ed5e4e85SVaclav Hapla char filename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4740ed5e4e85SVaclav Hapla char bdFilename[PETSC_MAX_PATH_LEN] = "<unspecified>"; 4741ed5e4e85SVaclav Hapla char plexname[PETSC_MAX_PATH_LEN] = ""; 47424e22dd4cSMatthew G. Knepley const char *option; 47439318fe57SMatthew G. Knepley 47449318fe57SMatthew G. Knepley PetscFunctionBegin; 4745708be2fdSJed Brown PetscCall(PetscLogEventBegin(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 47469566063dSJacob Faibussowitsch PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 47479318fe57SMatthew G. Knepley /* TODO Turn this into a registration interface */ 47489566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_filename", "File containing a mesh", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &fflg)); 4749d0812dedSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_file_contents", "Contents of a file format in a string", "DMPlexCreateFromFile", filename, filename, sizeof(filename), &strflg)); 47509566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_filename", "File containing a mesh boundary", "DMPlexCreateFromFile", bdFilename, bdFilename, sizeof(bdFilename), &bdfflg)); 47519566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_name", "Name of the mesh in the file", "DMPlexCreateFromFile", plexname, plexname, sizeof(plexname), &nameflg)); 47529566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cell", "Cell shape", "", DMPolytopeTypes, (PetscEnum)cell, (PetscEnum *)&cell, NULL)); 47539566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_reference_cell_domain", "Use a reference cell domain", "", refDomain, &refDomain, NULL)); 47549566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_shape", "Shape for built-in mesh", "", DMPlexShapes, (PetscEnum)shape, (PetscEnum *)&shape, &flg)); 47559566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_dim", "Topological dimension of the mesh", "DMGetDimension", dim, &dim, &flg, 0)); 47569566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_simplex", "Mesh cell shape", "", simplex, &simplex, &flg)); 47579566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate", "Flag to create edges and faces automatically", "", interpolate, &interpolate, &flg)); 4758b9da1bb3SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_orient", "Orient the constructed mesh", "DMPlexOrient", orient, &orient, &flg)); 47599566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_cone", "Set adjacency direction", "DMSetBasicAdjacency", adjCone, &adjCone, &flg)); 47609566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_adj_closure", "Set adjacency size", "DMSetBasicAdjacency", adjClosure, &adjClosure, &flg2)); 47619566063dSJacob Faibussowitsch if (flg || flg2) PetscCall(DMSetBasicAdjacency(dm, adjCone, adjClosure)); 47623f3e541fSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_adj", "Debug output level all adjacency computations", "", 0, &((DM_Plex *)dm->data)->printAdj, NULL, 0)); 47639318fe57SMatthew G. Knepley 476461a622f3SMatthew G. Knepley switch (cell) { 476561a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT: 476661a622f3SMatthew G. Knepley case DM_POLYTOPE_SEGMENT: 476761a622f3SMatthew G. Knepley case DM_POLYTOPE_POINT_PRISM_TENSOR: 476861a622f3SMatthew G. Knepley case DM_POLYTOPE_TRIANGLE: 476961a622f3SMatthew G. Knepley case DM_POLYTOPE_QUADRILATERAL: 477061a622f3SMatthew G. Knepley case DM_POLYTOPE_TETRAHEDRON: 4771d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_HEXAHEDRON: 4772d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_TRUE; 4773d71ae5a4SJacob Faibussowitsch break; 4774d71ae5a4SJacob Faibussowitsch default: 4775d71ae5a4SJacob Faibussowitsch *useCoordSpace = PETSC_FALSE; 4776d71ae5a4SJacob Faibussowitsch break; 477761a622f3SMatthew G. Knepley } 477861a622f3SMatthew G. Knepley 47799318fe57SMatthew G. Knepley if (fflg) { 47809318fe57SMatthew G. Knepley DM dmnew; 47811e4a82c4SMatthew G. Knepley const char *name; 47829318fe57SMatthew G. Knepley 47831e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 47841e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), filename, nameflg ? plexname : name, interpolate, &dmnew)); 47855de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 478669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 47879318fe57SMatthew G. Knepley } else if (refDomain) { 47889566063dSJacob Faibussowitsch PetscCall(DMPlexCreateReferenceCell_Internal(dm, cell)); 47899318fe57SMatthew G. Knepley } else if (bdfflg) { 47909318fe57SMatthew G. Knepley DM bdm, dmnew; 47911e4a82c4SMatthew G. Knepley const char *name; 47929318fe57SMatthew G. Knepley 47931e4a82c4SMatthew G. Knepley PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 47941e4a82c4SMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), bdFilename, nameflg ? plexname : name, interpolate, &bdm)); 47959566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)bdm, "bd_")); 47969566063dSJacob Faibussowitsch PetscCall(DMSetFromOptions(bdm)); 47979566063dSJacob Faibussowitsch PetscCall(DMPlexGenerate(bdm, NULL, interpolate, &dmnew)); 47989566063dSJacob Faibussowitsch PetscCall(DMDestroy(&bdm)); 47995de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 480069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 4801d0812dedSMatthew G. Knepley } else if (strflg) { 4802d0812dedSMatthew G. Knepley DM dmnew; 4803d0812dedSMatthew G. Knepley PetscViewer viewer; 4804d0812dedSMatthew G. Knepley const char *contents; 4805d0812dedSMatthew G. Knepley char *strname; 4806d0812dedSMatthew G. Knepley char tmpdir[PETSC_MAX_PATH_LEN]; 4807d0812dedSMatthew G. Knepley char tmpfilename[PETSC_MAX_PATH_LEN]; 4808d0812dedSMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 4809d0812dedSMatthew G. Knepley MPI_Comm comm; 4810d0812dedSMatthew G. Knepley PetscMPIInt rank; 4811d0812dedSMatthew G. Knepley 4812d0812dedSMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 4813d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Comm_rank(comm, &rank)); 4814d0812dedSMatthew G. Knepley PetscCall(PetscStrchr(filename, ':', &strname)); 4815d0812dedSMatthew G. Knepley PetscCheck(strname, comm, PETSC_ERR_ARG_WRONG, "File contents must have the form \"ext:string_name\", not %s", filename); 4816d0812dedSMatthew G. Knepley strname[0] = '\0'; 4817d0812dedSMatthew G. Knepley ++strname; 4818d0812dedSMatthew G. Knepley PetscCall(PetscDLSym(NULL, strname, (void **)&contents)); 4819d0812dedSMatthew G. Knepley PetscCheck(contents, comm, PETSC_ERR_ARG_WRONG, "Could not locate mesh string %s", strname); 4820d0812dedSMatthew G. Knepley PetscCall(PetscGetTmp(comm, tmpdir, PETSC_MAX_PATH_LEN)); 4821ed32af8cSMatthew G. Knepley PetscCall(PetscStrlcat(tmpdir, "/meshXXXXXX", PETSC_MAX_PATH_LEN)); 4822ed32af8cSMatthew G. Knepley PetscCall(PetscMkdtemp(tmpdir)); 4823ed32af8cSMatthew G. Knepley PetscCall(PetscSNPrintf(tmpfilename, PETSC_MAX_PATH_LEN, "%s/mesh.%s", tmpdir, filename)); 4824d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIOpen(comm, tmpfilename, &viewer)); 4825d0812dedSMatthew G. Knepley PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", contents)); 4826d0812dedSMatthew G. Knepley PetscCall(PetscViewerDestroy(&viewer)); 4827d0812dedSMatthew G. Knepley PetscCall(DMPlexCreateFromFile(PetscObjectComm((PetscObject)dm), tmpfilename, plexname, interpolate, &dmnew)); 4828ed32af8cSMatthew G. Knepley PetscCall(PetscRMTree(tmpdir)); 4829d0812dedSMatthew G. Knepley PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "%s Mesh", strname)); 4830d0812dedSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)dm, name)); 4831d0812dedSMatthew G. Knepley PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 4832d0812dedSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 48339318fe57SMatthew G. Knepley } else { 48349566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dm, DMPlexShapes[shape])); 48359318fe57SMatthew G. Knepley switch (shape) { 4836669647acSMatthew G. Knepley case DM_SHAPE_BOX: 48375dca41c3SJed Brown case DM_SHAPE_ZBOX: 4838669647acSMatthew G. Knepley case DM_SHAPE_ANNULUS: { 48399318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 48409318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 48419318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 48429318fe57SMatthew G. Knepley DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4843669647acSMatthew G. Knepley PetscBool isAnnular = shape == DM_SHAPE_ANNULUS ? PETSC_TRUE : PETSC_FALSE; 48449318fe57SMatthew G. Knepley PetscInt i, n; 48459318fe57SMatthew G. Knepley 48469318fe57SMatthew G. Knepley n = dim; 48479318fe57SMatthew G. Knepley for (i = 0; i < dim; ++i) faces[i] = (dim == 1 ? 1 : 4 - dim); 48489566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 48499318fe57SMatthew G. Knepley n = 3; 48509566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 485163a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Lower box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 48529318fe57SMatthew G. Knepley n = 3; 48539566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 485463a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Upper box point had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 48559318fe57SMatthew G. Knepley n = 3; 48569566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 485763a3b9bcSJacob Faibussowitsch PetscCheck(!flg || !(n != dim), comm, PETSC_ERR_ARG_SIZ, "Box boundary types had %" PetscInt_FMT " values, should have been %" PetscInt_FMT, n, dim); 4858669647acSMatthew G. Knepley 4859669647acSMatthew G. Knepley PetscCheck(!isAnnular || dim == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Only two dimensional annuli have been implemented"); 4860669647acSMatthew G. Knepley if (isAnnular) 4861669647acSMatthew G. Knepley for (i = 0; i < dim - 1; ++i) bdt[i] = DM_BOUNDARY_PERIODIC; 4862669647acSMatthew G. Knepley 48639318fe57SMatthew G. Knepley switch (cell) { 486461a622f3SMatthew G. Knepley case DM_POLYTOPE_TRI_PRISM_TENSOR: 48659566063dSJacob Faibussowitsch PetscCall(DMPlexCreateWedgeBoxMesh_Internal(dm, faces, lower, upper, bdt)); 4866d410b0cfSMatthew G. Knepley if (!interpolate) { 4867d410b0cfSMatthew G. Knepley DM udm; 4868d410b0cfSMatthew G. Knepley 48699566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 487069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 4871d410b0cfSMatthew G. Knepley } 48729318fe57SMatthew G. Knepley break; 4873d71ae5a4SJacob Faibussowitsch default: 48745dca41c3SJed Brown PetscCall(DMPlexCreateBoxMesh_Internal(dm, shape, dim, simplex, faces, lower, upper, bdt, interpolate)); 4875d71ae5a4SJacob Faibussowitsch break; 48769318fe57SMatthew G. Knepley } 4877669647acSMatthew G. Knepley if (isAnnular) { 4878669647acSMatthew G. Knepley DM cdm; 4879669647acSMatthew G. Knepley PetscDS cds; 4880669647acSMatthew G. Knepley PetscScalar bounds[2] = {lower[0], upper[0]}; 4881669647acSMatthew G. Knepley 4882669647acSMatthew G. Knepley // Fix coordinates for annular region 4883669647acSMatthew G. Knepley PetscCall(DMSetPeriodicity(dm, NULL, NULL, NULL)); 4884669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinatesLocal(dm, NULL)); 4885669647acSMatthew G. Knepley PetscCall(DMSetCellCoordinates(dm, NULL)); 4886*4c712d99Sksagiyam PetscCall(DMPlexCreateCoordinateSpace(dm, 1, PETSC_FALSE, PETSC_TRUE, NULL)); 4887669647acSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 4888669647acSMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 4889669647acSMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, 2, bounds)); 4890669647acSMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, boxToAnnulus)); 4891669647acSMatthew G. Knepley } 48929371c9d4SSatish Balay } break; 48939371c9d4SSatish Balay case DM_SHAPE_BOX_SURFACE: { 48949318fe57SMatthew G. Knepley PetscInt faces[3] = {0, 0, 0}; 48959318fe57SMatthew G. Knepley PetscReal lower[3] = {0, 0, 0}; 48969318fe57SMatthew G. Knepley PetscReal upper[3] = {1, 1, 1}; 48979318fe57SMatthew G. Knepley PetscInt i, n; 48989318fe57SMatthew G. Knepley 48999318fe57SMatthew G. Knepley n = dim + 1; 49009318fe57SMatthew G. Knepley for (i = 0; i < dim + 1; ++i) faces[i] = (dim + 1 == 1 ? 1 : 4 - (dim + 1)); 49019566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", faces, &n, &flg)); 49029318fe57SMatthew G. Knepley n = 3; 49039566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 490463a3b9bcSJacob 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); 49059318fe57SMatthew G. Knepley n = 3; 49069566063dSJacob Faibussowitsch PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 490763a3b9bcSJacob 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); 49089566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBoxSurfaceMesh_Internal(dm, dim + 1, faces, lower, upper, interpolate)); 49099371c9d4SSatish Balay } break; 49109371c9d4SSatish Balay case DM_SHAPE_SPHERE: { 49119318fe57SMatthew G. Knepley PetscReal R = 1.0; 49129318fe57SMatthew G. Knepley 49139566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_sphere_radius", "Radius of the sphere", "", R, &R, &flg)); 49149566063dSJacob Faibussowitsch PetscCall(DMPlexCreateSphereMesh_Internal(dm, dim, simplex, R)); 49159371c9d4SSatish Balay } break; 49169371c9d4SSatish Balay case DM_SHAPE_BALL: { 49179318fe57SMatthew G. Knepley PetscReal R = 1.0; 49189318fe57SMatthew G. Knepley 49199566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_ball_radius", "Radius of the ball", "", R, &R, &flg)); 49209566063dSJacob Faibussowitsch PetscCall(DMPlexCreateBallMesh_Internal(dm, dim, R)); 49219371c9d4SSatish Balay } break; 49229371c9d4SSatish Balay case DM_SHAPE_CYLINDER: { 49239318fe57SMatthew G. Knepley DMBoundaryType bdt = DM_BOUNDARY_NONE; 49249318fe57SMatthew G. Knepley PetscInt Nw = 6; 492549704ca5SMatthew G. Knepley PetscInt Nr = 0; 49269318fe57SMatthew G. Knepley 49279566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnum("-dm_plex_cylinder_bd", "Boundary type in the z direction", "", DMBoundaryTypes, (PetscEnum)bdt, (PetscEnum *)&bdt, NULL)); 49289566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_wedges", "Number of wedges around the cylinder", "", Nw, &Nw, NULL)); 492949704ca5SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_plex_cylinder_num_refine", "Number of refinements before projection", "", Nr, &Nr, NULL)); 49309318fe57SMatthew G. Knepley switch (cell) { 4931d71ae5a4SJacob Faibussowitsch case DM_POLYTOPE_TRI_PRISM_TENSOR: 4932d71ae5a4SJacob Faibussowitsch PetscCall(DMPlexCreateWedgeCylinderMesh_Internal(dm, Nw, interpolate)); 4933d71ae5a4SJacob Faibussowitsch break; 4934d71ae5a4SJacob Faibussowitsch default: 493549704ca5SMatthew G. Knepley PetscCall(DMPlexCreateHexCylinderMesh_Internal(dm, bdt, Nr)); 4936d71ae5a4SJacob Faibussowitsch break; 49379318fe57SMatthew G. Knepley } 49389371c9d4SSatish Balay } break; 4939b7f5c055SJed Brown case DM_SHAPE_SCHWARZ_P: // fallthrough 49409371c9d4SSatish Balay case DM_SHAPE_GYROID: { 4941b7f5c055SJed Brown PetscInt extent[3] = {1, 1, 1}, refine = 0, layers = 0, three; 4942b7f5c055SJed Brown PetscReal thickness = 0.; 4943b7f5c055SJed Brown DMBoundaryType periodic[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 4944b7f5c055SJed Brown DMPlexTPSType tps_type = shape == DM_SHAPE_SCHWARZ_P ? DMPLEX_TPS_SCHWARZ_P : DMPLEX_TPS_GYROID; 49451436d7faSJed Brown PetscBool tps_distribute; 49469566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-dm_plex_tps_extent", "Number of replicas for each of three dimensions", NULL, extent, (three = 3, &three), NULL)); 49479566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_refine", "Number of refinements", NULL, refine, &refine, NULL)); 49489566063dSJacob Faibussowitsch PetscCall(PetscOptionsEnumArray("-dm_plex_tps_periodic", "Periodicity in each of three dimensions", NULL, DMBoundaryTypes, (PetscEnum *)periodic, (three = 3, &three), NULL)); 49499566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_plex_tps_layers", "Number of layers in volumetric extrusion (or zero to not extrude)", NULL, layers, &layers, NULL)); 49509566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_tps_thickness", "Thickness of volumetric extrusion", NULL, thickness, &thickness, NULL)); 49519566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &tps_distribute)); 49529566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_tps_distribute", "Distribute the 2D mesh prior to refinement and extrusion", NULL, tps_distribute, &tps_distribute, NULL)); 49539566063dSJacob Faibussowitsch PetscCall(DMPlexCreateTPSMesh_Internal(dm, tps_type, extent, periodic, tps_distribute, refine, layers, thickness)); 49549371c9d4SSatish Balay } break; 49559371c9d4SSatish Balay case DM_SHAPE_DOUBLET: { 495605bd46c0SStefano Zampini DM dmnew; 495705bd46c0SStefano Zampini PetscReal rl = 0.0; 495805bd46c0SStefano Zampini 495905bd46c0SStefano Zampini PetscCall(PetscOptionsReal("-dm_plex_doublet_refinementlimit", "Refinement limit", NULL, rl, &rl, NULL)); 496005bd46c0SStefano Zampini PetscCall(DMPlexCreateDoublet(PetscObjectComm((PetscObject)dm), dim, simplex, interpolate, rl, &dmnew)); 49615de52c6dSVaclav Hapla PetscCall(DMPlexCopy_Internal(dm, PETSC_FALSE, PETSC_FALSE, dmnew)); 496269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &dmnew)); 49639371c9d4SSatish Balay } break; 4964cfb853baSMatthew G. Knepley case DM_SHAPE_HYPERCUBIC: { 49658d2ec52aSSatish Balay PetscInt *edges, overlap = 1; 4966cfb853baSMatthew G. Knepley PetscReal *lower, *upper; 4967cfb853baSMatthew G. Knepley DMBoundaryType *bdt; 4968cfb853baSMatthew G. Knepley PetscInt n, d; 4969cfb853baSMatthew G. Knepley 4970cfb853baSMatthew G. Knepley *useCoordSpace = PETSC_FALSE; 4971cfb853baSMatthew G. Knepley PetscCall(PetscMalloc4(dim, &edges, dim, &lower, dim, &upper, dim, &bdt)); 4972cfb853baSMatthew G. Knepley for (d = 0; d < dim; ++d) { 4973cfb853baSMatthew G. Knepley edges[d] = 1; 4974cfb853baSMatthew G. Knepley lower[d] = 0.; 4975cfb853baSMatthew G. Knepley upper[d] = 1.; 4976cfb853baSMatthew G. Knepley bdt[d] = DM_BOUNDARY_PERIODIC; 4977cfb853baSMatthew G. Knepley } 4978cfb853baSMatthew G. Knepley n = dim; 4979cfb853baSMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_plex_box_faces", "Number of faces along each dimension", "", edges, &n, &flg)); 4980cfb853baSMatthew G. Knepley n = dim; 4981cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_lower", "Lower left corner of box", "", lower, &n, &flg)); 4982cfb853baSMatthew 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); 4983cfb853baSMatthew G. Knepley n = dim; 4984cfb853baSMatthew G. Knepley PetscCall(PetscOptionsRealArray("-dm_plex_box_upper", "Upper right corner of box", "", upper, &n, &flg)); 4985cfb853baSMatthew 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); 4986cfb853baSMatthew G. Knepley n = dim; 4987cfb853baSMatthew G. Knepley PetscCall(PetscOptionsEnumArray("-dm_plex_box_bd", "Boundary type for each dimension", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 4988cfb853baSMatthew 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); 49898d2ec52aSSatish Balay PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", overlap, &overlap, NULL, 0)); 49908d2ec52aSSatish Balay PetscCall(DMPlexCreateHypercubicMesh_Internal(dm, dim, lower, upper, edges, overlap, bdt)); 4991cfb853baSMatthew G. Knepley PetscCall(PetscFree4(edges, lower, upper, bdt)); 4992cfb853baSMatthew G. Knepley } break; 4993d71ae5a4SJacob Faibussowitsch default: 4994d71ae5a4SJacob Faibussowitsch SETERRQ(comm, PETSC_ERR_SUP, "Domain shape %s is unsupported", DMPlexShapes[shape]); 49959318fe57SMatthew G. Knepley } 49969318fe57SMatthew G. Knepley } 49979566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 499848a46eb9SPierre Jolivet if (!((PetscObject)dm)->name && nameflg) PetscCall(PetscObjectSetName((PetscObject)dm, plexname)); 4999b9da1bb3SMatthew G. Knepley if (orient) PetscCall(DMPlexOrient(dm)); 50004e22dd4cSMatthew G. Knepley // Allow label creation 50014e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_label_", &option, NULL, &flg)); 50024e22dd4cSMatthew G. Knepley if (flg) { 50034e22dd4cSMatthew G. Knepley DMLabel label; 50044e22dd4cSMatthew G. Knepley PetscInt points[1024], n = 1024; 50054e22dd4cSMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 50064e22dd4cSMatthew G. Knepley const char *name = &option[14]; 50074e22dd4cSMatthew G. Knepley 50084e22dd4cSMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 50094e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 50104e22dd4cSMatthew G. Knepley fulloption[0] = '-'; 50114e22dd4cSMatthew G. Knepley fulloption[1] = 0; 50124e22dd4cSMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, option, PETSC_MAX_PATH_LEN)); 50134e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, NULL)); 50144e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < n; ++p) PetscCall(DMLabelSetValue(label, points[p], 1)); 50154e22dd4cSMatthew G. Knepley } 5016dd0eeac9SMatthew G. Knepley // Allow cohesive label creation 5017dd0eeac9SMatthew G. Knepley // Faces are input, completed, and all points are marked with their depth 5018dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsFindPairPrefix_Private(NULL, ((PetscObject)dm)->prefix, "-dm_plex_cohesive_label_", &option, NULL, &flg)); 5019dd0eeac9SMatthew G. Knepley if (flg) { 5020dd0eeac9SMatthew G. Knepley DMLabel label; 5021dd0eeac9SMatthew G. Knepley PetscInt points[1024], n, pStart, pEnd, Nl = 1; 50225390be7dSMatthew G. Knepley PetscBool noCreate = PETSC_FALSE; 5023dd0eeac9SMatthew G. Knepley char fulloption[PETSC_MAX_PATH_LEN]; 5024dd0eeac9SMatthew G. Knepley char name[PETSC_MAX_PATH_LEN]; 5025dd0eeac9SMatthew G. Knepley size_t len; 5026dd0eeac9SMatthew G. Knepley 5027dd0eeac9SMatthew G. Knepley PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 5028dd0eeac9SMatthew G. Knepley PetscCall(PetscStrncpy(name, &option[23], PETSC_MAX_PATH_LEN)); 5029dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlen(name, &len)); 5030dd0eeac9SMatthew G. Knepley if (name[len - 1] == '0') Nl = 10; 5031dd0eeac9SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 50326497c311SBarry Smith if (l > 0) name[len - 1] = (char)('0' + l); 5033dd0eeac9SMatthew G. Knepley fulloption[0] = 0; 5034dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, "-dm_plex_cohesive_label_", 32)); 5035dd0eeac9SMatthew G. Knepley PetscCall(PetscStrlcat(fulloption, name, PETSC_MAX_PATH_LEN - 32)); 5036dd0eeac9SMatthew G. Knepley n = 1024; 5037dd0eeac9SMatthew G. Knepley PetscCall(PetscOptionsGetIntArray(NULL, ((PetscObject)dm)->prefix, fulloption, points, &n, &flg)); 5038dd0eeac9SMatthew G. Knepley if (!flg) break; 50395390be7dSMatthew G. Knepley PetscCall(DMHasLabel(dm, name, &noCreate)); 50405390be7dSMatthew G. Knepley if (noCreate) { 50415390be7dSMatthew G. Knepley DMLabel inlabel; 50425390be7dSMatthew G. Knepley IS pointIS; 50435390be7dSMatthew G. Knepley const PetscInt *lpoints; 50445390be7dSMatthew G. Knepley PetscInt pdep, ln, inval = points[0]; 50455390be7dSMatthew G. Knepley char newname[PETSC_MAX_PATH_LEN]; 50465390be7dSMatthew G. Knepley 50475390be7dSMatthew G. Knepley PetscCheck(n == 1, comm, PETSC_ERR_ARG_WRONG, "Must specify a label value with this option"); 50485390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &inlabel)); 50495390be7dSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(inlabel, inval, &pointIS)); 50505390be7dSMatthew G. Knepley PetscCall(ISGetLocalSize(pointIS, &ln)); 50515390be7dSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &lpoints)); 50525390be7dSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, lpoints[0], &pdep)); 50535390be7dSMatthew G. Knepley PetscCall(PetscSNPrintf(newname, PETSC_MAX_PATH_LEN, "%s%" PetscInt_FMT, name, points[0])); 50545390be7dSMatthew G. Knepley PetscCall(DMCreateLabel(dm, newname)); 50555390be7dSMatthew G. Knepley PetscCall(DMGetLabel(dm, newname, &label)); 50565390be7dSMatthew G. Knepley if (!pdep) PetscCall(ProcessCohesiveLabel_Vertices(dm, label, inlabel, inval, ln, lpoints)); 50575390be7dSMatthew G. Knepley else PetscCall(ProcessCohesiveLabel_Faces(dm, label, ln, lpoints)); 50585390be7dSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &lpoints)); 50595390be7dSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 50605390be7dSMatthew G. Knepley } else { 5061dd0eeac9SMatthew G. Knepley PetscCall(DMCreateLabel(dm, name)); 5062dd0eeac9SMatthew G. Knepley PetscCall(DMGetLabel(dm, name, &label)); 5063dd0eeac9SMatthew G. Knepley if (pStart >= pEnd) n = 0; 50645390be7dSMatthew G. Knepley PetscCall(ProcessCohesiveLabel_Faces(dm, label, n, points)); 5065dd0eeac9SMatthew G. Knepley } 5066dd0eeac9SMatthew G. Knepley PetscCall(DMPlexOrientLabel(dm, label)); 50670542aa8cSMatthew G. Knepley PetscCall(DMPlexLabelCohesiveComplete(dm, label, NULL, 1, PETSC_FALSE, PETSC_FALSE, NULL)); 5068dd0eeac9SMatthew G. Knepley } 5069dd0eeac9SMatthew G. Knepley } 50705390be7dSMatthew G. Knepley PetscCall(DMViewFromOptions(dm, NULL, "-created_dm_view")); 5071708be2fdSJed Brown PetscCall(PetscLogEventEnd(DMPLEX_CreateFromOptions, dm, 0, 0, 0)); 50723ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50730a6ba040SMatthew G. Knepley } 50740a6ba040SMatthew G. Knepley 5075ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_NonRefinement_Plex(DM dm, PetscOptionItems PetscOptionsObject) 5076d71ae5a4SJacob Faibussowitsch { 50770a6ba040SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 50787f9d8d6cSVaclav Hapla PetscBool flg, flg2; 50799318fe57SMatthew G. Knepley char bdLabel[PETSC_MAX_PATH_LEN]; 5080adc21957SMatthew G. Knepley char method[PETSC_MAX_PATH_LEN]; 50810a6ba040SMatthew G. Knepley 50820a6ba040SMatthew G. Knepley PetscFunctionBegin; 50830a6ba040SMatthew G. Knepley /* Handle viewing */ 50849566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_print_set_values", "Output all set values info", "DMPlexMatSetClosure", PETSC_FALSE, &mesh->printSetValues, NULL)); 50855962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fem", "Debug output level for all fem computations", "DMPlexSNESComputeResidualFEM", 0, &mesh->printFEM, NULL, 0)); 50865962854dSMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_fvm", "Debug output level for all fvm computations", "DMPlexSNESComputeResidualFVM", 0, &mesh->printFVM, NULL, 0)); 50879566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_print_tol", "Tolerance for FEM output", "DMPlexSNESComputeResidualFEM", mesh->printTol, &mesh->printTol, NULL)); 50889566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_plex_print_l2", "Debug output level all L2 diff computations", "DMComputeL2Diff", 0, &mesh->printL2, NULL, 0)); 5089f5867de0SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_locate", "Debug output level all point location computations", "DMLocatePoints", 0, &mesh->printLocate, NULL, 0)); 5090a77a5016SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_plex_print_project", "Debug output level all projection computations", "DMPlexProject", 0, &mesh->printProject, NULL, 0)); 50919566063dSJacob Faibussowitsch PetscCall(DMMonitorSetFromOptions(dm, "-dm_plex_monitor_throughput", "Monitor the simulation throughput", "DMPlexMonitorThroughput", DMPlexMonitorThroughput, NULL, &flg)); 50929566063dSJacob Faibussowitsch if (flg) PetscCall(PetscLogDefaultBegin()); 50935e2c5519SMatthew G. Knepley // Interpolation 50945e2c5519SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_interpolate_prefer_tensor", "When different orderings exist, prefer the tensor order", "DMPlexSetInterpolationPreferTensor", mesh->interpolatePreferTensor, &mesh->interpolatePreferTensor, NULL)); 50959318fe57SMatthew G. Knepley /* Labeling */ 50969566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_boundary_label", "Label to mark the mesh boundary", "", bdLabel, bdLabel, sizeof(bdLabel), &flg)); 50979566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexCreateBoundaryLabel_Private(dm, bdLabel)); 5098953fc75cSMatthew G. Knepley /* Point Location */ 50999566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_hash_location", "Use grid hashing for point location", "DMInterpolate", PETSC_FALSE, &mesh->useHashLocation, NULL)); 51000848f4b5SMatthew G. Knepley /* Partitioning and distribution */ 51019566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_partition_balance", "Attempt to evenly divide points on partition boundary between processes", "DMPlexSetPartitionBalance", PETSC_FALSE, &mesh->partitionBalance, NULL)); 5102d02c7345SMatthew G. Knepley /* Reordering */ 5103adc21957SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_reorder_section", "Compute point permutation for local section", "DMReorderSectionSetDefault", PETSC_FALSE, &flg2, &flg)); 5104adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetDefault(dm, flg2 ? DM_REORDER_DEFAULT_TRUE : DM_REORDER_DEFAULT_FALSE)); 5105adc21957SMatthew G. Knepley PetscCall(PetscOptionsString("-dm_reorder_section_type", "Reordering method for local section", "DMReorderSectionSetType", method, method, PETSC_MAX_PATH_LEN, &flg)); 5106adc21957SMatthew G. Knepley if (flg) PetscCall(DMReorderSectionSetType(dm, method)); 51072e62ab5aSMatthew G. Knepley /* Generation and remeshing */ 51089566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_remesh_bd", "Allow changes to the boundary on remeshing", "DMAdapt", PETSC_FALSE, &mesh->remeshBd, NULL)); 510961f058f9SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_save_transform", "Save the transform producing this mesh", "DMAdapt", PETSC_FALSE, &mesh->saveTransform, NULL)); 5110b29cfa1cSToby Isaac /* Projection behavior */ 5111d5b43468SJose E. Roman PetscCall(PetscOptionsBoundedInt("-dm_plex_max_projection_height", "Maximum mesh point height used to project locally", "DMPlexSetMaxProjectionHeight", 0, &mesh->maxProjectionHeight, NULL, 0)); 51129566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_regular_refinement", "Use special nested projection algorithm for regular refinement", "DMPlexSetRegularRefinement", mesh->regularRefinement, &mesh->regularRefinement, NULL)); 5113f12cf164SMatthew G. Knepley /* Checking structure */ 5114f12cf164SMatthew G. Knepley { 51157f9d8d6cSVaclav Hapla PetscBool all = PETSC_FALSE; 5116f12cf164SMatthew G. Knepley 51177f9d8d6cSVaclav Hapla PetscCall(PetscOptionsBool("-dm_plex_check_all", "Perform all basic checks", "DMPlexCheck", PETSC_FALSE, &all, NULL)); 51187f9d8d6cSVaclav Hapla if (all) { 51197f9d8d6cSVaclav Hapla PetscCall(DMPlexCheck(dm)); 51207f9d8d6cSVaclav Hapla } else { 51219566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_symmetry", "Check that the adjacency information in the mesh is symmetric", "DMPlexCheckSymmetry", PETSC_FALSE, &flg, &flg2)); 51227f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSymmetry(dm)); 51239566063dSJacob 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)); 51247f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckSkeleton(dm, 0)); 51259566063dSJacob 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)); 51267f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckFaces(dm, 0)); 51279566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_geometry", "Check that cells have positive volume", "DMPlexCheckGeometry", PETSC_FALSE, &flg, &flg2)); 51287f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckGeometry(dm)); 51299566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_pointsf", "Check some necessary conditions for PointSF", "DMPlexCheckPointSF", PETSC_FALSE, &flg, &flg2)); 5130d7d32a9aSMatthew G. Knepley if (flg && flg2) PetscCall(DMPlexCheckPointSF(dm, NULL, PETSC_FALSE)); 51319566063dSJacob 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)); 51327f9d8d6cSVaclav Hapla if (flg && flg2) PetscCall(DMPlexCheckInterfaceCones(dm)); 51337f9d8d6cSVaclav Hapla } 51349566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_check_cell_shape", "Check cell shape", "DMPlexCheckCellShape", PETSC_FALSE, &flg, &flg2)); 51359566063dSJacob Faibussowitsch if (flg && flg2) PetscCall(DMPlexCheckCellShape(dm, PETSC_TRUE, PETSC_DETERMINE)); 5136f12cf164SMatthew G. Knepley } 51379318fe57SMatthew G. Knepley { 51389318fe57SMatthew G. Knepley PetscReal scale = 1.0; 51394f3833eaSMatthew G. Knepley 51409566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_plex_scale", "Scale factor for mesh coordinates", "DMPlexScale", scale, &scale, &flg)); 51419318fe57SMatthew G. Knepley if (flg) { 51429318fe57SMatthew G. Knepley Vec coordinates, coordinatesLocal; 51439318fe57SMatthew G. Knepley 51449566063dSJacob Faibussowitsch PetscCall(DMGetCoordinates(dm, &coordinates)); 51459566063dSJacob Faibussowitsch PetscCall(DMGetCoordinatesLocal(dm, &coordinatesLocal)); 51469566063dSJacob Faibussowitsch PetscCall(VecScale(coordinates, scale)); 51479566063dSJacob Faibussowitsch PetscCall(VecScale(coordinatesLocal, scale)); 51489318fe57SMatthew G. Knepley } 51499318fe57SMatthew G. Knepley } 51509566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(mesh->partitioner)); 51513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 515268d4fef7SMatthew G. Knepley } 515368d4fef7SMatthew G. Knepley 5154ce78bad3SBarry Smith PetscErrorCode DMSetFromOptions_Overlap_Plex(DM dm, PetscOptionItems PetscOptionsObject, PetscInt *overlap) 5155d71ae5a4SJacob Faibussowitsch { 5156c506a872SMatthew G. Knepley PetscInt numOvLabels = 16, numOvExLabels = 16; 5157c506a872SMatthew G. Knepley char *ovLabelNames[16], *ovExLabelNames[16]; 5158c506a872SMatthew G. Knepley PetscInt numOvValues = 16, numOvExValues = 16, l; 5159c506a872SMatthew G. Knepley PetscBool flg; 5160c506a872SMatthew G. Knepley 5161c506a872SMatthew G. Knepley PetscFunctionBegin; 5162c506a872SMatthew G. Knepley PetscCall(PetscOptionsBoundedInt("-dm_distribute_overlap", "The size of the overlap halo", "DMPlexDistribute", *overlap, overlap, NULL, 0)); 5163c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_labels", "List of overlap label names", "DMPlexDistribute", ovLabelNames, &numOvLabels, &flg)); 5164c506a872SMatthew G. Knepley if (!flg) numOvLabels = 0; 5165c506a872SMatthew G. Knepley if (numOvLabels) { 5166c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvLabels = numOvLabels; 5167c506a872SMatthew G. Knepley for (l = 0; l < numOvLabels; ++l) { 5168c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovLabelNames[l], &((DM_Plex *)dm->data)->ovLabels[l])); 5169c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovLabelNames[l]); 5170c506a872SMatthew G. Knepley PetscCall(PetscFree(ovLabelNames[l])); 5171c506a872SMatthew G. Knepley } 5172c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_values", "List of overlap label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovValues, &numOvValues, &flg)); 5173c506a872SMatthew G. Knepley if (!flg) numOvValues = 0; 5174c506a872SMatthew 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); 5175c506a872SMatthew G. Knepley 5176c506a872SMatthew G. Knepley PetscCall(PetscOptionsStringArray("-dm_distribute_overlap_exclude_labels", "List of overlap exclude label names", "DMPlexDistribute", ovExLabelNames, &numOvExLabels, &flg)); 5177c506a872SMatthew G. Knepley if (!flg) numOvExLabels = 0; 5178c506a872SMatthew G. Knepley ((DM_Plex *)dm->data)->numOvExLabels = numOvExLabels; 5179c506a872SMatthew G. Knepley for (l = 0; l < numOvExLabels; ++l) { 5180c506a872SMatthew G. Knepley PetscCall(DMGetLabel(dm, ovExLabelNames[l], &((DM_Plex *)dm->data)->ovExLabels[l])); 5181c506a872SMatthew G. Knepley PetscCheck(((DM_Plex *)dm->data)->ovExLabels[l], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid label name %s", ovExLabelNames[l]); 5182c506a872SMatthew G. Knepley PetscCall(PetscFree(ovExLabelNames[l])); 5183c506a872SMatthew G. Knepley } 5184c506a872SMatthew G. Knepley PetscCall(PetscOptionsIntArray("-dm_distribute_overlap_exclude_values", "List of overlap exclude label values", "DMPlexDistribute", ((DM_Plex *)dm->data)->ovExValues, &numOvExValues, &flg)); 5185c506a872SMatthew G. Knepley if (!flg) numOvExValues = 0; 5186c506a872SMatthew 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); 5187c506a872SMatthew G. Knepley } 51883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5189c506a872SMatthew G. Knepley } 5190c506a872SMatthew G. Knepley 5191ce78bad3SBarry Smith static PetscErrorCode DMSetFromOptions_Plex(DM dm, PetscOptionItems PetscOptionsObject) 5192d71ae5a4SJacob Faibussowitsch { 5193bdf63967SMatthew G. Knepley PetscFunctionList ordlist; 5194bdf63967SMatthew G. Knepley char oname[256]; 51954e22dd4cSMatthew G. Knepley char sublabelname[PETSC_MAX_PATH_LEN] = ""; 5196adc21957SMatthew G. Knepley DMReorderDefaultFlag reorder; 5197d410b0cfSMatthew G. Knepley PetscReal volume = -1.0; 51989318fe57SMatthew G. Knepley PetscInt prerefine = 0, refine = 0, r, coarsen = 0, overlap = 0, extLayers = 0, dim; 5199530e699aSMatthew 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; 520068d4fef7SMatthew G. Knepley 520168d4fef7SMatthew G. Knepley PetscFunctionBegin; 5202d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "DMPlex Options"); 5203dd4c3f67SMatthew G. Knepley if (dm->cloneOpts) goto non_refine; 52049318fe57SMatthew G. Knepley /* Handle automatic creation */ 52059566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 5206530e699aSMatthew G. Knepley if (dim < 0) PetscCall(DMPlexCreateFromOptions_Internal(PetscOptionsObject, &coordSpace, dm)); 52076bc1bd01Sksagiyam PetscCall(DMGetDimension(dm, &dim)); 5208d89e6e46SMatthew G. Knepley /* Handle interpolation before distribution */ 52099566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_interpolate_pre", "Flag to interpolate mesh before distribution", "", interpolate, &interpolate, &flg)); 5210d89e6e46SMatthew G. Knepley if (flg) { 5211d89e6e46SMatthew G. Knepley DMPlexInterpolatedFlag interpolated; 5212d89e6e46SMatthew G. Knepley 52139566063dSJacob Faibussowitsch PetscCall(DMPlexIsInterpolated(dm, &interpolated)); 5214d89e6e46SMatthew G. Knepley if (interpolated == DMPLEX_INTERPOLATED_FULL && !interpolate) { 5215d89e6e46SMatthew G. Knepley DM udm; 5216d89e6e46SMatthew G. Knepley 52179566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(dm, &udm)); 521869d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &udm)); 5219d89e6e46SMatthew G. Knepley } else if (interpolated != DMPLEX_INTERPOLATED_FULL && interpolate) { 5220d89e6e46SMatthew G. Knepley DM idm; 5221d89e6e46SMatthew G. Knepley 52229566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(dm, &idm)); 522369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &idm)); 5224d89e6e46SMatthew G. Knepley } 5225d89e6e46SMatthew G. Knepley } 52264e22dd4cSMatthew G. Knepley // Handle submesh selection before distribution 52274e22dd4cSMatthew G. Knepley PetscCall(PetscOptionsString("-dm_plex_submesh", "Label to use for submesh selection", "", sublabelname, sublabelname, PETSC_MAX_PATH_LEN, &flg)); 52284e22dd4cSMatthew G. Knepley if (flg) { 52294e22dd4cSMatthew G. Knepley DM subdm; 52304e22dd4cSMatthew G. Knepley DMLabel label; 52314e22dd4cSMatthew G. Knepley IS valueIS, pointIS; 52324e22dd4cSMatthew G. Knepley const PetscInt *values, *points; 52334e22dd4cSMatthew G. Knepley PetscBool markedFaces = PETSC_FALSE; 52344e22dd4cSMatthew G. Knepley PetscInt Nv, value, Np; 52354e22dd4cSMatthew G. Knepley 52364e22dd4cSMatthew G. Knepley PetscCall(DMGetLabel(dm, sublabelname, &label)); 52374e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetNumValues(label, &Nv)); 52384e22dd4cSMatthew 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); 52394e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetValueIS(label, &valueIS)); 52404e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(valueIS, &values)); 52414e22dd4cSMatthew G. Knepley value = values[0]; 52424e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(valueIS, &values)); 52434e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&valueIS)); 52444e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumSize(label, value, &Np)); 52454e22dd4cSMatthew G. Knepley PetscCall(DMLabelGetStratumIS(label, value, &pointIS)); 52464e22dd4cSMatthew G. Knepley PetscCall(ISGetIndices(pointIS, &points)); 52474e22dd4cSMatthew G. Knepley for (PetscInt p = 0; p < Np; ++p) { 52484e22dd4cSMatthew G. Knepley PetscInt pdepth; 52494e22dd4cSMatthew G. Knepley 52504e22dd4cSMatthew G. Knepley PetscCall(DMPlexGetPointDepth(dm, points[p], &pdepth)); 52514e22dd4cSMatthew G. Knepley if (pdepth) { 52524e22dd4cSMatthew G. Knepley markedFaces = PETSC_TRUE; 52534e22dd4cSMatthew G. Knepley break; 52544e22dd4cSMatthew G. Knepley } 52554e22dd4cSMatthew G. Knepley } 52564e22dd4cSMatthew G. Knepley PetscCall(ISRestoreIndices(pointIS, &points)); 52574e22dd4cSMatthew G. Knepley PetscCall(ISDestroy(&pointIS)); 52584e22dd4cSMatthew G. Knepley PetscCall(DMPlexCreateSubmesh(dm, label, value, markedFaces, &subdm)); 52594e22dd4cSMatthew G. Knepley PetscCall(DMPlexReplace_Internal(dm, &subdm)); 52604e22dd4cSMatthew G. Knepley PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 52614e22dd4cSMatthew G. Knepley } 52629b44eab4SMatthew G. Knepley /* Handle DMPlex refinement before distribution */ 52639566063dSJacob Faibussowitsch PetscCall(DMPlexGetRefinementUniform(dm, &uniformOrig)); 52649566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_pre", "The number of refinements before distribution", "DMCreate", prerefine, &prerefine, NULL, 0)); 52659566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap_pre", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 52669566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_uniform_pre", "Flag for uniform refinement before distribution", "DMCreate", uniform, &uniform, &flg)); 52679566063dSJacob Faibussowitsch if (flg) PetscCall(DMPlexSetRefinementUniform(dm, uniform)); 52689566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-dm_refine_volume_limit_pre", "The maximum cell volume after refinement before distribution", "DMCreate", volume, &volume, &flg)); 52699318fe57SMatthew G. Knepley if (flg) { 52709566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, PETSC_FALSE)); 52719566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementLimit(dm, volume)); 52729318fe57SMatthew G. Knepley prerefine = PetscMax(prerefine, 1); 52739318fe57SMatthew G. Knepley } 5274b23db253SStefano Zampini if (prerefine) PetscCall(DMLocalizeCoordinates(dm)); 52759b44eab4SMatthew G. Knepley for (r = 0; r < prerefine; ++r) { 52769b44eab4SMatthew G. Knepley DM rdm; 52772192575eSBarry Smith PetscPointFn *coordFunc; 52789b44eab4SMatthew G. Knepley 5279509b31aaSMatthew G. Knepley PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc)); 5280dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 52819566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 528269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 5283dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 528461a622f3SMatthew G. Knepley if (coordFunc && remap) { 52859566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 5286509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, coordFunc)); 52879b44eab4SMatthew G. Knepley } 52889b44eab4SMatthew G. Knepley } 52899566063dSJacob Faibussowitsch PetscCall(DMPlexSetRefinementUniform(dm, uniformOrig)); 52909318fe57SMatthew G. Knepley /* Handle DMPlex extrusion before distribution */ 52919566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_extrude", "The number of layers to extrude", "", extLayers, &extLayers, NULL, 0)); 52929318fe57SMatthew G. Knepley if (extLayers) { 52939318fe57SMatthew G. Knepley DM edm; 52949318fe57SMatthew G. Knepley 52959566063dSJacob Faibussowitsch PetscCall(DMExtrude(dm, extLayers, &edm)); 529669d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &edm)); 5297509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, NULL)); 5298dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5299d410b0cfSMatthew G. Knepley extLayers = 0; 53005e17fc22SAidan Hamilton PetscCall(DMGetDimension(dm, &dim)); 53019318fe57SMatthew G. Knepley } 5302bdf63967SMatthew G. Knepley /* Handle DMPlex reordering before distribution */ 53036bc1bd01Sksagiyam PetscCall(DMPlexReorderGetDefault(dm, &reorder)); 53049566063dSJacob Faibussowitsch PetscCall(MatGetOrderingList(&ordlist)); 53056bc1bd01Sksagiyam PetscCall(PetscStrncpy(oname, MATORDERINGNATURAL, sizeof(oname))); 53069566063dSJacob Faibussowitsch PetscCall(PetscOptionsFList("-dm_plex_reorder", "Set mesh reordering type", "DMPlexGetOrdering", ordlist, MATORDERINGNATURAL, oname, sizeof(oname), &flg)); 5307adc21957SMatthew G. Knepley if (reorder == DM_REORDER_DEFAULT_TRUE || flg) { 5308bdf63967SMatthew G. Knepley DM pdm; 5309bdf63967SMatthew G. Knepley IS perm; 5310bdf63967SMatthew G. Knepley 53119566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering(dm, oname, NULL, &perm)); 53129566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &pdm)); 53139566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 531469d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &pdm)); 5315dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 5316bdf63967SMatthew G. Knepley } 53179b44eab4SMatthew G. Knepley /* Handle DMPlex distribution */ 53189566063dSJacob Faibussowitsch PetscCall(DMPlexDistributeGetDefault(dm, &distribute)); 5319c506a872SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute", "Flag to redistribute a mesh among processes", "DMPlexDistribute", distribute, &distribute, NULL)); 5320a286e215SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_distribute_save_sf", "Flag to save the migration SF", "DMPlexSetMigrationSF", saveSF, &saveSF, NULL)); 5321dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_Overlap_Plex(dm, PetscOptionsObject, &overlap)); 53229b44eab4SMatthew G. Knepley if (distribute) { 53239b44eab4SMatthew G. Knepley DM pdm = NULL; 53249b44eab4SMatthew G. Knepley PetscPartitioner part; 5325a286e215SMatthew G. Knepley PetscSF sfMigration; 53269566ead2SJames Wright PetscBool use_partition_balance; 53279b44eab4SMatthew G. Knepley 53289566063dSJacob Faibussowitsch PetscCall(DMPlexGetPartitioner(dm, &part)); 53299566063dSJacob Faibussowitsch PetscCall(PetscPartitionerSetFromOptions(part)); 53309566ead2SJames Wright PetscCall(DMPlexGetPartitionBalance(dm, &use_partition_balance)); 53319566ead2SJames 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)); 53329566ead2SJames Wright if (flg) PetscCall(DMPlexSetPartitionBalance(dm, use_partition_balance)); 5333a286e215SMatthew G. Knepley PetscCall(DMPlexDistribute(dm, overlap, &sfMigration, &pdm)); 53345d2873a6SJames Wright if (pdm) { 53355d2873a6SJames Wright // Delete the local section to force the existing one to be rebuilt with the distributed DM 53365d2873a6SJames Wright PetscCall(DMSetLocalSection(dm, pdm->localSection)); 53375d2873a6SJames Wright PetscCall(DMPlexReplace_Internal(dm, &pdm)); 53385d2873a6SJames Wright } 5339a286e215SMatthew G. Knepley if (saveSF) PetscCall(DMPlexSetMigrationSF(dm, sfMigration)); 5340a286e215SMatthew G. Knepley PetscCall(PetscSFDestroy(&sfMigration)); 53419b44eab4SMatthew G. Knepley } 53424054ae39SJames Wright 53434054ae39SJames Wright { 53444054ae39SJames Wright PetscBool useBoxLabel = PETSC_FALSE; 53454054ae39SJames Wright PetscCall(PetscOptionsBool("-dm_plex_box_label", "Create 'Face Sets' assuming boundary faces align with cartesian directions", "DMCreate", useBoxLabel, &useBoxLabel, NULL)); 5346d7d2d1d2SJames Wright if (useBoxLabel) { 5347d7d2d1d2SJames Wright PetscInt n = 3; 5348d7d2d1d2SJames Wright DMBoundaryType bdt[3] = {DM_BOUNDARY_NONE, DM_BOUNDARY_NONE, DM_BOUNDARY_NONE}; 5349d7d2d1d2SJames Wright 5350d7d2d1d2SJames Wright PetscCall(PetscOptionsEnumArray("-dm_plex_box_label_bd", "Boundary type for each dimension when using -dm_plex_box_label", "", DMBoundaryTypes, (PetscEnum *)bdt, &n, &flg)); 5351d7d2d1d2SJames 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); 5352d7d2d1d2SJames Wright PetscCall(DMPlexSetBoxLabel_Internal(dm, bdt)); 5353d7d2d1d2SJames Wright } 53544054ae39SJames Wright } 5355d2b2dc1eSMatthew G. Knepley /* Must check CEED options before creating function space for coordinates */ 5356d2b2dc1eSMatthew G. Knepley { 5357d2b2dc1eSMatthew G. Knepley PetscBool useCeed = PETSC_FALSE, flg; 5358d2b2dc1eSMatthew G. Knepley 5359d2b2dc1eSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_plex_use_ceed", "Use LibCEED as the FEM backend", "DMPlexSetUseCeed", useCeed, &useCeed, &flg)); 5360d2b2dc1eSMatthew G. Knepley if (flg) PetscCall(DMPlexSetUseCeed(dm, useCeed)); 5361d2b2dc1eSMatthew G. Knepley } 53629318fe57SMatthew G. Knepley /* Create coordinate space */ 5363530e699aSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_coord_space", "Use an FEM space for coordinates", "", coordSpace, &coordSpace, NULL)); 5364530e699aSMatthew G. Knepley if (coordSpace) { 5365e44f6aebSMatthew G. Knepley PetscInt degree = 1, deg; 53665515ebd3SMatthew G. Knepley PetscInt height = 0; 53675515ebd3SMatthew G. Knepley DM cdm; 5368530e699aSMatthew G. Knepley PetscBool localize = PETSC_TRUE, sparseLocalize = PETSC_TRUE; 53699318fe57SMatthew G. Knepley 53709566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-dm_coord_petscspace_degree", "FEM degree for coordinate space", "", degree, °ree, NULL)); 5371e44f6aebSMatthew G. Knepley PetscCall(DMGetCoordinateDegree_Internal(dm, °)); 5372*4c712d99Sksagiyam if (coordSpace && deg <= 1) PetscCall(DMPlexCreateCoordinateSpace(dm, degree, PETSC_FALSE, PETSC_TRUE, NULL)); 53735515ebd3SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5374530e699aSMatthew G. Knepley if (!coordSpace) { 537561a622f3SMatthew G. Knepley PetscDS cds; 537661a622f3SMatthew G. Knepley PetscObject obj; 537761a622f3SMatthew G. Knepley PetscClassId id; 537861a622f3SMatthew G. Knepley 53799566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 53809566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 53819566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 538261a622f3SMatthew G. Knepley if (id == PETSCFE_CLASSID) { 538361a622f3SMatthew G. Knepley PetscContainer dummy; 538461a622f3SMatthew G. Knepley 53859566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PETSC_COMM_SELF, &dummy)); 53869566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)dummy, "coordinates")); 53879566063dSJacob Faibussowitsch PetscCall(DMSetField(cdm, 0, NULL, (PetscObject)dummy)); 53889566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&dummy)); 53899566063dSJacob Faibussowitsch PetscCall(DMClearDS(cdm)); 539061a622f3SMatthew G. Knepley } 5391509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, NULL)); 539261a622f3SMatthew G. Knepley } 5393c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_localize", "Localize mesh coordinates", "", localize, &localize, NULL)); 5394c3db174cSMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_sparse_localize", "Localize only necessary cells", "DMSetSparseLocalize", sparseLocalize, &sparseLocalize, &flg)); 5395c3db174cSMatthew G. Knepley if (flg) PetscCall(DMSetSparseLocalize(dm, sparseLocalize)); 53965515ebd3SMatthew G. Knepley PetscCall(PetscOptionsInt("-dm_localize_height", "Localize edges and faces in addition to cells", "", height, &height, &flg)); 53975515ebd3SMatthew G. Knepley if (flg) PetscCall(DMPlexSetMaxProjectionHeight(cdm, height)); 5398c3db174cSMatthew G. Knepley if (localize) PetscCall(DMLocalizeCoordinates(dm)); 53999318fe57SMatthew G. Knepley } 540068d4fef7SMatthew G. Knepley /* Handle DMPlex refinement */ 540161a622f3SMatthew G. Knepley remap = PETSC_TRUE; 54029566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 54039566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_refine_remap", "Flag to control coordinate remapping", "DMCreate", remap, &remap, NULL)); 54049566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 54059566063dSJacob Faibussowitsch if (refine) PetscCall(DMPlexSetRefinementUniform(dm, PETSC_TRUE)); 540668d4fef7SMatthew G. Knepley if (refine && isHierarchy) { 5407acdc6f61SToby Isaac DM *dms, coarseDM; 540868d4fef7SMatthew G. Knepley 54099566063dSJacob Faibussowitsch PetscCall(DMGetCoarseDM(dm, &coarseDM)); 54109566063dSJacob Faibussowitsch PetscCall(PetscObjectReference((PetscObject)coarseDM)); 54119566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(refine, &dms)); 54129566063dSJacob Faibussowitsch PetscCall(DMRefineHierarchy(dm, refine, dms)); 541368d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 54149566063dSJacob Faibussowitsch PetscCall(DMPlexSwap_Static(dm, dms[refine - 1])); 541568d4fef7SMatthew G. Knepley if (refine == 1) { 54169566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[0])); 54179566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 541868d4fef7SMatthew G. Knepley } else { 54199566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dm, dms[refine - 2])); 54209566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dm, PETSC_TRUE)); 54219566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[0], dms[refine - 1])); 54229566063dSJacob Faibussowitsch PetscCall(DMPlexSetRegularRefinement(dms[0], PETSC_TRUE)); 542368d4fef7SMatthew G. Knepley } 54249566063dSJacob Faibussowitsch PetscCall(DMSetCoarseDM(dms[refine - 1], coarseDM)); 54259566063dSJacob Faibussowitsch PetscCall(PetscObjectDereference((PetscObject)coarseDM)); 542668d4fef7SMatthew G. Knepley /* Free DMs */ 542768d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 5428dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 54299566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 543068d4fef7SMatthew G. Knepley } 54319566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 543268d4fef7SMatthew G. Knepley } else { 543368d4fef7SMatthew G. Knepley for (r = 0; r < refine; ++r) { 54349318fe57SMatthew G. Knepley DM rdm; 54352192575eSBarry Smith PetscPointFn *coordFunc; 543668d4fef7SMatthew G. Knepley 5437dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54389566063dSJacob Faibussowitsch PetscCall(DMRefine(dm, PetscObjectComm((PetscObject)dm), &rdm)); 543968d4fef7SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 544069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 5441dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54423674be70SMatthew G. Knepley PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc)); 544361a622f3SMatthew G. Knepley if (coordFunc && remap) { 54449566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 5445509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, coordFunc)); 544651a74b61SMatthew G. Knepley } 544768d4fef7SMatthew G. Knepley } 544868d4fef7SMatthew G. Knepley } 54493cf6fe12SMatthew G. Knepley /* Handle DMPlex coarsening */ 54509566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen", "Coarsen the mesh", "DMCreate", coarsen, &coarsen, NULL, 0)); 54519566063dSJacob Faibussowitsch PetscCall(PetscOptionsBoundedInt("-dm_coarsen_hierarchy", "The number of coarsenings", "DMCreate", coarsen, &coarsen, &isHierarchy, 0)); 5452b653a561SMatthew G. Knepley if (coarsen && isHierarchy) { 5453b653a561SMatthew G. Knepley DM *dms; 5454b653a561SMatthew G. Knepley 54559566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(coarsen, &dms)); 54569566063dSJacob Faibussowitsch PetscCall(DMCoarsenHierarchy(dm, coarsen, dms)); 5457b653a561SMatthew G. Knepley /* Free DMs */ 5458b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 5459dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dms[r], PetscOptionsObject)); 54609566063dSJacob Faibussowitsch PetscCall(DMDestroy(&dms[r])); 5461b653a561SMatthew G. Knepley } 54629566063dSJacob Faibussowitsch PetscCall(PetscFree(dms)); 5463b653a561SMatthew G. Knepley } else { 5464b653a561SMatthew G. Knepley for (r = 0; r < coarsen; ++r) { 54659318fe57SMatthew G. Knepley DM cdm; 54662192575eSBarry Smith PetscPointFn *coordFunc; 54673cf6fe12SMatthew G. Knepley 5468509b31aaSMatthew G. Knepley PetscCall(DMPlexGetCoordinateMap(dm, &coordFunc)); 5469dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54709566063dSJacob Faibussowitsch PetscCall(DMCoarsen(dm, PetscObjectComm((PetscObject)dm), &cdm)); 54713cf6fe12SMatthew G. Knepley /* Total hack since we do not pass in a pointer */ 547269d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &cdm)); 5473dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 54749318fe57SMatthew G. Knepley if (coordFunc) { 54759566063dSJacob Faibussowitsch PetscCall(DMPlexRemapGeometry(dm, 0.0, coordFunc)); 5476509b31aaSMatthew G. Knepley PetscCall(DMPlexSetCoordinateMap(dm, coordFunc)); 54779318fe57SMatthew G. Knepley } 54783cf6fe12SMatthew G. Knepley } 5479b653a561SMatthew G. Knepley } 5480be664eb1SMatthew G. Knepley // Handle coordinate remapping 5481be664eb1SMatthew G. Knepley remap = PETSC_FALSE; 5482be664eb1SMatthew G. Knepley PetscCall(PetscOptionsBool("-dm_coord_remap", "Flag to control coordinate remapping", "", remap, &remap, NULL)); 5483be664eb1SMatthew G. Knepley if (remap) { 5484be664eb1SMatthew G. Knepley DMPlexCoordMap map = DM_COORD_MAP_NONE; 54852192575eSBarry Smith PetscPointFn *mapFunc = NULL; 5486be664eb1SMatthew G. Knepley PetscScalar params[16]; 5487f45b553cSPierre Jolivet PetscInt Np = PETSC_STATIC_ARRAY_LENGTH(params), cdim; 5488be664eb1SMatthew G. Knepley MPI_Comm comm; 5489be664eb1SMatthew G. Knepley 5490be664eb1SMatthew G. Knepley PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 5491be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDim(dm, &cdim)); 5492be664eb1SMatthew G. Knepley PetscCall(PetscOptionsScalarArray("-dm_coord_map_params", "Parameters for the coordinate remapping", "", params, &Np, &flg)); 5493be664eb1SMatthew G. Knepley if (!flg) Np = 0; 5494be664eb1SMatthew G. Knepley // TODO Allow user to pass a map function by name 5495be664eb1SMatthew G. Knepley PetscCall(PetscOptionsEnum("-dm_coord_map", "Coordinate mapping for built-in mesh", "", DMPlexCoordMaps, (PetscEnum)map, (PetscEnum *)&map, &flg)); 5496be664eb1SMatthew G. Knepley if (flg) { 5497be664eb1SMatthew G. Knepley switch (map) { 5498be664eb1SMatthew G. Knepley case DM_COORD_MAP_NONE: 5499be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5500be664eb1SMatthew G. Knepley break; 5501be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHEAR: 5502be664eb1SMatthew G. Knepley mapFunc = coordMap_shear; 5503be664eb1SMatthew G. Knepley if (!Np) { 5504be664eb1SMatthew G. Knepley Np = cdim + 1; 5505be664eb1SMatthew G. Knepley params[0] = 0; 5506be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5507be664eb1SMatthew G. Knepley } 5508be664eb1SMatthew 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); 5509be664eb1SMatthew G. Knepley break; 5510be664eb1SMatthew G. Knepley case DM_COORD_MAP_FLARE: 5511be664eb1SMatthew G. Knepley mapFunc = coordMap_flare; 5512be664eb1SMatthew G. Knepley if (!Np) { 5513be664eb1SMatthew G. Knepley Np = cdim + 1; 5514be664eb1SMatthew G. Knepley params[0] = 0; 5515be664eb1SMatthew G. Knepley for (PetscInt d = 1; d <= cdim; ++d) params[d] = 1.0; 5516be664eb1SMatthew G. Knepley } 5517be664eb1SMatthew 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); 5518be664eb1SMatthew G. Knepley break; 5519be664eb1SMatthew G. Knepley case DM_COORD_MAP_ANNULUS: 5520be664eb1SMatthew G. Knepley mapFunc = coordMap_annulus; 5521be664eb1SMatthew G. Knepley if (!Np) { 5522be664eb1SMatthew G. Knepley Np = 2; 5523be664eb1SMatthew G. Knepley params[0] = 1.; 5524be664eb1SMatthew G. Knepley params[1] = 2.; 5525be664eb1SMatthew G. Knepley } 5526be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The annulus coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5527be664eb1SMatthew G. Knepley break; 5528be664eb1SMatthew G. Knepley case DM_COORD_MAP_SHELL: 5529be664eb1SMatthew G. Knepley mapFunc = coordMap_shell; 5530be664eb1SMatthew G. Knepley if (!Np) { 5531be664eb1SMatthew G. Knepley Np = 2; 5532be664eb1SMatthew G. Knepley params[0] = 1.; 5533be664eb1SMatthew G. Knepley params[1] = 2.; 5534be664eb1SMatthew G. Knepley } 5535be664eb1SMatthew G. Knepley PetscCheck(Np == 2, comm, PETSC_ERR_ARG_WRONG, "The spherical shell coordinate map must have 2 parameters, not %" PetscInt_FMT, Np); 5536be664eb1SMatthew G. Knepley break; 5537530e699aSMatthew G. Knepley case DM_COORD_MAP_SINUSOID: 5538530e699aSMatthew G. Knepley mapFunc = coordMap_sinusoid; 5539530e699aSMatthew G. Knepley if (!Np) { 5540530e699aSMatthew G. Knepley Np = 3; 5541530e699aSMatthew G. Knepley params[0] = 1.; 5542530e699aSMatthew G. Knepley params[1] = 1.; 5543530e699aSMatthew G. Knepley params[2] = 1.; 5544530e699aSMatthew G. Knepley } 5545530e699aSMatthew G. Knepley PetscCheck(Np == 3, comm, PETSC_ERR_ARG_WRONG, "The sinusoidal coordinate map must have 3 parameters, not %" PetscInt_FMT, Np); 5546530e699aSMatthew G. Knepley break; 5547be664eb1SMatthew G. Knepley default: 5548be664eb1SMatthew G. Knepley mapFunc = coordMap_identity; 5549be664eb1SMatthew G. Knepley } 5550be664eb1SMatthew G. Knepley } 5551be664eb1SMatthew G. Knepley if (Np) { 5552be664eb1SMatthew G. Knepley DM cdm; 5553be664eb1SMatthew G. Knepley PetscDS cds; 5554be664eb1SMatthew G. Knepley 5555be664eb1SMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5556be664eb1SMatthew G. Knepley PetscCall(DMGetDS(cdm, &cds)); 5557be664eb1SMatthew G. Knepley PetscCall(PetscDSSetConstants(cds, Np, params)); 5558be664eb1SMatthew G. Knepley } 5559be664eb1SMatthew G. Knepley PetscCall(DMPlexRemapGeometry(dm, 0.0, mapFunc)); 5560be664eb1SMatthew G. Knepley } 5561909dfd52SMatthew G. Knepley /* Handle ghost cells */ 55629566063dSJacob Faibussowitsch PetscCall(PetscOptionsBool("-dm_plex_create_fv_ghost_cells", "Flag to create finite volume ghost cells on the boundary", "DMCreate", ghostCells, &ghostCells, NULL)); 5563909dfd52SMatthew G. Knepley if (ghostCells) { 5564909dfd52SMatthew G. Knepley DM gdm; 5565909dfd52SMatthew G. Knepley char lname[PETSC_MAX_PATH_LEN]; 5566909dfd52SMatthew G. Knepley 5567909dfd52SMatthew G. Knepley lname[0] = '\0'; 55689566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-dm_plex_fv_ghost_cells_label", "Label name for ghost cells boundary", "DMCreate", lname, lname, sizeof(lname), &flg)); 55699566063dSJacob Faibussowitsch PetscCall(DMPlexConstructGhostCells(dm, flg ? lname : NULL, NULL, &gdm)); 557069d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &gdm)); 5571909dfd52SMatthew G. Knepley } 55726913077dSMatthew G. Knepley /* Handle 1D order */ 5573adc21957SMatthew G. Knepley if (reorder != DM_REORDER_DEFAULT_FALSE && dim == 1) { 55746913077dSMatthew G. Knepley DM cdm, rdm; 55756913077dSMatthew G. Knepley PetscDS cds; 55766913077dSMatthew G. Knepley PetscObject obj; 55776913077dSMatthew G. Knepley PetscClassId id = PETSC_OBJECT_CLASSID; 55786913077dSMatthew G. Knepley IS perm; 55796bc1bd01Sksagiyam PetscInt Nf; 55806913077dSMatthew G. Knepley PetscBool distributed; 55816913077dSMatthew G. Knepley 55829566063dSJacob Faibussowitsch PetscCall(DMPlexIsDistributed(dm, &distributed)); 55839566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 55849566063dSJacob Faibussowitsch PetscCall(DMGetDS(cdm, &cds)); 55859566063dSJacob Faibussowitsch PetscCall(PetscDSGetNumFields(cds, &Nf)); 55866913077dSMatthew G. Knepley if (Nf) { 55879566063dSJacob Faibussowitsch PetscCall(PetscDSGetDiscretization(cds, 0, &obj)); 55889566063dSJacob Faibussowitsch PetscCall(PetscObjectGetClassId(obj, &id)); 55896913077dSMatthew G. Knepley } 55906bc1bd01Sksagiyam if (!distributed && id != PETSCFE_CLASSID) { 55919566063dSJacob Faibussowitsch PetscCall(DMPlexGetOrdering1D(dm, &perm)); 55929566063dSJacob Faibussowitsch PetscCall(DMPlexPermute(dm, perm, &rdm)); 559369d8a87bSksagiyam PetscCall(DMPlexReplace_Internal(dm, &rdm)); 55949566063dSJacob Faibussowitsch PetscCall(ISDestroy(&perm)); 55956913077dSMatthew G. Knepley } 55966913077dSMatthew G. Knepley } 55973cf6fe12SMatthew G. Knepley /* Handle */ 5598dd4c3f67SMatthew G. Knepley non_refine: 5599dbbe0bcdSBarry Smith PetscCall(DMSetFromOptions_NonRefinement_Plex(dm, PetscOptionsObject)); 560022d6dc08SStefano Zampini char *phases[16]; 560122d6dc08SStefano Zampini PetscInt Nphases = 16; 560222d6dc08SStefano Zampini PetscCall(PetscOptionsStringArray("-dm_plex_option_phases", "Option phase prefixes", "DMSetFromOptions", phases, &Nphases, &flg)); 5603d0609cedSBarry Smith PetscOptionsHeadEnd(); 560422d6dc08SStefano Zampini 560522d6dc08SStefano Zampini // Phases 560622d6dc08SStefano Zampini if (flg) { 5607530e699aSMatthew G. Knepley DM cdm; 5608530e699aSMatthew G. Knepley char *oldPrefix, *oldCoordPrefix; 5609530e699aSMatthew G. Knepley const char *tmp; 561022d6dc08SStefano Zampini 5611530e699aSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5612530e699aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &tmp)); 5613530e699aSMatthew G. Knepley PetscCall(PetscStrallocpy(tmp, &oldPrefix)); 5614530e699aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)cdm, &tmp)); 5615530e699aSMatthew G. Knepley PetscCall(PetscStrallocpy(tmp, &oldCoordPrefix)); 561622d6dc08SStefano Zampini for (PetscInt ph = 0; ph < Nphases; ++ph) { 561722d6dc08SStefano Zampini PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)dm, phases[ph])); 5618530e699aSMatthew G. Knepley PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)cdm, phases[ph])); 561922d6dc08SStefano Zampini PetscCall(PetscInfo(dm, "Options phase %s for DM %s\n", phases[ph], dm->hdr.name)); 562022d6dc08SStefano Zampini PetscCall(DMSetFromOptions(dm)); 562122d6dc08SStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)dm, oldPrefix)); 5622530e699aSMatthew G. Knepley PetscCall(DMGetCoordinateDM(dm, &cdm)); 5623530e699aSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)cdm, oldCoordPrefix)); 562422d6dc08SStefano Zampini PetscCall(PetscFree(phases[ph])); 562522d6dc08SStefano Zampini } 5626530e699aSMatthew G. Knepley PetscCall(PetscFree(oldPrefix)); 5627530e699aSMatthew G. Knepley PetscCall(PetscFree(oldCoordPrefix)); 562822d6dc08SStefano Zampini } 56293ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 56300a6ba040SMatthew G. Knepley } 56310a6ba040SMatthew G. Knepley 5632d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateGlobalVector_Plex(DM dm, Vec *vec) 5633d71ae5a4SJacob Faibussowitsch { 5634552f7358SJed Brown PetscFunctionBegin; 56359566063dSJacob Faibussowitsch PetscCall(DMCreateGlobalVector_Section_Private(dm, vec)); 56369566063dSJacob Faibussowitsch /* PetscCall(VecSetOperation(*vec, VECOP_DUPLICATE, (void(*)(void)) VecDuplicate_MPI_DM)); */ 56379566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex)); 56389566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEWNATIVE, (void (*)(void))VecView_Plex_Native)); 56399566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex)); 56409566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOADNATIVE, (void (*)(void))VecLoad_Plex_Native)); 56413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5642552f7358SJed Brown } 5643552f7358SJed Brown 5644d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMCreateLocalVector_Plex(DM dm, Vec *vec) 5645d71ae5a4SJacob Faibussowitsch { 5646552f7358SJed Brown PetscFunctionBegin; 56479566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector_Section_Private(dm, vec)); 56489566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_VIEW, (void (*)(void))VecView_Plex_Local)); 56499566063dSJacob Faibussowitsch PetscCall(VecSetOperation(*vec, VECOP_LOAD, (void (*)(void))VecLoad_Plex_Local)); 56503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5651552f7358SJed Brown } 5652552f7358SJed Brown 5653d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetDimPoints_Plex(DM dm, PetscInt dim, PetscInt *pStart, PetscInt *pEnd) 5654d71ae5a4SJacob Faibussowitsch { 5655793f3fe5SMatthew G. Knepley PetscInt depth, d; 5656793f3fe5SMatthew G. Knepley 5657793f3fe5SMatthew G. Knepley PetscFunctionBegin; 56589566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepth(dm, &depth)); 5659793f3fe5SMatthew G. Knepley if (depth == 1) { 56609566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &d)); 56619566063dSJacob Faibussowitsch if (dim == 0) PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 56629566063dSJacob Faibussowitsch else if (dim == d) PetscCall(DMPlexGetDepthStratum(dm, 1, pStart, pEnd)); 56639371c9d4SSatish Balay else { 56649371c9d4SSatish Balay *pStart = 0; 56659371c9d4SSatish Balay *pEnd = 0; 56669371c9d4SSatish Balay } 5667793f3fe5SMatthew G. Knepley } else { 56689566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, dim, pStart, pEnd)); 5669793f3fe5SMatthew G. Knepley } 56703ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5671793f3fe5SMatthew G. Knepley } 5672793f3fe5SMatthew G. Knepley 5673d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMGetNeighbors_Plex(DM dm, PetscInt *nranks, const PetscMPIInt *ranks[]) 5674d71ae5a4SJacob Faibussowitsch { 5675502a2867SDave May PetscSF sf; 56766497c311SBarry Smith PetscMPIInt niranks, njranks; 56776497c311SBarry Smith PetscInt n; 56780a19bb7dSprj- const PetscMPIInt *iranks, *jranks; 56790a19bb7dSprj- DM_Plex *data = (DM_Plex *)dm->data; 5680502a2867SDave May 56812f356facSMatthew G. Knepley PetscFunctionBegin; 56829566063dSJacob Faibussowitsch PetscCall(DMGetPointSF(dm, &sf)); 56830a19bb7dSprj- if (!data->neighbors) { 56849566063dSJacob Faibussowitsch PetscCall(PetscSFSetUp(sf)); 56859566063dSJacob Faibussowitsch PetscCall(PetscSFGetRootRanks(sf, &njranks, &jranks, NULL, NULL, NULL)); 56869566063dSJacob Faibussowitsch PetscCall(PetscSFGetLeafRanks(sf, &niranks, &iranks, NULL, NULL)); 56879566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(njranks + niranks + 1, &data->neighbors)); 56889566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + 1, jranks, njranks)); 56899566063dSJacob Faibussowitsch PetscCall(PetscArraycpy(data->neighbors + njranks + 1, iranks, niranks)); 56900a19bb7dSprj- n = njranks + niranks; 56919566063dSJacob Faibussowitsch PetscCall(PetscSortRemoveDupsMPIInt(&n, data->neighbors + 1)); 56920a19bb7dSprj- /* The following cast should never fail: can't have more neighbors than PETSC_MPI_INT_MAX */ 56939566063dSJacob Faibussowitsch PetscCall(PetscMPIIntCast(n, data->neighbors)); 56940a19bb7dSprj- } 56950a19bb7dSprj- if (nranks) *nranks = data->neighbors[0]; 56960a19bb7dSprj- if (ranks) { 56970a19bb7dSprj- if (data->neighbors[0]) *ranks = data->neighbors + 1; 56980a19bb7dSprj- else *ranks = NULL; 56990a19bb7dSprj- } 57003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5701502a2867SDave May } 5702502a2867SDave May 57031eb70e55SToby Isaac PETSC_INTERN PetscErrorCode DMInterpolateSolution_Plex(DM, DM, Mat, Vec, Vec); 57041eb70e55SToby Isaac 5705d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMInitialize_Plex(DM dm) 5706d71ae5a4SJacob Faibussowitsch { 5707552f7358SJed Brown PetscFunctionBegin; 5708552f7358SJed Brown dm->ops->view = DMView_Plex; 57092c40f234SMatthew G. Knepley dm->ops->load = DMLoad_Plex; 5710552f7358SJed Brown dm->ops->setfromoptions = DMSetFromOptions_Plex; 571138221697SMatthew G. Knepley dm->ops->clone = DMClone_Plex; 5712552f7358SJed Brown dm->ops->setup = DMSetUp_Plex; 57131bb6d2a8SBarry Smith dm->ops->createlocalsection = DMCreateLocalSection_Plex; 5714adc21957SMatthew G. Knepley dm->ops->createsectionpermutation = DMCreateSectionPermutation_Plex; 571566ad2231SToby Isaac dm->ops->createdefaultconstraints = DMCreateDefaultConstraints_Plex; 5716552f7358SJed Brown dm->ops->createglobalvector = DMCreateGlobalVector_Plex; 5717552f7358SJed Brown dm->ops->createlocalvector = DMCreateLocalVector_Plex; 5718184d77edSJed Brown dm->ops->getlocaltoglobalmapping = NULL; 57190298fd71SBarry Smith dm->ops->createfieldis = NULL; 5720552f7358SJed Brown dm->ops->createcoordinatedm = DMCreateCoordinateDM_Plex; 572199acd26cSksagiyam dm->ops->createcellcoordinatedm = DMCreateCellCoordinateDM_Plex; 5722f19dbd58SToby Isaac dm->ops->createcoordinatefield = DMCreateCoordinateField_Plex; 57230a6ba040SMatthew G. Knepley dm->ops->getcoloring = NULL; 5724552f7358SJed Brown dm->ops->creatematrix = DMCreateMatrix_Plex; 5725bceba477SMatthew G. Knepley dm->ops->createinterpolation = DMCreateInterpolation_Plex; 5726bd041c0cSMatthew G. Knepley dm->ops->createmassmatrix = DMCreateMassMatrix_Plex; 5727b4937a87SMatthew G. Knepley dm->ops->createmassmatrixlumped = DMCreateMassMatrixLumped_Plex; 57285a84ad33SLisandro Dalcin dm->ops->createinjection = DMCreateInjection_Plex; 5729552f7358SJed Brown dm->ops->refine = DMRefine_Plex; 57300a6ba040SMatthew G. Knepley dm->ops->coarsen = DMCoarsen_Plex; 57310a6ba040SMatthew G. Knepley dm->ops->refinehierarchy = DMRefineHierarchy_Plex; 5732b653a561SMatthew G. Knepley dm->ops->coarsenhierarchy = DMCoarsenHierarchy_Plex; 5733d410b0cfSMatthew G. Knepley dm->ops->extrude = DMExtrude_Plex; 57340298fd71SBarry Smith dm->ops->globaltolocalbegin = NULL; 57350298fd71SBarry Smith dm->ops->globaltolocalend = NULL; 57360298fd71SBarry Smith dm->ops->localtoglobalbegin = NULL; 57370298fd71SBarry Smith dm->ops->localtoglobalend = NULL; 5738552f7358SJed Brown dm->ops->destroy = DMDestroy_Plex; 5739552f7358SJed Brown dm->ops->createsubdm = DMCreateSubDM_Plex; 57402adcc780SMatthew G. Knepley dm->ops->createsuperdm = DMCreateSuperDM_Plex; 5741793f3fe5SMatthew G. Knepley dm->ops->getdimpoints = DMGetDimPoints_Plex; 5742552f7358SJed Brown dm->ops->locatepoints = DMLocatePoints_Plex; 57430709b2feSToby Isaac dm->ops->projectfunctionlocal = DMProjectFunctionLocal_Plex; 57440709b2feSToby Isaac dm->ops->projectfunctionlabellocal = DMProjectFunctionLabelLocal_Plex; 5745bfc4295aSToby Isaac dm->ops->projectfieldlocal = DMProjectFieldLocal_Plex; 57468c6c5593SMatthew G. Knepley dm->ops->projectfieldlabellocal = DMProjectFieldLabelLocal_Plex; 5747ece3a9fcSMatthew G. Knepley dm->ops->projectbdfieldlabellocal = DMProjectBdFieldLabelLocal_Plex; 57480709b2feSToby Isaac dm->ops->computel2diff = DMComputeL2Diff_Plex; 5749b698f381SToby Isaac dm->ops->computel2gradientdiff = DMComputeL2GradientDiff_Plex; 57502a16baeaSToby Isaac dm->ops->computel2fielddiff = DMComputeL2FieldDiff_Plex; 575128d58a37SPierre Jolivet dm->ops->getneighbors = DMGetNeighbors_Plex; 57526c6a6b79SMatthew G. Knepley dm->ops->getlocalboundingbox = DMGetLocalBoundingBox_Coordinates; 5753907a3e9cSStefano Zampini dm->ops->createdomaindecomposition = DMCreateDomainDecomposition_Plex; 5754907a3e9cSStefano Zampini dm->ops->createddscatters = DMCreateDomainDecompositionScatters_Plex; 57559566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBoundaryValues_C", DMPlexInsertBoundaryValues_Plex)); 57566c51210dSStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertTimeDerivativeBoundaryValues_C", DMPlexInsertTimeDerivativeBoundaryValues_Plex)); 575701468941SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexInsertBounds_C", DMPlexInsertBounds_Plex)); 57589566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMSetUpGLVisViewer_C", DMSetUpGLVisViewer_Plex)); 57599566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMCreateNeumannOverlap_C", DMCreateNeumannOverlap_Plex)); 57609566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeGetDefault_C", DMPlexDistributeGetDefault_Plex)); 57619566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexDistributeSetDefault_C", DMPlexDistributeSetDefault_Plex)); 57626bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderGetDefault_C", DMPlexReorderGetDefault_Plex)); 57636bc1bd01Sksagiyam PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexReorderSetDefault_C", DMPlexReorderSetDefault_Plex)); 5764adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetDefault_C", DMReorderSectionGetDefault_Plex)); 5765adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetDefault_C", DMReorderSectionSetDefault_Plex)); 5766adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionGetType_C", DMReorderSectionGetType_Plex)); 5767adc21957SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMReorderSectionSetType_C", DMReorderSectionSetType_Plex)); 57689566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMInterpolateSolution_C", DMInterpolateSolution_Plex)); 5769c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetOverlap_C", DMPlexGetOverlap_Plex)); 5770c506a872SMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetOverlap_C", DMPlexSetOverlap_Plex)); 5771d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexGetUseCeed_C", DMPlexGetUseCeed_Plex)); 5772d2b2dc1eSMatthew G. Knepley PetscCall(PetscObjectComposeFunction((PetscObject)dm, "DMPlexSetUseCeed_C", DMPlexSetUseCeed_Plex)); 57733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5774552f7358SJed Brown } 5775552f7358SJed Brown 5776d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMClone_Plex(DM dm, DM *newdm) 5777d71ae5a4SJacob Faibussowitsch { 577863a16f15SMatthew G. Knepley DM_Plex *mesh = (DM_Plex *)dm->data; 57791fca310dSJames Wright const PetscSF *face_sfs; 57801fca310dSJames Wright PetscInt num_face_sfs; 578163a16f15SMatthew G. Knepley 578263a16f15SMatthew G. Knepley PetscFunctionBegin; 578363a16f15SMatthew G. Knepley mesh->refct++; 578463a16f15SMatthew G. Knepley (*newdm)->data = mesh; 57851fca310dSJames Wright PetscCall(DMPlexGetIsoperiodicFaceSF(dm, &num_face_sfs, &face_sfs)); 57861fca310dSJames Wright PetscCall(DMPlexSetIsoperiodicFaceSF(*newdm, num_face_sfs, (PetscSF *)face_sfs)); 57879566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)*newdm, DMPLEX)); 57889566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(*newdm)); 57893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 579063a16f15SMatthew G. Knepley } 579163a16f15SMatthew G. Knepley 57928818961aSMatthew G Knepley /*MC 57930b4b7b1cSBarry Smith DMPLEX = "plex" - A `DM` object that encapsulates an unstructured mesh (or grid), or CW Complex {cite}`cwcomplex`, 57940b4b7b1cSBarry Smith which can be expressed using a Hasse Diagram {cite}`hassediagram`. 579520f4b53cSBarry Smith In the local representation, `Vec`s contain all unknowns in the interior and shared boundary. This is 57960b4b7b1cSBarry Smith specified by a `PetscSection` object. Ownership in the global representation is determined by 5797a1cb98faSBarry Smith ownership of the underlying `DMPLEX` points. This is specified by another `PetscSection` object. 57988818961aSMatthew G Knepley 5799e5893cccSMatthew G. Knepley Options Database Keys: 5800250712c9SMatthew G. Knepley + -dm_refine_pre - Refine mesh before distribution 5801250712c9SMatthew G. Knepley + -dm_refine_uniform_pre - Choose uniform or generator-based refinement 5802250712c9SMatthew G. Knepley + -dm_refine_volume_limit_pre - Cell volume limit after pre-refinement using generator 5803250712c9SMatthew G. Knepley . -dm_distribute - Distribute mesh across processes 5804250712c9SMatthew G. Knepley . -dm_distribute_overlap - Number of cells to overlap for distribution 5805250712c9SMatthew G. Knepley . -dm_refine - Refine mesh after distribution 5806c3db174cSMatthew G. Knepley . -dm_localize <bool> - Whether to localize coordinates for periodic meshes 5807c3db174cSMatthew G. Knepley . -dm_sparse_localize <bool> - Whether to only localize cells on the periodic boundary 5808250712c9SMatthew G. Knepley . -dm_plex_hash_location - Use grid hashing for point location 5809ddce0771SMatthew G. Knepley . -dm_plex_hash_box_faces <n,m,p> - The number of divisions in each direction of the grid hash 5810f12cf164SMatthew G. Knepley . -dm_plex_partition_balance - Attempt to evenly divide points on partition boundary between processes 5811f12cf164SMatthew G. Knepley . -dm_plex_remesh_bd - Allow changes to the boundary on remeshing 5812d5b43468SJose E. Roman . -dm_plex_max_projection_height - Maximum mesh point height used to project locally 5813f12cf164SMatthew G. Knepley . -dm_plex_regular_refinement - Use special nested projection algorithm for regular refinement 5814d02c7345SMatthew G. Knepley . -dm_plex_reorder_section - Use specialized blocking if available 5815aaa8cc7dSPierre Jolivet . -dm_plex_check_all - Perform all checks below 5816f12cf164SMatthew G. Knepley . -dm_plex_check_symmetry - Check that the adjacency information in the mesh is symmetric 5817f12cf164SMatthew G. Knepley . -dm_plex_check_skeleton <celltype> - Check that each cell has the correct number of vertices 5818f12cf164SMatthew 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 5819f12cf164SMatthew G. Knepley . -dm_plex_check_geometry - Check that cells have positive volume 5820f12cf164SMatthew G. Knepley . -dm_view :mesh.tex:ascii_latex - View the mesh in LaTeX/TikZ 5821e5893cccSMatthew G. Knepley . -dm_plex_view_scale <num> - Scale the TikZ 58225962854dSMatthew G. Knepley . -dm_plex_print_fem <num> - View FEM assembly information, such as element vectors and matrices 58235962854dSMatthew G. Knepley - -dm_plex_print_fvm <num> - View FVM assembly information, such as flux updates 5824e5893cccSMatthew G. Knepley 58258818961aSMatthew G Knepley Level: intermediate 58268818961aSMatthew G Knepley 58271cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMPlexCreate()`, `DMCreate()`, `DMSetType()`, `PetscSection` 58288818961aSMatthew G Knepley M*/ 58298818961aSMatthew G Knepley 5830d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode DMCreate_Plex(DM dm) 5831d71ae5a4SJacob Faibussowitsch { 5832552f7358SJed Brown DM_Plex *mesh; 5833412e9a14SMatthew G. Knepley PetscInt unit; 5834552f7358SJed Brown 5835552f7358SJed Brown PetscFunctionBegin; 5836f39ec787SMatthew G. Knepley PetscCall(PetscCitationsRegister(PlexCitation, &Plexcite)); 5837552f7358SJed Brown PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 58384dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&mesh)); 5839adc21957SMatthew G. Knepley dm->reorderSection = DM_REORDER_DEFAULT_NOTSET; 5840552f7358SJed Brown dm->data = mesh; 5841552f7358SJed Brown 5842552f7358SJed Brown mesh->refct = 1; 58439566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->coneSection)); 58449566063dSJacob Faibussowitsch PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), &mesh->supportSection)); 5845552f7358SJed Brown mesh->refinementUniform = PETSC_TRUE; 5846552f7358SJed Brown mesh->refinementLimit = -1.0; 5847e600fa54SMatthew G. Knepley mesh->distDefault = PETSC_TRUE; 5848adc21957SMatthew G. Knepley mesh->reorderDefault = DM_REORDER_DEFAULT_NOTSET; 58491d1f2f2aSksagiyam mesh->distributionName = NULL; 58507d0f5628SVaclav Hapla mesh->interpolated = DMPLEX_INTERPOLATED_INVALID; 58517d0f5628SVaclav Hapla mesh->interpolatedCollective = DMPLEX_INTERPOLATED_INVALID; 58525e2c5519SMatthew G. Knepley mesh->interpolatePreferTensor = PETSC_TRUE; 5853552f7358SJed Brown 58549566063dSJacob Faibussowitsch PetscCall(PetscPartitionerCreate(PetscObjectComm((PetscObject)dm), &mesh->partitioner)); 58552e62ab5aSMatthew G. Knepley mesh->remeshBd = PETSC_FALSE; 5856d9deefdfSMatthew G. Knepley 58578865f1eaSKarl Rupp for (unit = 0; unit < NUM_PETSC_UNITS; ++unit) mesh->scale[unit] = 1.0; 5858552f7358SJed Brown 5859df0420ecSMatthew G. Knepley mesh->depthState = -1; 5860ba2698f1SMatthew G. Knepley mesh->celltypeState = -1; 58616113b454SMatthew G. Knepley mesh->printTol = 1.0e-10; 5862c29ce622SStefano Zampini mesh->nonempty_comm = MPI_COMM_SELF; 5863552f7358SJed Brown 58649566063dSJacob Faibussowitsch PetscCall(DMInitialize_Plex(dm)); 58653ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5866552f7358SJed Brown } 5867552f7358SJed Brown 5868552f7358SJed Brown /*@ 5869a1cb98faSBarry Smith DMPlexCreate - Creates a `DMPLEX` object, which encapsulates an unstructured mesh, or CW complex, which can be expressed using a Hasse Diagram. 5870552f7358SJed Brown 5871d083f849SBarry Smith Collective 5872552f7358SJed Brown 5873552f7358SJed Brown Input Parameter: 5874a1cb98faSBarry Smith . comm - The communicator for the `DMPLEX` object 5875552f7358SJed Brown 5876552f7358SJed Brown Output Parameter: 5877a1cb98faSBarry Smith . mesh - The `DMPLEX` object 5878552f7358SJed Brown 5879552f7358SJed Brown Level: beginner 5880552f7358SJed Brown 588142747ad1SJacob Faibussowitsch .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMType`, `DMCreate()`, `DMSetType()` 5882552f7358SJed Brown @*/ 5883d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreate(MPI_Comm comm, DM *mesh) 5884d71ae5a4SJacob Faibussowitsch { 5885552f7358SJed Brown PetscFunctionBegin; 58864f572ea9SToby Isaac PetscAssertPointer(mesh, 2); 58879566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, mesh)); 58889566063dSJacob Faibussowitsch PetscCall(DMSetType(*mesh, DMPLEX)); 58893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5890552f7358SJed Brown } 5891552f7358SJed Brown 5892b09969d6SVaclav Hapla /*@C 5893b0fe842aSMatthew 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 5894a1cb98faSBarry Smith 589520f4b53cSBarry Smith Collective; No Fortran Support 5896b09969d6SVaclav Hapla 5897b09969d6SVaclav Hapla Input Parameters: 5898a1cb98faSBarry Smith + dm - The `DM` 5899b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 5900a1cb98faSBarry Smith . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 5901a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DETERMINE` 5902b09969d6SVaclav Hapla . numCorners - The number of vertices for each cell 59035e488331SVaclav Hapla - cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 5904b09969d6SVaclav Hapla 5905be8c289dSNicolas Barral Output Parameters: 5906a1cb98faSBarry Smith + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 5907be8c289dSNicolas Barral - verticesAdjSaved - (Optional) vertex adjacency array 5908b09969d6SVaclav Hapla 5909b09969d6SVaclav Hapla Level: advanced 5910b09969d6SVaclav Hapla 5911a1cb98faSBarry Smith Notes: 5912a1cb98faSBarry Smith Two triangles sharing a face 5913a1cb98faSBarry Smith .vb 5914a1cb98faSBarry Smith 5915a1cb98faSBarry Smith 2 5916a1cb98faSBarry Smith / | \ 5917a1cb98faSBarry Smith / | \ 5918a1cb98faSBarry Smith / | \ 5919a1cb98faSBarry Smith 0 0 | 1 3 5920a1cb98faSBarry Smith \ | / 5921a1cb98faSBarry Smith \ | / 5922a1cb98faSBarry Smith \ | / 5923a1cb98faSBarry Smith 1 5924a1cb98faSBarry Smith .ve 5925a1cb98faSBarry Smith would have input 5926a1cb98faSBarry Smith .vb 5927a1cb98faSBarry Smith numCells = 2, numVertices = 4 5928a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 5929a1cb98faSBarry Smith .ve 5930a1cb98faSBarry Smith which would result in the `DMPLEX` 5931a1cb98faSBarry Smith .vb 5932a1cb98faSBarry Smith 5933a1cb98faSBarry Smith 4 5934a1cb98faSBarry Smith / | \ 5935a1cb98faSBarry Smith / | \ 5936a1cb98faSBarry Smith / | \ 5937a1cb98faSBarry Smith 2 0 | 1 5 5938a1cb98faSBarry Smith \ | / 5939a1cb98faSBarry Smith \ | / 5940a1cb98faSBarry Smith \ | / 5941a1cb98faSBarry Smith 3 5942a1cb98faSBarry Smith .ve 5943a1cb98faSBarry Smith 5944a1cb98faSBarry Smith Vertices are implicitly numbered consecutively 0,...,NVertices. 5945a1cb98faSBarry Smith Each rank owns a chunk of numVertices consecutive vertices. 5946a1cb98faSBarry Smith If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 5947a1cb98faSBarry Smith If NVertices is `PETSC_DETERMINE` and numVertices is PETSC_DECIDE, NVertices is computed by PETSc as the maximum vertex index in cells + 1. 5948a1cb98faSBarry Smith If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 5949a1cb98faSBarry Smith 5950a1cb98faSBarry Smith The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 5951a1cb98faSBarry Smith 59521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 5953a1cb98faSBarry Smith `PetscSF` 5954b09969d6SVaclav Hapla @*/ 5955ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellListParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscInt numCorners, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[]) 5956d71ae5a4SJacob Faibussowitsch { 59572464107aSksagiyam PetscSF sfPoint; 59582464107aSksagiyam PetscLayout layout; 595982fb893eSVaclav Hapla PetscInt numVerticesAdj, *verticesAdj, *cones, c, p; 5960a47d0d45SMatthew G. Knepley 5961a47d0d45SMatthew G. Knepley PetscFunctionBegin; 596225b6865aSVaclav Hapla PetscValidLogicalCollectiveInt(dm, NVertices, 4); 59639566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 596425b6865aSVaclav Hapla /* Get/check global number of vertices */ 596525b6865aSVaclav Hapla { 596625b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 596725b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 596825b6865aSVaclav Hapla 596925b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 59701690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 59719371c9d4SSatish Balay for (i = 0; i < len; i++) 59729371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 597325b6865aSVaclav Hapla ++NVerticesInCells; 5974462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 597525b6865aSVaclav Hapla 597625b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 59779371c9d4SSatish Balay else 59789371c9d4SSatish 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); 597925b6865aSVaclav Hapla } 59809079aca8SVaclav Hapla /* Count locally unique vertices */ 59819079aca8SVaclav Hapla { 59829079aca8SVaclav Hapla PetscHSetI vhash; 59839079aca8SVaclav Hapla PetscInt off = 0; 59849079aca8SVaclav Hapla 59859566063dSJacob Faibussowitsch PetscCall(PetscHSetICreate(&vhash)); 5986a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 598748a46eb9SPierre Jolivet for (p = 0; p < numCorners; ++p) PetscCall(PetscHSetIAdd(vhash, cells[c * numCorners + p])); 5988a47d0d45SMatthew G. Knepley } 59899566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 59909566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 5991ad540459SPierre Jolivet else verticesAdj = *verticesAdjSaved; 59929566063dSJacob Faibussowitsch PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 59939566063dSJacob Faibussowitsch PetscCall(PetscHSetIDestroy(&vhash)); 599463a3b9bcSJacob Faibussowitsch PetscCheck(off == numVerticesAdj, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid number of local vertices %" PetscInt_FMT " should be %" PetscInt_FMT, off, numVerticesAdj); 5995a47d0d45SMatthew G. Knepley } 59969566063dSJacob Faibussowitsch PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 5997a47d0d45SMatthew G. Knepley /* Create cones */ 59989566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 59999566063dSJacob Faibussowitsch for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 60009566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 60019566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 6002a47d0d45SMatthew G. Knepley for (c = 0; c < numCells; ++c) { 6003a47d0d45SMatthew G. Knepley for (p = 0; p < numCorners; ++p) { 6004a47d0d45SMatthew G. Knepley const PetscInt gv = cells[c * numCorners + p]; 6005a47d0d45SMatthew G. Knepley PetscInt lv; 6006a47d0d45SMatthew G. Knepley 60079079aca8SVaclav Hapla /* Positions within verticesAdj form 0-based local vertex numbering; 60089079aca8SVaclav Hapla we need to shift it by numCells to get correct DAG points (cells go first) */ 60099566063dSJacob Faibussowitsch PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 601063a3b9bcSJacob Faibussowitsch PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 6011961cfab0SVaclav Hapla cones[c * numCorners + p] = lv + numCells; 6012a47d0d45SMatthew G. Knepley } 6013a47d0d45SMatthew G. Knepley } 60142464107aSksagiyam /* Build point sf */ 60159566063dSJacob Faibussowitsch PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 60169566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetSize(layout, NVertices)); 60179566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 60189566063dSJacob Faibussowitsch PetscCall(PetscLayoutSetBlockSize(layout, 1)); 60199566063dSJacob Faibussowitsch PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 60209566063dSJacob Faibussowitsch PetscCall(PetscLayoutDestroy(&layout)); 60219566063dSJacob Faibussowitsch if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 60229566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 60232464107aSksagiyam if (dm->sf) { 60242464107aSksagiyam const char *prefix; 60252464107aSksagiyam 60269566063dSJacob Faibussowitsch PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 60279566063dSJacob Faibussowitsch PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 60282464107aSksagiyam } 60299566063dSJacob Faibussowitsch PetscCall(DMSetPointSF(dm, sfPoint)); 60309566063dSJacob Faibussowitsch PetscCall(PetscSFDestroy(&sfPoint)); 6031f4f49eeaSPierre Jolivet if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 6032a47d0d45SMatthew G. Knepley /* Fill in the rest of the topology structure */ 60339566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 60349566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 60359566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 60363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6037a47d0d45SMatthew G. Knepley } 6038a47d0d45SMatthew G. Knepley 6039b0fe842aSMatthew G. Knepley /*@C 6040b0fe842aSMatthew G. Knepley DMPlexBuildFromCellSectionParallel - Build distributed `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) allowing multiple celltypes 6041b0fe842aSMatthew G. Knepley 6042b0fe842aSMatthew G. Knepley Collective; No Fortran Support 6043b0fe842aSMatthew G. Knepley 6044b0fe842aSMatthew G. Knepley Input Parameters: 6045b0fe842aSMatthew G. Knepley + dm - The `DM` 6046b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 6047b0fe842aSMatthew G. Knepley . numVertices - The number of vertices to be owned by this process, or `PETSC_DECIDE` 6048b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DETERMINE` 6049b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 6050b0fe842aSMatthew G. Knepley - cells - An array of the global vertex numbers for each cell 6051b0fe842aSMatthew G. Knepley 6052b0fe842aSMatthew G. Knepley Output Parameters: 6053b0fe842aSMatthew G. Knepley + vertexSF - (Optional) `PetscSF` describing complete vertex ownership 6054b0fe842aSMatthew G. Knepley - verticesAdjSaved - (Optional) vertex adjacency array 6055b0fe842aSMatthew G. Knepley 6056b0fe842aSMatthew G. Knepley Level: advanced 6057b0fe842aSMatthew G. Knepley 6058b0fe842aSMatthew G. Knepley Notes: 6059b0fe842aSMatthew G. Knepley A triangle and quadrilateral sharing a face 6060b0fe842aSMatthew G. Knepley .vb 6061b0fe842aSMatthew G. Knepley 2----------3 6062b0fe842aSMatthew G. Knepley / | | 6063b0fe842aSMatthew G. Knepley / | | 6064b0fe842aSMatthew G. Knepley / | | 6065b0fe842aSMatthew G. Knepley 0 0 | 1 | 6066b0fe842aSMatthew G. Knepley \ | | 6067b0fe842aSMatthew G. Knepley \ | | 6068b0fe842aSMatthew G. Knepley \ | | 6069b0fe842aSMatthew G. Knepley 1----------4 6070b0fe842aSMatthew G. Knepley .ve 6071b0fe842aSMatthew G. Knepley would have input 6072b0fe842aSMatthew G. Knepley .vb 6073b0fe842aSMatthew G. Knepley numCells = 2, numVertices = 5 6074b0fe842aSMatthew G. Knepley cells = [0 1 2 1 4 3 2] 6075b0fe842aSMatthew G. Knepley .ve 6076b0fe842aSMatthew G. Knepley which would result in the `DMPLEX` 6077b0fe842aSMatthew G. Knepley .vb 6078b0fe842aSMatthew G. Knepley 4----------5 6079b0fe842aSMatthew G. Knepley / | | 6080b0fe842aSMatthew G. Knepley / | | 6081b0fe842aSMatthew G. Knepley / | | 6082b0fe842aSMatthew G. Knepley 2 0 | 1 | 6083b0fe842aSMatthew G. Knepley \ | | 6084b0fe842aSMatthew G. Knepley \ | | 6085b0fe842aSMatthew G. Knepley \ | | 6086b0fe842aSMatthew G. Knepley 3----------6 6087b0fe842aSMatthew G. Knepley .ve 6088b0fe842aSMatthew G. Knepley 6089b0fe842aSMatthew G. Knepley Vertices are implicitly numbered consecutively 0,...,NVertices. 6090b0fe842aSMatthew G. Knepley Each rank owns a chunk of numVertices consecutive vertices. 6091b0fe842aSMatthew G. Knepley If numVertices is `PETSC_DECIDE`, PETSc will distribute them as evenly as possible using PetscLayout. 6092b0fe842aSMatthew 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. 6093b0fe842aSMatthew G. Knepley If only NVertices is `PETSC_DETERMINE`, it is computed as the sum of numVertices over all ranks. 6094b0fe842aSMatthew G. Knepley 6095b0fe842aSMatthew G. Knepley The cell distribution is arbitrary non-overlapping, independent of the vertex distribution. 6096b0fe842aSMatthew G. Knepley 6097b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexCreateFromCellSectionParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, 6098b0fe842aSMatthew G. Knepley `PetscSF` 6099b0fe842aSMatthew G. Knepley @*/ 6100ce78bad3SBarry Smith PetscErrorCode DMPlexBuildFromCellSectionParallel(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt NVertices, PetscSection cellSection, const PetscInt cells[], PeOp PetscSF *vertexSF, PeOp PetscInt *verticesAdjSaved[]) 6101b0fe842aSMatthew G. Knepley { 6102b0fe842aSMatthew G. Knepley PetscSF sfPoint; 6103b0fe842aSMatthew G. Knepley PetscLayout layout; 6104b0fe842aSMatthew G. Knepley PetscInt numVerticesAdj, *verticesAdj, *cones, cStart, cEnd, len; 6105b0fe842aSMatthew G. Knepley 6106b0fe842aSMatthew G. Knepley PetscFunctionBegin; 6107b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(dm, NVertices, 4); 6108b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 6109b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetChart(cellSection, &cStart, &cEnd)); 6110b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetStorageSize(cellSection, &len)); 6111b0fe842aSMatthew 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); 6112b0fe842aSMatthew G. Knepley /* Get/check global number of vertices */ 6113b0fe842aSMatthew G. Knepley { 6114b0fe842aSMatthew G. Knepley PetscInt NVerticesInCells; 6115b0fe842aSMatthew G. Knepley 6116b0fe842aSMatthew G. Knepley /* NVerticesInCells = max(cells) + 1 */ 6117b0fe842aSMatthew G. Knepley NVerticesInCells = PETSC_MIN_INT; 6118b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) 6119b0fe842aSMatthew G. Knepley if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 6120b0fe842aSMatthew G. Knepley ++NVerticesInCells; 6121b0fe842aSMatthew G. Knepley PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &NVerticesInCells, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm))); 6122b0fe842aSMatthew G. Knepley 6123b0fe842aSMatthew G. Knepley if (numVertices == PETSC_DECIDE && NVertices == PETSC_DECIDE) NVertices = NVerticesInCells; 6124b0fe842aSMatthew G. Knepley else 6125b0fe842aSMatthew 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); 6126b0fe842aSMatthew G. Knepley } 6127b0fe842aSMatthew G. Knepley /* Count locally unique vertices */ 6128b0fe842aSMatthew G. Knepley { 6129b0fe842aSMatthew G. Knepley PetscHSetI vhash; 6130b0fe842aSMatthew G. Knepley PetscInt off = 0; 6131b0fe842aSMatthew G. Knepley 6132b0fe842aSMatthew G. Knepley PetscCall(PetscHSetICreate(&vhash)); 6133b0fe842aSMatthew G. Knepley for (PetscInt i = 0; i < len; i++) PetscCall(PetscHSetIAdd(vhash, cells[i])); 6134b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetSize(vhash, &numVerticesAdj)); 6135b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscMalloc1(numVerticesAdj, &verticesAdj)); 6136b0fe842aSMatthew G. Knepley else verticesAdj = *verticesAdjSaved; 6137b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIGetElems(vhash, &off, verticesAdj)); 6138b0fe842aSMatthew G. Knepley PetscCall(PetscHSetIDestroy(&vhash)); 6139b0fe842aSMatthew 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); 6140b0fe842aSMatthew G. Knepley } 6141b0fe842aSMatthew G. Knepley PetscCall(PetscSortInt(numVerticesAdj, verticesAdj)); 6142b0fe842aSMatthew G. Knepley /* Create cones */ 6143b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetChart(dm, 0, numCells + numVerticesAdj)); 6144b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 6145b0fe842aSMatthew G. Knepley PetscInt dof; 6146b0fe842aSMatthew G. Knepley 6147b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 6148b0fe842aSMatthew G. Knepley PetscCall(DMPlexSetConeSize(dm, c, dof)); 6149b0fe842aSMatthew G. Knepley } 6150b0fe842aSMatthew G. Knepley PetscCall(DMSetUp(dm)); 6151b0fe842aSMatthew G. Knepley PetscCall(DMPlexGetCones(dm, &cones)); 6152b0fe842aSMatthew G. Knepley for (PetscInt c = 0; c < numCells; ++c) { 6153b0fe842aSMatthew G. Knepley PetscInt dof, off; 6154b0fe842aSMatthew G. Knepley 6155b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetDof(cellSection, c, &dof)); 6156b0fe842aSMatthew G. Knepley PetscCall(PetscSectionGetOffset(cellSection, c, &off)); 6157b0fe842aSMatthew G. Knepley for (PetscInt p = off; p < off + dof; ++p) { 6158b0fe842aSMatthew G. Knepley const PetscInt gv = cells[p]; 6159b0fe842aSMatthew G. Knepley PetscInt lv; 6160b0fe842aSMatthew G. Knepley 6161b0fe842aSMatthew G. Knepley /* Positions within verticesAdj form 0-based local vertex numbering; 6162b0fe842aSMatthew G. Knepley we need to shift it by numCells to get correct DAG points (cells go first) */ 6163b0fe842aSMatthew G. Knepley PetscCall(PetscFindInt(gv, numVerticesAdj, verticesAdj, &lv)); 6164b0fe842aSMatthew G. Knepley PetscCheck(lv >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not find global vertex %" PetscInt_FMT " in local connectivity", gv); 6165b0fe842aSMatthew G. Knepley cones[p] = lv + numCells; 6166b0fe842aSMatthew G. Knepley } 6167b0fe842aSMatthew G. Knepley } 6168b0fe842aSMatthew G. Knepley /* Build point sf */ 6169b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &layout)); 6170b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetSize(layout, NVertices)); 6171b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetLocalSize(layout, numVertices)); 6172b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutSetBlockSize(layout, 1)); 6173b0fe842aSMatthew G. Knepley PetscCall(PetscSFCreateByMatchingIndices(layout, numVerticesAdj, verticesAdj, NULL, numCells, numVerticesAdj, verticesAdj, NULL, numCells, vertexSF, &sfPoint)); 6174b0fe842aSMatthew G. Knepley PetscCall(PetscLayoutDestroy(&layout)); 6175b0fe842aSMatthew G. Knepley if (!verticesAdjSaved) PetscCall(PetscFree(verticesAdj)); 6176b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetName((PetscObject)sfPoint, "point SF")); 6177b0fe842aSMatthew G. Knepley if (dm->sf) { 6178b0fe842aSMatthew G. Knepley const char *prefix; 6179b0fe842aSMatthew G. Knepley 6180b0fe842aSMatthew G. Knepley PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm->sf, &prefix)); 6181b0fe842aSMatthew G. Knepley PetscCall(PetscObjectSetOptionsPrefix((PetscObject)sfPoint, prefix)); 6182b0fe842aSMatthew G. Knepley } 6183b0fe842aSMatthew G. Knepley PetscCall(DMSetPointSF(dm, sfPoint)); 6184b0fe842aSMatthew G. Knepley PetscCall(PetscSFDestroy(&sfPoint)); 6185b0fe842aSMatthew G. Knepley if (vertexSF) PetscCall(PetscObjectSetName((PetscObject)*vertexSF, "Vertex Ownership SF")); 6186b0fe842aSMatthew G. Knepley /* Fill in the rest of the topology structure */ 6187b0fe842aSMatthew G. Knepley PetscCall(DMPlexSymmetrize(dm)); 6188b0fe842aSMatthew G. Knepley PetscCall(DMPlexStratify(dm)); 6189b0fe842aSMatthew G. Knepley PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 6190b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 6191b0fe842aSMatthew G. Knepley } 6192b0fe842aSMatthew G. Knepley 6193cc4c1da9SBarry Smith /*@ 6194a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellListParallel - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 6195a1cb98faSBarry Smith 619620f4b53cSBarry Smith Collective; No Fortran Support 6197b09969d6SVaclav Hapla 6198b09969d6SVaclav Hapla Input Parameters: 6199a1cb98faSBarry Smith + dm - The `DM` 6200b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6201a1cb98faSBarry Smith . sfVert - `PetscSF` describing complete vertex ownership 6202b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6203b09969d6SVaclav Hapla 6204b09969d6SVaclav Hapla Level: advanced 6205b09969d6SVaclav Hapla 62061cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellListParallel()` 6207b09969d6SVaclav Hapla @*/ 6208d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellListParallel(DM dm, PetscInt spaceDim, PetscSF sfVert, const PetscReal vertexCoords[]) 6209d71ae5a4SJacob Faibussowitsch { 6210a47d0d45SMatthew G. Knepley PetscSection coordSection; 6211a47d0d45SMatthew G. Knepley Vec coordinates; 6212a47d0d45SMatthew G. Knepley PetscScalar *coords; 62131edcf0b2SVaclav Hapla PetscInt numVertices, numVerticesAdj, coordSize, v, vStart, vEnd; 6214835f2295SStefano Zampini PetscMPIInt spaceDimi; 6215a47d0d45SMatthew G. Knepley 6216a47d0d45SMatthew G. Knepley PetscFunctionBegin; 62179566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 62189566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 62191dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 62209566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 62219566063dSJacob Faibussowitsch PetscCall(PetscSFGetGraph(sfVert, &numVertices, &numVerticesAdj, NULL, NULL)); 62221dca8a05SBarry 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); 62239566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 62249566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 62259566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 62269566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 62271edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 62289566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 62299566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 6230a47d0d45SMatthew G. Knepley } 62319566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 62329566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 62339566063dSJacob Faibussowitsch PetscCall(VecCreate(PetscObjectComm((PetscObject)dm), &coordinates)); 62349566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 62359566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 62369566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 62379566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 62389566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6239a47d0d45SMatthew G. Knepley { 6240a47d0d45SMatthew G. Knepley MPI_Datatype coordtype; 6241a47d0d45SMatthew G. Knepley 6242a47d0d45SMatthew G. Knepley /* Need a temp buffer for coords if we have complex/single */ 6243835f2295SStefano Zampini PetscCall(PetscMPIIntCast(spaceDim, &spaceDimi)); 6244835f2295SStefano Zampini PetscCallMPI(MPI_Type_contiguous(spaceDimi, MPIU_SCALAR, &coordtype)); 62459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_commit(&coordtype)); 624621016a8bSBarry Smith #if defined(PETSC_USE_COMPLEX) 624721016a8bSBarry Smith { 624821016a8bSBarry Smith PetscScalar *svertexCoords; 624921016a8bSBarry Smith PetscInt i; 62509566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(numVertices * spaceDim, &svertexCoords)); 62513612f820SVaclav Hapla for (i = 0; i < numVertices * spaceDim; i++) svertexCoords[i] = vertexCoords[i]; 62529566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 62539566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, svertexCoords, coords, MPI_REPLACE)); 62549566063dSJacob Faibussowitsch PetscCall(PetscFree(svertexCoords)); 625521016a8bSBarry Smith } 625621016a8bSBarry Smith #else 62579566063dSJacob Faibussowitsch PetscCall(PetscSFBcastBegin(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 62589566063dSJacob Faibussowitsch PetscCall(PetscSFBcastEnd(sfVert, coordtype, vertexCoords, coords, MPI_REPLACE)); 625921016a8bSBarry Smith #endif 62609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Type_free(&coordtype)); 6261a47d0d45SMatthew G. Knepley } 62629566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 62639566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 62649566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 62659566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 62663ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6267a47d0d45SMatthew G. Knepley } 6268a47d0d45SMatthew G. Knepley 6269c3edce3dSSatish Balay /*@ 6270b0fe842aSMatthew 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 6271a1cb98faSBarry Smith 6272a1cb98faSBarry Smith Collective 6273a47d0d45SMatthew G. Knepley 6274a47d0d45SMatthew G. Knepley Input Parameters: 6275a47d0d45SMatthew G. Knepley + comm - The communicator 6276a47d0d45SMatthew G. Knepley . dim - The topological dimension of the mesh 6277a47d0d45SMatthew G. Knepley . numCells - The number of cells owned by this process 6278a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 6279a1cb98faSBarry Smith . NVertices - The global number of vertices, or `PETSC_DECIDE` 6280a47d0d45SMatthew G. Knepley . numCorners - The number of vertices for each cell 6281a47d0d45SMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6282a47d0d45SMatthew G. Knepley . cells - An array of numCells*numCorners numbers, the global vertex numbers for each cell 6283a47d0d45SMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 6284a47d0d45SMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6285a47d0d45SMatthew G. Knepley 6286d8d19677SJose E. Roman Output Parameters: 6287a1cb98faSBarry Smith + dm - The `DM` 6288a1cb98faSBarry Smith . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 628960225df5SJacob Faibussowitsch - verticesAdj - (Optional) vertex adjacency array 6290a47d0d45SMatthew G. Knepley 6291b09969d6SVaclav Hapla Level: intermediate 6292a47d0d45SMatthew G. Knepley 6293a1cb98faSBarry Smith Notes: 6294a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 6295a1cb98faSBarry Smith `DMPlexBuildFromCellListParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 6296a1cb98faSBarry Smith 6297a1cb98faSBarry Smith See `DMPlexBuildFromCellListParallel()` for an example and details about the topology-related parameters. 6298a1cb98faSBarry Smith 6299a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 6300a1cb98faSBarry Smith 63011cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 6302a47d0d45SMatthew G. Knepley @*/ 6303ce78bad3SBarry 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) 6304d71ae5a4SJacob Faibussowitsch { 6305a47d0d45SMatthew G. Knepley PetscSF sfVert; 6306a47d0d45SMatthew G. Knepley 6307a47d0d45SMatthew G. Knepley PetscFunctionBegin; 63089566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 63099566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 6310a47d0d45SMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 6311064a246eSJacob Faibussowitsch PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 63129566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 63139566063dSJacob Faibussowitsch PetscCall(DMPlexBuildFromCellListParallel(*dm, numCells, numVertices, NVertices, numCorners, cells, &sfVert, verticesAdj)); 6314a47d0d45SMatthew G. Knepley if (interpolate) { 63155fd9971aSMatthew G. Knepley DM idm; 6316a47d0d45SMatthew G. Knepley 63179566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 63189566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 6319a47d0d45SMatthew G. Knepley *dm = idm; 6320a47d0d45SMatthew G. Knepley } 63219566063dSJacob Faibussowitsch PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 632218d54ad4SMichael Lange if (vertexSF) *vertexSF = sfVert; 63239566063dSJacob Faibussowitsch else PetscCall(PetscSFDestroy(&sfVert)); 63243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6325a47d0d45SMatthew G. Knepley } 6326a47d0d45SMatthew G. Knepley 6327cc4c1da9SBarry Smith /*@ 6328b0fe842aSMatthew G. Knepley DMPlexCreateFromCellSectionParallel - Create distributed `DMPLEX` from a list of vertices for each cell (common mesh generator output) and supports multiple celltypes 6329b0fe842aSMatthew G. Knepley 6330b0fe842aSMatthew G. Knepley Collective 6331b0fe842aSMatthew G. Knepley 6332b0fe842aSMatthew G. Knepley Input Parameters: 6333b0fe842aSMatthew G. Knepley + comm - The communicator 6334b0fe842aSMatthew G. Knepley . dim - The topological dimension of the mesh 6335b0fe842aSMatthew G. Knepley . numCells - The number of cells owned by this process 6336b0fe842aSMatthew G. Knepley . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE` 6337b0fe842aSMatthew G. Knepley . NVertices - The global number of vertices, or `PETSC_DECIDE` 6338b0fe842aSMatthew G. Knepley . cellSection - The `PetscSection` giving the number of vertices for each cell (layout of cells) 6339b0fe842aSMatthew G. Knepley . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6340b0fe842aSMatthew G. Knepley . cells - An array of the global vertex numbers for each cell 6341b0fe842aSMatthew G. Knepley . spaceDim - The spatial dimension used for coordinates 6342b0fe842aSMatthew G. Knepley - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6343b0fe842aSMatthew G. Knepley 6344b0fe842aSMatthew G. Knepley Output Parameters: 6345b0fe842aSMatthew G. Knepley + dm - The `DM` 6346b0fe842aSMatthew G. Knepley . vertexSF - (Optional) `PetscSF` describing complete vertex ownership 6347b0fe842aSMatthew G. Knepley - verticesAdj - (Optional) vertex adjacency array 6348b0fe842aSMatthew G. Knepley 6349b0fe842aSMatthew G. Knepley Level: intermediate 6350b0fe842aSMatthew G. Knepley 6351b0fe842aSMatthew G. Knepley Notes: 6352b0fe842aSMatthew G. Knepley This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, 6353b0fe842aSMatthew G. Knepley `DMPlexBuildFromCellSectionParallel()`, `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellListParallel()` 6354b0fe842aSMatthew G. Knepley 6355b0fe842aSMatthew G. Knepley See `DMPlexBuildFromCellSectionParallel()` for an example and details about the topology-related parameters. 6356b0fe842aSMatthew G. Knepley 6357b0fe842aSMatthew G. Knepley See `DMPlexBuildCoordinatesFromCellListParallel()` for details about the geometry-related parameters. 6358b0fe842aSMatthew G. Knepley 6359b0fe842aSMatthew G. Knepley .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 6360b0fe842aSMatthew G. Knepley @*/ 6361ce78bad3SBarry 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) 6362b0fe842aSMatthew G. Knepley { 6363b0fe842aSMatthew G. Knepley PetscSF sfVert; 6364b0fe842aSMatthew G. Knepley 6365b0fe842aSMatthew G. Knepley PetscFunctionBegin; 6366b0fe842aSMatthew G. Knepley PetscCall(DMCreate(comm, dm)); 6367b0fe842aSMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 6368b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, dim, 2); 6369b0fe842aSMatthew G. Knepley PetscValidLogicalCollectiveInt(*dm, spaceDim, 9); 6370b0fe842aSMatthew G. Knepley PetscCall(DMSetDimension(*dm, dim)); 6371b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildFromCellSectionParallel(*dm, numCells, numVertices, NVertices, cellSection, cells, &sfVert, verticesAdj)); 6372b0fe842aSMatthew G. Knepley if (interpolate) { 6373b0fe842aSMatthew G. Knepley DM idm; 6374b0fe842aSMatthew G. Knepley 6375b0fe842aSMatthew G. Knepley PetscCall(DMPlexInterpolate(*dm, &idm)); 6376b0fe842aSMatthew G. Knepley PetscCall(DMDestroy(dm)); 6377b0fe842aSMatthew G. Knepley *dm = idm; 6378b0fe842aSMatthew G. Knepley } 6379b0fe842aSMatthew G. Knepley PetscCall(DMPlexBuildCoordinatesFromCellListParallel(*dm, spaceDim, sfVert, vertexCoords)); 6380b0fe842aSMatthew G. Knepley if (vertexSF) *vertexSF = sfVert; 6381b0fe842aSMatthew G. Knepley else PetscCall(PetscSFDestroy(&sfVert)); 6382b0fe842aSMatthew G. Knepley PetscFunctionReturn(PETSC_SUCCESS); 6383b0fe842aSMatthew G. Knepley } 6384b0fe842aSMatthew G. Knepley 6385b0fe842aSMatthew G. Knepley /*@ 6386a1cb98faSBarry Smith DMPlexBuildFromCellList - Build `DMPLEX` topology from a list of vertices for each cell (common mesh generator output) 6387a1cb98faSBarry Smith 638820f4b53cSBarry Smith Collective; No Fortran Support 63899298eaa6SMatthew G Knepley 63909298eaa6SMatthew G Knepley Input Parameters: 6391a1cb98faSBarry Smith + dm - The `DM` 6392b09969d6SVaclav Hapla . numCells - The number of cells owned by this process 6393a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DETERMINE` 63949298eaa6SMatthew G Knepley . numCorners - The number of vertices for each cell 6395a3b724e8SBarry Smith - cells - An array of `numCells` x `numCorners` numbers, the global vertex numbers for each cell 63969298eaa6SMatthew G Knepley 6397b09969d6SVaclav Hapla Level: advanced 63989298eaa6SMatthew G Knepley 6399b09969d6SVaclav Hapla Notes: 6400b09969d6SVaclav Hapla Two triangles sharing a face 6401a1cb98faSBarry Smith .vb 64029298eaa6SMatthew G Knepley 6403a1cb98faSBarry Smith 2 6404a1cb98faSBarry Smith / | \ 6405a1cb98faSBarry Smith / | \ 6406a1cb98faSBarry Smith / | \ 6407a1cb98faSBarry Smith 0 0 | 1 3 6408a1cb98faSBarry Smith \ | / 6409a1cb98faSBarry Smith \ | / 6410a1cb98faSBarry Smith \ | / 6411a1cb98faSBarry Smith 1 6412a1cb98faSBarry Smith .ve 6413a1cb98faSBarry Smith would have input 6414a1cb98faSBarry Smith .vb 6415a1cb98faSBarry Smith numCells = 2, numVertices = 4 6416a1cb98faSBarry Smith cells = [0 1 2 1 3 2] 6417a1cb98faSBarry Smith .ve 6418a1cb98faSBarry Smith which would result in the `DMPLEX` 6419a1cb98faSBarry Smith .vb 6420a1cb98faSBarry Smith 6421a1cb98faSBarry Smith 4 6422a1cb98faSBarry Smith / | \ 6423a1cb98faSBarry Smith / | \ 6424a1cb98faSBarry Smith / | \ 6425a1cb98faSBarry Smith 2 0 | 1 5 6426a1cb98faSBarry Smith \ | / 6427a1cb98faSBarry Smith \ | / 6428a1cb98faSBarry Smith \ | / 6429a1cb98faSBarry Smith 3 6430a1cb98faSBarry Smith .ve 6431a1cb98faSBarry Smith 6432a1cb98faSBarry Smith If numVertices is `PETSC_DETERMINE`, it is computed by PETSc as the maximum vertex index in cells + 1. 643325b6865aSVaclav Hapla 64341cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildFromCellListParallel()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromCellListPetsc()` 6435b09969d6SVaclav Hapla @*/ 6436d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildFromCellList(DM dm, PetscInt numCells, PetscInt numVertices, PetscInt numCorners, const PetscInt cells[]) 6437d71ae5a4SJacob Faibussowitsch { 6438961cfab0SVaclav Hapla PetscInt *cones, c, p, dim; 6439b09969d6SVaclav Hapla 6440b09969d6SVaclav Hapla PetscFunctionBegin; 64419566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 64429566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 644325b6865aSVaclav Hapla /* Get/check global number of vertices */ 644425b6865aSVaclav Hapla { 644525b6865aSVaclav Hapla PetscInt NVerticesInCells, i; 644625b6865aSVaclav Hapla const PetscInt len = numCells * numCorners; 644725b6865aSVaclav Hapla 644825b6865aSVaclav Hapla /* NVerticesInCells = max(cells) + 1 */ 64491690c2aeSBarry Smith NVerticesInCells = PETSC_INT_MIN; 64509371c9d4SSatish Balay for (i = 0; i < len; i++) 64519371c9d4SSatish Balay if (cells[i] > NVerticesInCells) NVerticesInCells = cells[i]; 645225b6865aSVaclav Hapla ++NVerticesInCells; 645325b6865aSVaclav Hapla 645425b6865aSVaclav Hapla if (numVertices == PETSC_DECIDE) numVertices = NVerticesInCells; 64559371c9d4SSatish Balay else 64569371c9d4SSatish 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); 645725b6865aSVaclav Hapla } 64589566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, 0, numCells + numVertices)); 645948a46eb9SPierre Jolivet for (c = 0; c < numCells; ++c) PetscCall(DMPlexSetConeSize(dm, c, numCorners)); 64609566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); 64619566063dSJacob Faibussowitsch PetscCall(DMPlexGetCones(dm, &cones)); 6462b09969d6SVaclav Hapla for (c = 0; c < numCells; ++c) { 6463ad540459SPierre Jolivet for (p = 0; p < numCorners; ++p) cones[c * numCorners + p] = cells[c * numCorners + p] + numCells; 6464b09969d6SVaclav Hapla } 64659566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 64669566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 64679566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildFromCellList, dm, 0, 0, 0)); 64683ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6469b09969d6SVaclav Hapla } 6470b09969d6SVaclav Hapla 6471cc4c1da9SBarry Smith /*@ 6472a1cb98faSBarry Smith DMPlexBuildCoordinatesFromCellList - Build `DM` coordinates from a list of coordinates for each owned vertex (common mesh generator output) 6473a1cb98faSBarry Smith 6474cc4c1da9SBarry Smith Collective 6475b09969d6SVaclav Hapla 6476b09969d6SVaclav Hapla Input Parameters: 6477a1cb98faSBarry Smith + dm - The `DM` 6478b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6479b09969d6SVaclav Hapla - vertexCoords - An array of numVertices*spaceDim numbers, the coordinates of each vertex 6480b09969d6SVaclav Hapla 6481b09969d6SVaclav Hapla Level: advanced 6482b09969d6SVaclav Hapla 64831cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexBuildCoordinatesFromCellListParallel()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexBuildFromCellList()` 6484b09969d6SVaclav Hapla @*/ 6485d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexBuildCoordinatesFromCellList(DM dm, PetscInt spaceDim, const PetscReal vertexCoords[]) 6486d71ae5a4SJacob Faibussowitsch { 6487b09969d6SVaclav Hapla PetscSection coordSection; 6488b09969d6SVaclav Hapla Vec coordinates; 6489b09969d6SVaclav Hapla DM cdm; 6490b09969d6SVaclav Hapla PetscScalar *coords; 64911edcf0b2SVaclav Hapla PetscInt v, vStart, vEnd, d; 6492b09969d6SVaclav Hapla 6493b09969d6SVaclav Hapla PetscFunctionBegin; 64949566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 64959566063dSJacob Faibussowitsch PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 64961dca8a05SBarry Smith PetscCheck(vStart >= 0 && vEnd >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "DM is not set up properly. DMPlexBuildFromCellList() should be called first."); 64979566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(dm, spaceDim)); 64989566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 64999566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 65009566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, spaceDim)); 65019566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, vStart, vEnd)); 65021edcf0b2SVaclav Hapla for (v = vStart; v < vEnd; ++v) { 65039566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, spaceDim)); 65049566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, spaceDim)); 6505b09969d6SVaclav Hapla } 65069566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 6507b09969d6SVaclav Hapla 65089566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDM(dm, &cdm)); 65099566063dSJacob Faibussowitsch PetscCall(DMCreateLocalVector(cdm, &coordinates)); 65109566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, spaceDim)); 65119566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 65129566063dSJacob Faibussowitsch PetscCall(VecGetArrayWrite(coordinates, &coords)); 65131edcf0b2SVaclav Hapla for (v = 0; v < vEnd - vStart; ++v) { 6514ad540459SPierre Jolivet for (d = 0; d < spaceDim; ++d) coords[v * spaceDim + d] = vertexCoords[v * spaceDim + d]; 6515b09969d6SVaclav Hapla } 65169566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayWrite(coordinates, &coords)); 65179566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 65189566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 65199566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_BuildCoordinatesFromCellList, dm, 0, 0, 0)); 65203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6521b09969d6SVaclav Hapla } 6522b09969d6SVaclav Hapla 6523b09969d6SVaclav Hapla /*@ 6524a1cb98faSBarry Smith DMPlexCreateFromCellListPetsc - Create `DMPLEX` from a list of vertices for each cell (common mesh generator output), but only process 0 takes in the input 65253df08285SMatthew G. Knepley 6526a1cb98faSBarry Smith Collective 6527b09969d6SVaclav Hapla 6528b09969d6SVaclav Hapla Input Parameters: 6529b09969d6SVaclav Hapla + comm - The communicator 6530b09969d6SVaclav Hapla . dim - The topological dimension of the mesh 65313df08285SMatthew G. Knepley . numCells - The number of cells, only on process 0 6532a1cb98faSBarry Smith . numVertices - The number of vertices owned by this process, or `PETSC_DECIDE`, only on process 0 65333df08285SMatthew G. Knepley . numCorners - The number of vertices for each cell, only on process 0 6534b09969d6SVaclav Hapla . interpolate - Flag indicating that intermediate mesh entities (faces, edges) should be created automatically 6535ce78bad3SBarry Smith . cells - An array of $ numCells \times numCorners$ numbers, the vertices for each cell, only on process 0 6536b09969d6SVaclav Hapla . spaceDim - The spatial dimension used for coordinates 6537ce78bad3SBarry Smith - vertexCoords - An array of $ numVertices \times spaceDim$ numbers, the coordinates of each vertex, only on process 0 6538b09969d6SVaclav Hapla 6539b09969d6SVaclav Hapla Output Parameter: 6540a1cb98faSBarry Smith . dm - The `DM`, which only has points on process 0 654125b6865aSVaclav Hapla 6542b09969d6SVaclav Hapla Level: intermediate 6543b09969d6SVaclav Hapla 6544a1cb98faSBarry Smith Notes: 6545a1cb98faSBarry Smith This function is just a convenient sequence of `DMCreate()`, `DMSetType()`, `DMSetDimension()`, `DMPlexBuildFromCellList()`, 6546a1cb98faSBarry Smith `DMPlexInterpolate()`, `DMPlexBuildCoordinatesFromCellList()` 6547a1cb98faSBarry Smith 6548a1cb98faSBarry Smith See `DMPlexBuildFromCellList()` for an example and details about the topology-related parameters. 6549a1cb98faSBarry Smith See `DMPlexBuildCoordinatesFromCellList()` for details about the geometry-related parameters. 6550a1cb98faSBarry Smith See `DMPlexCreateFromCellListParallelPetsc()` for parallel input 6551a1cb98faSBarry Smith 65521cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListParallelPetsc()`, `DMPlexBuildFromCellList()`, `DMPlexBuildCoordinatesFromCellList()`, `DMPlexCreateFromDAG()`, `DMPlexCreate()` 65539298eaa6SMatthew G Knepley @*/ 6554d71ae5a4SJacob 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) 6555d71ae5a4SJacob Faibussowitsch { 65563df08285SMatthew G. Knepley PetscMPIInt rank; 65579298eaa6SMatthew G Knepley 65589298eaa6SMatthew G Knepley PetscFunctionBegin; 655928b400f6SJacob 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."); 65609566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 65619566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 65629566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 65639566063dSJacob Faibussowitsch PetscCall(DMSetDimension(*dm, dim)); 6564c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildFromCellList(*dm, numCells, numVertices, numCorners, cells)); 65659566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildFromCellList(*dm, 0, 0, 0, NULL)); 65669298eaa6SMatthew G Knepley if (interpolate) { 65675fd9971aSMatthew G. Knepley DM idm; 65689298eaa6SMatthew G Knepley 65699566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 65709566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 65719298eaa6SMatthew G Knepley *dm = idm; 65729298eaa6SMatthew G Knepley } 6573c5853193SPierre Jolivet if (rank == 0) PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, vertexCoords)); 65749566063dSJacob Faibussowitsch else PetscCall(DMPlexBuildCoordinatesFromCellList(*dm, spaceDim, NULL)); 65753ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 65769298eaa6SMatthew G Knepley } 65779298eaa6SMatthew G Knepley 6578939f6067SMatthew G. Knepley /*@ 657920f4b53cSBarry Smith DMPlexCreateFromDAG - This takes as input the adjacency-list representation of the Directed Acyclic Graph (Hasse Diagram) encoding a mesh, and produces a `DM` 6580939f6067SMatthew G. Knepley 6581939f6067SMatthew G. Knepley Input Parameters: 658220f4b53cSBarry Smith + dm - The empty `DM` object, usually from `DMCreate()` and `DMSetDimension()` 6583939f6067SMatthew G. Knepley . depth - The depth of the DAG 6584ce78bad3SBarry Smith . numPoints - Array of size $ depth + 1 $ containing the number of points at each `depth` 6585939f6067SMatthew G. Knepley . coneSize - The cone size of each point 6586939f6067SMatthew G. Knepley . cones - The concatenation of the cone points for each point, the cone list must be oriented correctly for each point 6587939f6067SMatthew G. Knepley . coneOrientations - The orientation of each cone point 6588ce78bad3SBarry Smith - vertexCoords - An array of $ numPoints[0] \times spacedim $ numbers representing the coordinates of each vertex, with `spacedim` the value set via `DMSetCoordinateDim()` 6589939f6067SMatthew G. Knepley 6590939f6067SMatthew G. Knepley Output Parameter: 659120f4b53cSBarry Smith . dm - The `DM` 659220f4b53cSBarry Smith 659320f4b53cSBarry Smith Level: advanced 6594939f6067SMatthew G. Knepley 6595a1cb98faSBarry Smith Note: 6596a1cb98faSBarry Smith Two triangles sharing a face would have input 6597a1cb98faSBarry Smith .vb 6598a1cb98faSBarry Smith depth = 1, numPoints = [4 2], coneSize = [3 3 0 0 0 0] 6599a1cb98faSBarry Smith cones = [2 3 4 3 5 4], coneOrientations = [0 0 0 0 0 0] 6600a1cb98faSBarry Smith vertexCoords = [-1.0 0.0 0.0 -1.0 0.0 1.0 1.0 0.0] 6601a1cb98faSBarry Smith .ve 6602939f6067SMatthew G. Knepley which would result in the DMPlex 6603a1cb98faSBarry Smith .vb 6604a1cb98faSBarry Smith 4 6605a1cb98faSBarry Smith / | \ 6606a1cb98faSBarry Smith / | \ 6607a1cb98faSBarry Smith / | \ 6608a1cb98faSBarry Smith 2 0 | 1 5 6609a1cb98faSBarry Smith \ | / 6610a1cb98faSBarry Smith \ | / 6611a1cb98faSBarry Smith \ | / 6612a1cb98faSBarry Smith 3 6613a1cb98faSBarry Smith .ve 6614a1cb98faSBarry Smith Notice that all points are numbered consecutively, unlike `DMPlexCreateFromCellListPetsc()` 6615939f6067SMatthew G. Knepley 6616ce78bad3SBarry Smith Developer Note: 6617ce78bad3SBarry Smith This does not create anything so should not have create in the name. 6618ce78bad3SBarry Smith 66191cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 6620939f6067SMatthew G. Knepley @*/ 6621d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromDAG(DM dm, PetscInt depth, const PetscInt numPoints[], const PetscInt coneSize[], const PetscInt cones[], const PetscInt coneOrientations[], const PetscScalar vertexCoords[]) 6622d71ae5a4SJacob Faibussowitsch { 66239298eaa6SMatthew G Knepley Vec coordinates; 66249298eaa6SMatthew G Knepley PetscSection coordSection; 66259298eaa6SMatthew G Knepley PetscScalar *coords; 6626811e8653SToby Isaac PetscInt coordSize, firstVertex = -1, pStart = 0, pEnd = 0, p, v, dim, dimEmbed, d, off; 66279298eaa6SMatthew G Knepley 66289298eaa6SMatthew G Knepley PetscFunctionBegin; 66299566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 66309566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateDim(dm, &dimEmbed)); 663163a3b9bcSJacob Faibussowitsch PetscCheck(dimEmbed >= dim, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Embedding dimension %" PetscInt_FMT " cannot be less than intrinsic dimension %" PetscInt_FMT, dimEmbed, dim); 66329298eaa6SMatthew G Knepley for (d = 0; d <= depth; ++d) pEnd += numPoints[d]; 66339566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(dm, pStart, pEnd)); 66349298eaa6SMatthew G Knepley for (p = pStart; p < pEnd; ++p) { 66359566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeSize(dm, p, coneSize[p - pStart])); 6636ad540459SPierre Jolivet if (firstVertex < 0 && !coneSize[p - pStart]) firstVertex = p - pStart; 663797e052ccSToby Isaac } 66381dca8a05SBarry Smith PetscCheck(firstVertex >= 0 || !numPoints[0], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Expected %" PetscInt_FMT " vertices but could not find any", numPoints[0]); 66399566063dSJacob Faibussowitsch PetscCall(DMSetUp(dm)); /* Allocate space for cones */ 66409298eaa6SMatthew G Knepley for (p = pStart, off = 0; p < pEnd; off += coneSize[p - pStart], ++p) { 66419566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(dm, p, &cones[off])); 66429566063dSJacob Faibussowitsch PetscCall(DMPlexSetConeOrientation(dm, p, &coneOrientations[off])); 66439298eaa6SMatthew G Knepley } 66449566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(dm)); 66459566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(dm)); 66469298eaa6SMatthew G Knepley /* Build coordinates */ 66479566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(dm, &coordSection)); 66489566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 66499566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed)); 66509566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, firstVertex, firstVertex + numPoints[0])); 66519298eaa6SMatthew G Knepley for (v = firstVertex; v < firstVertex + numPoints[0]; ++v) { 66529566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed)); 66539566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed)); 66549298eaa6SMatthew G Knepley } 66559566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 66569566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 66579566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 66589566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 66599566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 666058b7e2c1SStefano Zampini PetscCall(VecSetBlockSize(coordinates, PetscMax(dimEmbed, 1))); 66619566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 66629318fe57SMatthew G. Knepley if (vertexCoords) { 66639566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 66649298eaa6SMatthew G Knepley for (v = 0; v < numPoints[0]; ++v) { 66659298eaa6SMatthew G Knepley PetscInt off; 66669298eaa6SMatthew G Knepley 66679566063dSJacob Faibussowitsch PetscCall(PetscSectionGetOffset(coordSection, v + firstVertex, &off)); 6668ad540459SPierre Jolivet for (d = 0; d < dimEmbed; ++d) coords[off + d] = vertexCoords[v * dimEmbed + d]; 66699298eaa6SMatthew G Knepley } 66709318fe57SMatthew G. Knepley } 66719566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 66729566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(dm, coordinates)); 66739566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 66743ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 66759298eaa6SMatthew G Knepley } 66768415267dSToby Isaac 6677a4e35b19SJacob Faibussowitsch /* 6678a1cb98faSBarry Smith DMPlexCreateCellVertexFromFile - Create a `DMPLEX` mesh from a simple cell-vertex file. 6679a1cb98faSBarry Smith 6680a1cb98faSBarry Smith Collective 66818ca92349SMatthew G. Knepley 66828ca92349SMatthew G. Knepley + comm - The MPI communicator 66838ca92349SMatthew G. Knepley . filename - Name of the .dat file 66848ca92349SMatthew G. Knepley - interpolate - Create faces and edges in the mesh 66858ca92349SMatthew G. Knepley 66868ca92349SMatthew G. Knepley Output Parameter: 6687a1cb98faSBarry Smith . dm - The `DM` object representing the mesh 66888ca92349SMatthew G. Knepley 66898ca92349SMatthew G. Knepley Level: beginner 66908ca92349SMatthew G. Knepley 6691a1cb98faSBarry Smith Note: 6692a1cb98faSBarry Smith The format is the simplest possible: 6693a1cb98faSBarry Smith .vb 6694d0812dedSMatthew G. Knepley dim Ne Nv Nc Nl 6695d0812dedSMatthew G. Knepley v_1 v_2 ... v_Nc 6696d0812dedSMatthew G. Knepley ... 6697d0812dedSMatthew G. Knepley x y z marker_1 ... marker_Nl 6698a1cb98faSBarry Smith .ve 6699a1cb98faSBarry Smith 6700a1cb98faSBarry Smith Developer Note: 6701a1cb98faSBarry Smith Should use a `PetscViewer` not a filename 6702a1cb98faSBarry Smith 67036afe31f6SMartin Diehl .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromFile()`, `DMPlexCreateGmsh()`, `DMPlexCreate()` 6704a4e35b19SJacob Faibussowitsch */ 6705ff6a9541SJacob Faibussowitsch static PetscErrorCode DMPlexCreateCellVertexFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 6706d71ae5a4SJacob Faibussowitsch { 67078ca92349SMatthew G. Knepley DMLabel marker; 67088ca92349SMatthew G. Knepley PetscViewer viewer; 67098ca92349SMatthew G. Knepley Vec coordinates; 67108ca92349SMatthew G. Knepley PetscSection coordSection; 67118ca92349SMatthew G. Knepley PetscScalar *coords; 67128ca92349SMatthew G. Knepley char line[PETSC_MAX_PATH_LEN]; 6713d0812dedSMatthew G. Knepley PetscInt cdim, coordSize, v, c, d; 67148ca92349SMatthew G. Knepley PetscMPIInt rank; 6715d0812dedSMatthew G. Knepley int snum, dim, Nv, Nc, Ncn, Nl; 67168ca92349SMatthew G. Knepley 67178ca92349SMatthew G. Knepley PetscFunctionBegin; 67189566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 67199566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 67209566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII)); 67219566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 67229566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 6723dd400576SPatrick Sanan if (rank == 0) { 6724d0812dedSMatthew G. Knepley PetscCall(PetscViewerRead(viewer, line, 5, NULL, PETSC_STRING)); 6725d0812dedSMatthew G. Knepley snum = sscanf(line, "%d %d %d %d %d", &dim, &Nc, &Nv, &Ncn, &Nl); 6726d0812dedSMatthew G. Knepley PetscCheck(snum == 5, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 672725ce1634SJed Brown } else { 6728f8d5e320SMatthew G. Knepley Nc = Nv = Ncn = Nl = 0; 67298ca92349SMatthew G. Knepley } 6730d0812dedSMatthew G. Knepley PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm)); 6731835f2295SStefano Zampini cdim = dim; 67329566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 67339566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 67349566063dSJacob Faibussowitsch PetscCall(DMPlexSetChart(*dm, 0, Nc + Nv)); 6735835f2295SStefano Zampini PetscCall(DMSetDimension(*dm, dim)); 67369566063dSJacob Faibussowitsch PetscCall(DMSetCoordinateDim(*dm, cdim)); 67378ca92349SMatthew G. Knepley /* Read topology */ 6738dd400576SPatrick Sanan if (rank == 0) { 6739f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 6740f8d5e320SMatthew G. Knepley PetscInt cone[8]; 67418ca92349SMatthew G. Knepley int vbuf[8], v; 67428ca92349SMatthew G. Knepley 67439371c9d4SSatish Balay for (c = 0; c < Ncn; ++c) { 67449371c9d4SSatish Balay format[c * 3 + 0] = '%'; 67459371c9d4SSatish Balay format[c * 3 + 1] = 'd'; 67469371c9d4SSatish Balay format[c * 3 + 2] = ' '; 67479371c9d4SSatish Balay } 6748f8d5e320SMatthew G. Knepley format[Ncn * 3 - 1] = '\0'; 67499566063dSJacob Faibussowitsch for (c = 0; c < Nc; ++c) PetscCall(DMPlexSetConeSize(*dm, c, Ncn)); 67509566063dSJacob Faibussowitsch PetscCall(DMSetUp(*dm)); 67518ca92349SMatthew G. Knepley for (c = 0; c < Nc; ++c) { 67529566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, Ncn, NULL, PETSC_STRING)); 6753f8d5e320SMatthew G. Knepley switch (Ncn) { 6754d71ae5a4SJacob Faibussowitsch case 2: 6755d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1]); 6756d71ae5a4SJacob Faibussowitsch break; 6757d71ae5a4SJacob Faibussowitsch case 3: 6758d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2]); 6759d71ae5a4SJacob Faibussowitsch break; 6760d71ae5a4SJacob Faibussowitsch case 4: 6761d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3]); 6762d71ae5a4SJacob Faibussowitsch break; 6763d71ae5a4SJacob Faibussowitsch case 6: 6764d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5]); 6765d71ae5a4SJacob Faibussowitsch break; 6766d71ae5a4SJacob Faibussowitsch case 8: 6767d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &vbuf[0], &vbuf[1], &vbuf[2], &vbuf[3], &vbuf[4], &vbuf[5], &vbuf[6], &vbuf[7]); 6768d71ae5a4SJacob Faibussowitsch break; 6769d71ae5a4SJacob Faibussowitsch default: 6770d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell shape with %d vertices", Ncn); 6771f8d5e320SMatthew G. Knepley } 677208401ef6SPierre Jolivet PetscCheck(snum == Ncn, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6773f8d5e320SMatthew G. Knepley for (v = 0; v < Ncn; ++v) cone[v] = vbuf[v] + Nc; 67748ca92349SMatthew G. Knepley /* Hexahedra are inverted */ 6775f8d5e320SMatthew G. Knepley if (Ncn == 8) { 67768ca92349SMatthew G. Knepley PetscInt tmp = cone[1]; 67778ca92349SMatthew G. Knepley cone[1] = cone[3]; 67788ca92349SMatthew G. Knepley cone[3] = tmp; 67798ca92349SMatthew G. Knepley } 67809566063dSJacob Faibussowitsch PetscCall(DMPlexSetCone(*dm, c, cone)); 67818ca92349SMatthew G. Knepley } 67828ca92349SMatthew G. Knepley } 67839566063dSJacob Faibussowitsch PetscCall(DMPlexSymmetrize(*dm)); 67849566063dSJacob Faibussowitsch PetscCall(DMPlexStratify(*dm)); 67858ca92349SMatthew G. Knepley /* Read coordinates */ 67869566063dSJacob Faibussowitsch PetscCall(DMGetCoordinateSection(*dm, &coordSection)); 67879566063dSJacob Faibussowitsch PetscCall(PetscSectionSetNumFields(coordSection, 1)); 67889566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldComponents(coordSection, 0, cdim)); 67899566063dSJacob Faibussowitsch PetscCall(PetscSectionSetChart(coordSection, Nc, Nc + Nv)); 67908ca92349SMatthew G. Knepley for (v = Nc; v < Nc + Nv; ++v) { 67919566063dSJacob Faibussowitsch PetscCall(PetscSectionSetDof(coordSection, v, cdim)); 67929566063dSJacob Faibussowitsch PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, cdim)); 67938ca92349SMatthew G. Knepley } 67949566063dSJacob Faibussowitsch PetscCall(PetscSectionSetUp(coordSection)); 67959566063dSJacob Faibussowitsch PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize)); 67969566063dSJacob Faibussowitsch PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates)); 67979566063dSJacob Faibussowitsch PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates")); 67989566063dSJacob Faibussowitsch PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE)); 67999566063dSJacob Faibussowitsch PetscCall(VecSetBlockSize(coordinates, cdim)); 68009566063dSJacob Faibussowitsch PetscCall(VecSetType(coordinates, VECSTANDARD)); 68019566063dSJacob Faibussowitsch PetscCall(VecGetArray(coordinates, &coords)); 6802dd400576SPatrick Sanan if (rank == 0) { 6803f8d5e320SMatthew G. Knepley char format[PETSC_MAX_PATH_LEN]; 68048ca92349SMatthew G. Knepley double x[3]; 6805f8d5e320SMatthew G. Knepley int l, val[3]; 68068ca92349SMatthew G. Knepley 6807f8d5e320SMatthew G. Knepley if (Nl) { 68089371c9d4SSatish Balay for (l = 0; l < Nl; ++l) { 68099371c9d4SSatish Balay format[l * 3 + 0] = '%'; 68109371c9d4SSatish Balay format[l * 3 + 1] = 'd'; 68119371c9d4SSatish Balay format[l * 3 + 2] = ' '; 68129371c9d4SSatish Balay } 6813f8d5e320SMatthew G. Knepley format[Nl * 3 - 1] = '\0'; 68149566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 68159566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &marker)); 6816f8d5e320SMatthew G. Knepley } 68178ca92349SMatthew G. Knepley for (v = 0; v < Nv; ++v) { 68189566063dSJacob Faibussowitsch PetscCall(PetscViewerRead(viewer, line, 3 + Nl, NULL, PETSC_STRING)); 6819f8d5e320SMatthew G. Knepley snum = sscanf(line, "%lg %lg %lg", &x[0], &x[1], &x[2]); 682008401ef6SPierre Jolivet PetscCheck(snum == 3, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 6821f8d5e320SMatthew G. Knepley switch (Nl) { 6822d71ae5a4SJacob Faibussowitsch case 0: 6823d71ae5a4SJacob Faibussowitsch snum = 0; 6824d71ae5a4SJacob Faibussowitsch break; 6825d71ae5a4SJacob Faibussowitsch case 1: 6826d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0]); 6827d71ae5a4SJacob Faibussowitsch break; 6828d71ae5a4SJacob Faibussowitsch case 2: 6829d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1]); 6830d71ae5a4SJacob Faibussowitsch break; 6831d71ae5a4SJacob Faibussowitsch case 3: 6832d71ae5a4SJacob Faibussowitsch snum = sscanf(line, format, &val[0], &val[1], &val[2]); 6833d71ae5a4SJacob Faibussowitsch break; 6834d71ae5a4SJacob Faibussowitsch default: 6835d71ae5a4SJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "Request support for %d labels", Nl); 6836f8d5e320SMatthew G. Knepley } 683708401ef6SPierre Jolivet PetscCheck(snum == Nl, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to parse cell-vertex file: %s", line); 68388ca92349SMatthew G. Knepley for (d = 0; d < cdim; ++d) coords[v * cdim + d] = x[d]; 68399566063dSJacob Faibussowitsch for (l = 0; l < Nl; ++l) PetscCall(DMLabelSetValue(marker, v + Nc, val[l])); 68408ca92349SMatthew G. Knepley } 68418ca92349SMatthew G. Knepley } 68429566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(coordinates, &coords)); 68439566063dSJacob Faibussowitsch PetscCall(DMSetCoordinatesLocal(*dm, coordinates)); 68449566063dSJacob Faibussowitsch PetscCall(VecDestroy(&coordinates)); 68459566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 68468ca92349SMatthew G. Knepley if (interpolate) { 68478ca92349SMatthew G. Knepley DM idm; 68488ca92349SMatthew G. Knepley DMLabel bdlabel; 68498ca92349SMatthew G. Knepley 68509566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 68519566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 68528ca92349SMatthew G. Knepley *dm = idm; 68538ca92349SMatthew G. Knepley 6854f8d5e320SMatthew G. Knepley if (!Nl) { 68559566063dSJacob Faibussowitsch PetscCall(DMCreateLabel(*dm, "marker")); 68569566063dSJacob Faibussowitsch PetscCall(DMGetLabel(*dm, "marker", &bdlabel)); 68579566063dSJacob Faibussowitsch PetscCall(DMPlexMarkBoundaryFaces(*dm, PETSC_DETERMINE, bdlabel)); 68589566063dSJacob Faibussowitsch PetscCall(DMPlexLabelComplete(*dm, bdlabel)); 68598ca92349SMatthew G. Knepley } 6860f8d5e320SMatthew G. Knepley } 68613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 68628ca92349SMatthew G. Knepley } 68638ca92349SMatthew G. Knepley 6864cc4c1da9SBarry Smith /*@ 6865a1cb98faSBarry Smith DMPlexCreateFromFile - This takes a filename and produces a `DM` 6866a1cb98faSBarry Smith 6867a1cb98faSBarry Smith Collective 6868ca522641SMatthew G. Knepley 6869ca522641SMatthew G. Knepley Input Parameters: 6870ca522641SMatthew G. Knepley + comm - The communicator 6871ca522641SMatthew G. Knepley . filename - A file name 6872a1cb98faSBarry Smith . plexname - The object name of the resulting `DM`, also used for intra-datafile lookup by some formats 6873ca522641SMatthew G. Knepley - interpolate - Flag to create intermediate mesh pieces (edges, faces) 6874ca522641SMatthew G. Knepley 6875ca522641SMatthew G. Knepley Output Parameter: 6876a1cb98faSBarry Smith . dm - The `DM` 6877ca522641SMatthew G. Knepley 6878a1cb98faSBarry Smith Options Database Key: 6879a1cb98faSBarry Smith . -dm_plex_create_from_hdf5_xdmf - use the `PETSC_VIEWER_HDF5_XDMF` format for reading HDF5 688002ef0d99SVaclav Hapla 6881b44f4de4SBarry Smith Use `-dm_plex_create_ prefix` to pass options to the internal `PetscViewer`, e.g. `-dm_plex_create_viewer_hdf5_collective` 6882bca97951SVaclav Hapla 6883ca522641SMatthew G. Knepley Level: beginner 6884ca522641SMatthew G. Knepley 6885a1cb98faSBarry Smith Notes: 6886a1cb98faSBarry Smith Using `PETSCVIEWERHDF5` type with `PETSC_VIEWER_HDF5_PETSC` format, one can save multiple `DMPLEX` 6887a1cb98faSBarry Smith meshes in a single HDF5 file. This in turn requires one to name the `DMPLEX` object with `PetscObjectSetName()` 6888a1cb98faSBarry Smith before saving it with `DMView()` and before loading it with `DMLoad()` for identification of the mesh object. 6889a1cb98faSBarry Smith The input parameter name is thus used to name the `DMPLEX` object when `DMPlexCreateFromFile()` internally 6890a1cb98faSBarry Smith calls `DMLoad()`. Currently, name is ignored for other viewer types and/or formats. 6891a1cb98faSBarry Smith 68921cc06b55SBarry Smith .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()`, `PetscObjectSetName()`, `DMView()`, `DMLoad()` 6893ca522641SMatthew G. Knepley @*/ 6894d71ae5a4SJacob Faibussowitsch PetscErrorCode DMPlexCreateFromFile(MPI_Comm comm, const char filename[], const char plexname[], PetscBool interpolate, DM *dm) 6895d71ae5a4SJacob Faibussowitsch { 6896ef3a5affSJacob Faibussowitsch const char extGmsh[] = ".msh"; 6897ef3a5affSJacob Faibussowitsch const char extGmsh2[] = ".msh2"; 6898ef3a5affSJacob Faibussowitsch const char extGmsh4[] = ".msh4"; 6899ef3a5affSJacob Faibussowitsch const char extCGNS[] = ".cgns"; 6900ef3a5affSJacob Faibussowitsch const char extExodus[] = ".exo"; 6901ef3a5affSJacob Faibussowitsch const char extExodus_e[] = ".e"; 6902ef3a5affSJacob Faibussowitsch const char extGenesis[] = ".gen"; 6903ef3a5affSJacob Faibussowitsch const char extFluent[] = ".cas"; 6904ef3a5affSJacob Faibussowitsch const char extHDF5[] = ".h5"; 69056f2c871aSStefano Zampini const char extXDMFHDF5[] = ".xdmf.h5"; 6906ef3a5affSJacob Faibussowitsch const char extPLY[] = ".ply"; 69075552b385SBrandon const char extEGADSlite[] = ".egadslite"; 6908ef3a5affSJacob Faibussowitsch const char extEGADS[] = ".egads"; 6909ef3a5affSJacob Faibussowitsch const char extIGES[] = ".igs"; 69105552b385SBrandon const char extIGES2[] = ".iges"; 6911ef3a5affSJacob Faibussowitsch const char extSTEP[] = ".stp"; 69125552b385SBrandon const char extSTEP2[] = ".step"; 69135552b385SBrandon const char extBREP[] = ".brep"; 6914ef3a5affSJacob Faibussowitsch const char extCV[] = ".dat"; 6915ca522641SMatthew G. Knepley size_t len; 69165552b385SBrandon PetscBool isGmsh, isGmsh2, isGmsh4, isCGNS, isExodus, isGenesis, isFluent, isHDF5, isPLY, isEGADSlite, isEGADS, isIGES, isIGES2, isSTEP, isSTEP2, isBREP, isCV, isXDMFHDF5; 6917ca522641SMatthew G. Knepley PetscMPIInt rank; 6918ca522641SMatthew G. Knepley 6919ca522641SMatthew G. Knepley PetscFunctionBegin; 69204f572ea9SToby Isaac PetscAssertPointer(filename, 2); 69214f572ea9SToby Isaac if (plexname) PetscAssertPointer(plexname, 3); 69224f572ea9SToby Isaac PetscAssertPointer(dm, 5); 69239566063dSJacob Faibussowitsch PetscCall(DMInitializePackage()); 69249566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 69259566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 69269566063dSJacob Faibussowitsch PetscCall(PetscStrlen(filename, &len)); 692728b400f6SJacob Faibussowitsch PetscCheck(len, comm, PETSC_ERR_ARG_WRONG, "Filename must be a valid path"); 6928ef3a5affSJacob Faibussowitsch 69299371c9d4SSatish Balay #define CheckExtension(extension__, is_extension__) \ 69309371c9d4SSatish Balay do { \ 6931274aaeaaSJacob Faibussowitsch PetscAssert(sizeof(extension__), comm, PETSC_ERR_PLIB, "Zero-size extension: %s", extension__); \ 6932274aaeaaSJacob Faibussowitsch /* don't count the null-terminator at the end */ \ 6933274aaeaaSJacob Faibussowitsch const size_t ext_len = sizeof(extension__) - 1; \ 6934274aaeaaSJacob Faibussowitsch if (len < ext_len) { \ 6935ef3a5affSJacob Faibussowitsch is_extension__ = PETSC_FALSE; \ 6936ef3a5affSJacob Faibussowitsch } else { \ 6937274aaeaaSJacob Faibussowitsch PetscCall(PetscStrncmp(filename + len - ext_len, extension__, ext_len, &is_extension__)); \ 6938ef3a5affSJacob Faibussowitsch } \ 6939ef3a5affSJacob Faibussowitsch } while (0) 6940ef3a5affSJacob Faibussowitsch 6941ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh, isGmsh); 6942ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh2, isGmsh2); 6943ef3a5affSJacob Faibussowitsch CheckExtension(extGmsh4, isGmsh4); 6944ef3a5affSJacob Faibussowitsch CheckExtension(extCGNS, isCGNS); 6945ef3a5affSJacob Faibussowitsch CheckExtension(extExodus, isExodus); 6946ef3a5affSJacob Faibussowitsch if (!isExodus) CheckExtension(extExodus_e, isExodus); 6947ef3a5affSJacob Faibussowitsch CheckExtension(extGenesis, isGenesis); 6948ef3a5affSJacob Faibussowitsch CheckExtension(extFluent, isFluent); 6949ef3a5affSJacob Faibussowitsch CheckExtension(extHDF5, isHDF5); 6950ef3a5affSJacob Faibussowitsch CheckExtension(extPLY, isPLY); 69515552b385SBrandon CheckExtension(extEGADSlite, isEGADSlite); 6952ef3a5affSJacob Faibussowitsch CheckExtension(extEGADS, isEGADS); 6953ef3a5affSJacob Faibussowitsch CheckExtension(extIGES, isIGES); 69545552b385SBrandon CheckExtension(extIGES2, isIGES2); 6955ef3a5affSJacob Faibussowitsch CheckExtension(extSTEP, isSTEP); 69565552b385SBrandon CheckExtension(extSTEP2, isSTEP2); 69575552b385SBrandon CheckExtension(extBREP, isBREP); 6958ef3a5affSJacob Faibussowitsch CheckExtension(extCV, isCV); 69596f2c871aSStefano Zampini CheckExtension(extXDMFHDF5, isXDMFHDF5); 6960ef3a5affSJacob Faibussowitsch 6961ef3a5affSJacob Faibussowitsch #undef CheckExtension 6962ef3a5affSJacob Faibussowitsch 6963de78e4feSLisandro Dalcin if (isGmsh || isGmsh2 || isGmsh4) { 69649566063dSJacob Faibussowitsch PetscCall(DMPlexCreateGmshFromFile(comm, filename, interpolate, dm)); 6965ca522641SMatthew G. Knepley } else if (isCGNS) { 69669566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCGNSFromFile(comm, filename, interpolate, dm)); 696790c68965SMatthew G. Knepley } else if (isExodus || isGenesis) { 69689566063dSJacob Faibussowitsch PetscCall(DMPlexCreateExodusFromFile(comm, filename, interpolate, dm)); 69692f0bd6dcSMichael Lange } else if (isFluent) { 69709566063dSJacob Faibussowitsch PetscCall(DMPlexCreateFluentFromFile(comm, filename, interpolate, dm)); 6971cc2f8f65SMatthew G. Knepley } else if (isHDF5) { 6972cc2f8f65SMatthew G. Knepley PetscViewer viewer; 6973cc2f8f65SMatthew G. Knepley 697443b242b4SVaclav 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 */ 69756f2c871aSStefano Zampini PetscCall(PetscOptionsGetBool(NULL, NULL, "-dm_plex_create_from_hdf5_xdmf", &isXDMFHDF5, NULL)); 69769566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, &viewer)); 69779566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(viewer, PETSCVIEWERHDF5)); 69789566063dSJacob Faibussowitsch PetscCall(PetscViewerSetOptionsPrefix(viewer, "dm_plex_create_")); 69799566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(viewer)); 69809566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_READ)); 69819566063dSJacob Faibussowitsch PetscCall(PetscViewerFileSetName(viewer, filename)); 6982cd7e8a5eSksagiyam 69839566063dSJacob Faibussowitsch PetscCall(DMCreate(comm, dm)); 6984f4f49eeaSPierre Jolivet PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 69859566063dSJacob Faibussowitsch PetscCall(DMSetType(*dm, DMPLEX)); 69866f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_XDMF)); 69879566063dSJacob Faibussowitsch PetscCall(DMLoad(*dm, viewer)); 69886f2c871aSStefano Zampini if (isXDMFHDF5) PetscCall(PetscViewerPopFormat(viewer)); 69899566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&viewer)); 69905fd9971aSMatthew G. Knepley 69915fd9971aSMatthew G. Knepley if (interpolate) { 69925fd9971aSMatthew G. Knepley DM idm; 69935fd9971aSMatthew G. Knepley 69949566063dSJacob Faibussowitsch PetscCall(DMPlexInterpolate(*dm, &idm)); 69959566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 69965fd9971aSMatthew G. Knepley *dm = idm; 69975fd9971aSMatthew G. Knepley } 6998f2801cd6SMatthew G. Knepley } else if (isPLY) { 69999566063dSJacob Faibussowitsch PetscCall(DMPlexCreatePLYFromFile(comm, filename, interpolate, dm)); 70005552b385SBrandon } else if (isEGADSlite || isEGADS || isIGES || isIGES2 || isSTEP || isSTEP2 || isBREP) { 70015552b385SBrandon PetscCall(DMPlexCreateGeomFromFile(comm, filename, dm, isEGADSlite)); 70025552b385SBrandon 70037bee2925SMatthew Knepley if (!interpolate) { 70047bee2925SMatthew Knepley DM udm; 70057bee2925SMatthew Knepley 70069566063dSJacob Faibussowitsch PetscCall(DMPlexUninterpolate(*dm, &udm)); 70079566063dSJacob Faibussowitsch PetscCall(DMDestroy(dm)); 70087bee2925SMatthew Knepley *dm = udm; 70097bee2925SMatthew Knepley } 70108ca92349SMatthew G. Knepley } else if (isCV) { 70119566063dSJacob Faibussowitsch PetscCall(DMPlexCreateCellVertexFromFile(comm, filename, interpolate, dm)); 701298921bdaSJacob Faibussowitsch } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cannot load file %s: unrecognized extension", filename); 70139566063dSJacob Faibussowitsch PetscCall(PetscStrlen(plexname, &len)); 7014f4f49eeaSPierre Jolivet if (len) PetscCall(PetscObjectSetName((PetscObject)*dm, plexname)); 70159566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMPLEX_CreateFromFile, 0, 0, 0, 0)); 70163ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7017ca522641SMatthew G. Knepley } 701812b8a6daSStefano Zampini 7019cc4c1da9SBarry Smith /*@ 70209f6c5813SMatthew 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. 70219f6c5813SMatthew G. Knepley 70220528010dSStefano Zampini Input Parameters: 70230528010dSStefano Zampini + tr - The `DMPlexTransform` 70240528010dSStefano Zampini - prefix - An options prefix, or NULL 70259f6c5813SMatthew G. Knepley 70269f6c5813SMatthew G. Knepley Output Parameter: 70279f6c5813SMatthew G. Knepley . dm - The `DM` 70289f6c5813SMatthew G. Knepley 70299f6c5813SMatthew G. Knepley Level: beginner 70309f6c5813SMatthew G. Knepley 703120f4b53cSBarry Smith Notes: 703220f4b53cSBarry 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. 703320f4b53cSBarry Smith 70349f6c5813SMatthew G. Knepley .seealso: `DMPlexCreateFromFile`, `DMPlexCreateFromDAG()`, `DMPlexCreateFromCellListPetsc()`, `DMPlexCreate()` 70359f6c5813SMatthew G. Knepley @*/ 70360528010dSStefano Zampini PetscErrorCode DMPlexCreateEphemeral(DMPlexTransform tr, const char prefix[], DM *dm) 70379f6c5813SMatthew G. Knepley { 70380528010dSStefano Zampini DM bdm, bcdm, cdm; 70390528010dSStefano Zampini Vec coordinates, coordinatesNew; 70400528010dSStefano Zampini PetscSection cs; 7041817b2c36SMatthew G. Knepley PetscInt cdim, Nl; 70429f6c5813SMatthew G. Knepley 70439f6c5813SMatthew G. Knepley PetscFunctionBegin; 70449f6c5813SMatthew G. Knepley PetscCall(DMCreate(PetscObjectComm((PetscObject)tr), dm)); 70459f6c5813SMatthew G. Knepley PetscCall(DMSetType(*dm, DMPLEX)); 70460528010dSStefano Zampini ((DM_Plex *)(*dm)->data)->interpolated = DMPLEX_INTERPOLATED_FULL; 70470528010dSStefano Zampini // Handle coordinates 70480528010dSStefano Zampini PetscCall(DMPlexTransformGetDM(tr, &bdm)); 7049817b2c36SMatthew G. Knepley PetscCall(DMPlexTransformSetDimensions(tr, bdm, *dm)); 7050817b2c36SMatthew G. Knepley PetscCall(DMGetCoordinateDim(*dm, &cdim)); 70510528010dSStefano Zampini PetscCall(DMGetCoordinateDM(bdm, &bcdm)); 70520528010dSStefano Zampini PetscCall(DMGetCoordinateDM(*dm, &cdm)); 70530528010dSStefano Zampini PetscCall(DMCopyDisc(bcdm, cdm)); 70540528010dSStefano Zampini PetscCall(DMGetLocalSection(cdm, &cs)); 70550528010dSStefano Zampini PetscCall(PetscSectionSetNumFields(cs, 1)); 70560528010dSStefano Zampini PetscCall(PetscSectionSetFieldComponents(cs, 0, cdim)); 70570528010dSStefano Zampini PetscCall(DMGetCoordinatesLocal(bdm, &coordinates)); 70580528010dSStefano Zampini PetscCall(VecDuplicate(coordinates, &coordinatesNew)); 70590528010dSStefano Zampini PetscCall(VecCopy(coordinates, coordinatesNew)); 70600528010dSStefano Zampini PetscCall(DMSetCoordinatesLocal(*dm, coordinatesNew)); 70610528010dSStefano Zampini PetscCall(VecDestroy(&coordinatesNew)); 70629f6c5813SMatthew G. Knepley 70639f6c5813SMatthew G. Knepley PetscCall(PetscObjectReference((PetscObject)tr)); 70649f6c5813SMatthew G. Knepley PetscCall(DMPlexTransformDestroy(&((DM_Plex *)(*dm)->data)->tr)); 70659f6c5813SMatthew G. Knepley ((DM_Plex *)(*dm)->data)->tr = tr; 70660528010dSStefano Zampini PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE)); 70670528010dSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, prefix)); 70680528010dSStefano Zampini PetscCall(DMSetFromOptions(*dm)); 70699f6c5813SMatthew G. Knepley 70709f6c5813SMatthew G. Knepley PetscCall(DMGetNumLabels(bdm, &Nl)); 70719f6c5813SMatthew G. Knepley for (PetscInt l = 0; l < Nl; ++l) { 70729f6c5813SMatthew G. Knepley DMLabel label, labelNew; 70739f6c5813SMatthew G. Knepley const char *lname; 70749f6c5813SMatthew G. Knepley PetscBool isDepth, isCellType; 70759f6c5813SMatthew G. Knepley 70769f6c5813SMatthew G. Knepley PetscCall(DMGetLabelName(bdm, l, &lname)); 70779f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 70789f6c5813SMatthew G. Knepley if (isDepth) continue; 70799f6c5813SMatthew G. Knepley PetscCall(PetscStrcmp(lname, "celltype", &isCellType)); 70809f6c5813SMatthew G. Knepley if (isCellType) continue; 70819f6c5813SMatthew G. Knepley PetscCall(DMCreateLabel(*dm, lname)); 70829f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(bdm, lname, &label)); 70839f6c5813SMatthew G. Knepley PetscCall(DMGetLabel(*dm, lname, &labelNew)); 70849f6c5813SMatthew G. Knepley PetscCall(DMLabelSetType(labelNew, DMLABELEPHEMERAL)); 70859f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetLabel(labelNew, label)); 70869f6c5813SMatthew G. Knepley PetscCall(DMLabelEphemeralSetTransform(labelNew, tr)); 70879f6c5813SMatthew G. Knepley PetscCall(DMLabelSetUp(labelNew)); 70889f6c5813SMatthew G. Knepley } 70893ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 70909f6c5813SMatthew G. Knepley } 7091